Use Same Versionstamp in Multiple Subspaces

Is it possible to use the same Versionstamp in multiple subspaces within the same transaction? I’m using the Java bindings and was attempting to use Versionstamp as the key in one subspace and as part of a value in another subspace.

Yes, you can set a versionstamp multiple times in the same transaction. A versionstamp consists of 2 (or 3) components - an 8 byte commit version, a 2 byte transaction serialization order number within the commit version, and when using versionstamps within Tuples (currently Python and Java only), a 2 byte user version that you can specify yourself.

The commit version and serialization order number are fixed for the transaction and all of your versionstamps within a transaction will always have the same value for these components.

If you are using versionstamps as part of a key within a Subspace, then you must use the Tuple layer versionstamp support (https://apple.github.io/foundationdb/api-python.html#module-fdb.tuple), meaning you can only do so within Python or Java. If you want your value to have the same versionstamp as the key, you can use the Tuple layer for the value as well and specify the same user version for both. Alternatively, you could just look at the first 10 bytes of the key’s versionstamp and ignore the final two bytes (perhaps always setting the user version to the default value of 0).

Thanks for the reply. I was able to verify it with the test below. Now I need to go back to my original code and see where my mistake was when I initially attempted this.

@Test
public void usingSameVersionstampMultipleTimesTest() {
    FDB fdb = FDB.selectAPIVersion(520);
    try (Database db = fdb.open()) {
        DirectorySubspace directorySubspace = createEventStoreSubspace(db);

        Subspace subspaceOne = directorySubspace.subspace(Tuple.from("1"));
        Subspace subspaceTwo = directorySubspace.subspace(Tuple.from("2"));

        db.run(tr -> {
            try {
                Versionstamp versionstamp = Versionstamp.incomplete(1);
                Tuple t = Tuple.from(versionstamp);

                tr.mutate(MutationType.SET_VERSIONSTAMPED_KEY, subspaceOne.packWithVersionstamp(t), Tuple.from("subspace One value").pack());
                tr.mutate(MutationType.SET_VERSIONSTAMPED_VALUE, subspaceTwo.subspace(Tuple.from("subspace2 key")).pack(), Tuple.from("subspace2FirstValue", versionstamp).packWithVersionstamp());

            } catch (Exception ex) {
                System.out.println(ex);
            }

            return null;
        });


        db.read(tr -> {
            try {
                KeyValue subspaceOneKeyValue = tr.getRange(subspaceOne.range(), 1, false).asList().get().get(0);
                KeyValue subspaceTwoKeyValue = tr.getRange(subspaceTwo.range(), 1, false).asList().get().get(0);

                System.out.println("subspaceOne key: " + subspaceOne.unpack(subspaceOneKeyValue.getKey()));
                System.out.println("subspaceTwo value: " + Tuple.fromBytes(subspaceTwoKeyValue.getValue()));

                assertEquals(subspaceOne.unpack(subspaceOneKeyValue.getKey()).getVersionstamp(0), Tuple.fromBytes(subspaceTwoKeyValue.getValue()).getVersionstamp(1));

            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }

            return null;
        });
    }
}