-
Notifications
You must be signed in to change notification settings - Fork 5.9k
Description
The following bit of code generates a sequence number:
async function getIdentity(): Promise<Deno.KvU64> {
const key = ['sequence', 'processId']
await kv.atomic()
.mutate({
type: "sum",
key: key,
value: new Deno.KvU64(1n),
})
.commit()
const val = await kv.get(key)
return Promise.resolve( val.value as Deno.KvU64 )
}
In a Deno Deploy environment, when shared between multiple distributed processes, I do not think that this code is tranaction-safe. Due the the detached async kv.get() call you may not get what you mutated. To be safe, the .commit() operation should return the mutated value, in effect meaning that the commit() operation should have a added value field:
async function getIdentity(): Promise<Deno.KvU64> {
const key = ['sequence', 'processId']
const commitReturningValue await kv.atomic()
.mutate({
type: "sum",
key: key,
value: new Deno.KvU64(1n),
})
.commit()
return Promise.resolve( commitReturningValue.value as Deno.KvU64 )
}
const ret = getIdentity()
if ( ret.ok && ret.value !== null ) console.log( ret?.value.toString() )
It would, in my opinion, be even better if kv.atomic would allow for one (or even more) .get methods, that could denote what to return when committing the kv.atomic operations:
async function getIdentity(): Promise<Deno.KvU64> {
const key = ['sequence', 'processId']
const commitReturningValue await kv.atomic()
.mutate({
type: "sum",
key: key,
value: new Deno.KvU64(1n),
})
.get(key)
.commit()
return Promise.resolve( commitReturningValue.value as Deno.KvU64 )
}
I have noticed that .commit() seems to return the versionstamp of the mutated record, even though this may not be an actual feature/rule, so one solution to the above (and a fantastic feature in general) would be to allow the generic get() call options to specify a specific versionstamp for the key that you want to fetch.