restatedev / sdk-typescript

Restate SDK for JavaScript/Typescript
MIT License
46 stars 8 forks source link

Allow updating the entire key value store at once #412

Open PfisterFactor opened 2 months ago

PfisterFactor commented 2 months ago

There is an issue I run into with having a typed context.

Say I have a type like:

interface Lead {
    Status: "NONEXISTANT";
} |
{
    Status: "ACTIVE",
    Details: {
        SomeField: number,
        SomeOtherField: string
    };
}

And my context looks like:

ctx: restate.ObjectContext<Lead>

Currently there is no typesafe way for me to update the key value store. This is annoying when trying to implement a state-machine pattern for the key value store.

Example:

ctx.set("Status", "ACTIVE"); // Context is now in non-typesafe state because Details doesn't exist
ctx.set("Details", ...) // Get a type error because Details field isn't present when Status is "NONEXISTANT"

If we were to introduce some method to update the entire key/value state at once, we can resolve this. It would be akin to a map operation.

await ctx.update((oldState) => {
    return {
        Status: "ACTIVE",
        Details: {
            SomeField: 1,
            SomeOtherField: "hello"
        }
    }
} // All fields are updated atomically and type safety is preserved
mupperton commented 2 months ago

Could you not achieve the same thing with the following:

interface State {
    Lead: {
        Status: "NONEXISTANT"
    } |
    {
        Status: "ACTIVE"
        Details: {
            SomeField: number
            SomeOtherField: string
    }
    }
}

const handler = async (ctx: restate.ObjectContext<State>) => {
    const oldState = await ctx.get("Lead") // typed: Lead | null

    ctx.set("Lead", {
        Status: "ACTIVE",
        Details: {
            SomeField: 1,
            SomeOtherField: "hello",
        },
    })
}
PfisterFactor commented 1 month ago

Sure - but now we have to nest it arbitrarily. Plus the issue remains that you can't atomically update one or more fields within the context store at the first level