Changefeeds (watching and getting updates on ranges of keys)

There’s a few pieces to the answer to your question, and let’s start off with single key watches before expanding out into range watches.

The contract of a watch is that if the value of the key being watched permanently changes from the supplied value when watch is called at a version later than when the watch was set, then the watch will be triggered. What you appear to be asking for (or expecting) is a contract that if the value is modified, then the watch fires. The difference in implementation between these two is if version history is required.

Watches become complicated in what to do if a client goes away for a while, and then tries to resume its watch. If the system doesn’t know if any changes occurred on the watched key in the version range the client is interested in, then it has two options: trigger the watch or not. The former leads to systems that promise watches “will notify you if one or more changes might have happened”, versus the latter, where FDB is trying to promise “will notify you when a change definitely has happened”. FDB can get into a situation where it doesn’t know if a change happened between when a client started the watch and now because it only maintains 5 seconds of version history. It appears that RethinkDB’s change feeds are an example of the former, as if you’re “connected” then you get streamed notifications, but they make no guarantees of delivery. FDB watches guarantee delivery in a sense, as under failure, the watch will retry, and “eventually” you’ll be notified that a modification happened.

Suppose that we had a storage engine that could maintain, for any key, the most recent version at which it was modified. Then we would be able to support a watch of the form “notify me when key X was modified at a version later than Y”, as at any point we’d be able to know if a modification happened in that range by reading the key. Extending the watch to a range still presents a complication: knowing if a key was modified between a starting version and now for a client that’s missed version updates means a range read of the entire range, to see if there’s any key that’s been updated more recently. That’d be a somewhat expensive operation to be happening transparently, possibly by multiple clients, and particularly for watches that span a lot of data.

I do think it’s worth revisiting our watch API, particularly if we ever gain a natively MVCC storage engine. It’s possible that we’d downgrade our watch API’s contract to allow triggering the watch even if we’re unsure that any change happened, but I kind of like the current “it either happened or it didn’t” API…

1 Like