erquhart
erquhart2y ago

Action optimistic updates

Any plans to make optimistic updates work with actions?
5 Replies
ian
ian2y ago
Just to understand what behavior you want, let's say you have an action A:
export const A = action(...{
runMutation(api.m.B);
// some long fetch call
runMutation(api.m.C);
});
export const A = action(...{
runMutation(api.m.B);
// some long fetch call
runMutation(api.m.C);
});
If you were to have an optimistic update on A, would you want to have the modifications to query results persist until: 1. The modifications from B are reflected in queries 2. The modifications from C are reflected in queries 3. The action finishes from the POV of the client fyi: Actions aren't serialized in the same queue as queries & mutations, so you can run multiple in parallel. Before an action finishes, you can see results from the action (which is useful for updating the progress in long actions). Depending on use-cases, I could imagine wanting 1, 2, or 3. For (3), which is what I do for convenience, you could do something client-side, like:
setIsLoading(true);
try {
await myAction(params);
} finally {
setIsLoading(false);
}
setIsLoading(true);
try {
await myAction(params);
} finally {
setIsLoading(false);
}
where setIsLoading could set other data in a store, etc. It's theoretically possible for the action to resolve before the query is updated, but in practice I haven't had an issue with this. The pattern I prefer for these long actions is to: 1. Run a mutation that inserts a document that the action will update, and return that document ID to the client. I'd hang optimistic updates on this mutation. 2. Have the mutation schedule an action, passing in the document ID. 3. Have the action update the document after it runs the expensive operation. 4. Have the UI show that the document is loading until the updated document comes down. There isn't a direct connection between the action & frontend, but the effect of the action is seen through query data updating.
erquhart
erquhartOP2y ago
Yeah I'm focused on just the overall outcome of the action. I ended up with what you laid out at the end there, except I have the client calling the action after the mutation because I didn't realize mutations could schedule actions - going to check the docs on that now. Option 3 from your first message feels the most idiomatic, but that's just at first blush. Oh you mean scheduled functions, I hadn't even considered that
ian
ian2y ago
Yeah it’s a bit indirect: scheduler.runAfter(0
sshader
sshader2y ago
Yeah personally I’d recommend what Ian’s suggesting with scheduling the action. We have very few guarantees on actions (they can run out of order, run for several minutes, fail part way through) that make it harder to offer optimistic updates — e.g. having an optimistic update for an action that takes multiple minutes might mean the client doesn’t show any other updates for multiple minutes
erquhart
erquhartOP2y ago
Yeah that's fair

Did you find this page helpful?