SET_VERSIONSTAMPED_KEY and READ_YOUR_WRITES_DISABLE

Hi!

I am trying to use the Java bindings to implement a sort of layer where I plan to use SET_VERSIONSTAMPED_KEY extensively in order to maintain historical information. My plan is to write keys consisting of a prefix and versionstamp, and use a reverse range read of keys starting with that prefix in order to find the ‘most recent’ value for the prefix.

Side note: is there a good way to do a reverse range read that is inclusive of the lexicographically-last (first returned) key?

Of course my first try failed due to the obvious attempt to read an unreadable key. However after I called setReadYourWritesDisable it started working! Then, while reading the documentation for the C API, I noticed it says of FDB_MUTATION_TYPE_SET_VERSIONSTAMPED_KEY:

This operation is not compatible with the READ_YOUR_WRITES_DISABLE transaction option and will generate an error if used with it.

So I am confused! Is there actually a problem with my approach that I have not yet run into, or is the documentation wrong or somehow not applicable here?

I attempted to do a little digging, but I didn’t find any history of this case being an error exactly (though there was a time when disabling read your writes skipped some needed validation). Further, from looking at the code it seems that there is an intentional nod to the idea that this mutation could be used without read your writes.

I’ve raised Inconsistency between documentation and code for setting versionstamped key without read your writes · Issue #1685 · apple/foundationdb · GitHub in order that the answer here gets tracked down and fixed (either in documentation or code).

Yes, you can do this by specifying the end of your range to be the key after the one you want. This is true when reading forward or in reverse.

One way you can do this is by using key selectors. In Java, for example, you could use KeySelector.firstGreaterThan(inclusiveEndKey) as the end of your range. Alternatively, you could construct an end key yourself by adding a null byte to the end of your inclusive end key. For example, if you wanted the last key in the results to be foo, you could specify the end of your range as foo\x00.

Thanks for filing! I actually phrased that too vaguely, I wanted to find the last key that starts with a particular prefix. For this I found ByteArrayUtil.strinc to be very useful!