Hm, the right solution to this kind of depends on the semantics you want from this key.
There’s more on how to use read and write conflicts in @gaurav’s answer, but I think it might be worth considering the requirements here and seeing if there’s a better way.
Unfortunately, there’s not a great way to get exactly what you want from FDB if you require a key that produces a (1) unique value you can read during the course of the transaction that (2) monotonically increases by 1 each time it is written and (3) is scalable (i.e., supports concurrent operations). I think you can get any 2 of those 3. (I think you actually can get all three if you try really hard, but it requires maybe more write-amp then you’d like and more specialized logic.)
If you want (1) and (2), you can just read the key, increment its value by one, and then write it back to the database. Then when the transaction commits, the resolver checks that no one else has written that key since that transaction read it (unless one uses snapshot isolation level), so as long as your transaction commits, it is guaranteed that you got a unique value (and if it doesn’t commit, then it’s like it never happened). However, by its very nature, this means that no two transactions can operate at the same time, as they will conflict on this key.
If you want (2) and (3), you can use the atomic ADD operation: https://godoc.org/github.com/apple/foundationdb/bindings/go/src/fdb#Transaction.Add When the transaction commits, it will increment whatever value is currently stored in the database at the given key by the passed parameter (so, you could pass it 1). Then the value of the key will essentially be equal to the number of times it’s been written to. However, the write is entirely blind, and you don’t have access to the value of that key before the update (and after the update, it might have been updated by other transactions). The Record Layer uses this to maintain, for example, and index of how many records are in a database, and it works well for that, but it doesn’t work if you need the value back.
If you want (1) and (3), you can use versionstamp operations. See: https://godoc.org/github.com/apple/foundationdb/bindings/go/src/fdb#Transaction.SetVersionstampedKey and https://godoc.org/github.com/apple/foundationdb/bindings/go/src/fdb#Transaction.SetVersionstampedValue Those operations let you write the database’s commit version (with some other disambiguating bytes) into the database. This value is guaranteed to be unique for each transaction, and it is monotonically increasing (though not by 1 each time; it can go up essentially an arbitrary amount between transactions), and though you can’t inspect this value while the transaction is ongoing, you can get the value after the transaction completes, and you can use those two methods to write the value of the versionstamp into database keys and values.
There is, kind of, a way you could make this work by combining a few of these methods. For example, one can do something like with each operation, write a value (using a version stamped key) that essentially writes an item into a queue. This produces a universally agreed upon ordering. Then, one reads the value of some global counter key, and then assign a counter value to each transaction based on its order in that queue. However, this is probably more work than its worth, and it leads to a fair amount of overhead maintaining this queue.