Skip to content

Inquiry/Suggestion concerning ext/kv atomic() and .get() #20380

@cfjello

Description

@cfjello

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions