Francismiko
Francismiko2y ago

Better implementation of automated optimistic updates

When I implemented optimistic updates on my mutation functions, I found it difficult to reuse the common parts. And I had to implement it through the API withOptimisticUpdate. I'm using React & Next.js
8 Replies
Francismiko
FrancismikoOP2y ago
I very much hope to have a simple API, similar to: onOptimisticUpdate or offOptimisticUpdate to make it easier for me to implement some automation control logic on the front end. Any better suggestions? Or can I define an optimistic update function in the convex backend first, and then call it through a hook in the front end?
ballingt
ballingt2y ago
I hear you on it being difficult to build a catalog of optimistic update functions. Could you say more about what you want instead? If you want to know when the update has succeeded, the promise returned from the mutation may help (is that what offOptimisticUpdate would do?) You can define the optimistic update anywhere (re: "in the convex backend first" but it's code that runs on the client. Are you saying you'd like to define it next to the definition?
Michal Srb
Michal Srb2y ago
Something we've considered is defining the optimistic updates as tied to a mutation, not a call to a mutation. Along the lines of:
const optimisticUpdates = {
"myMutationFoo": (localStore, args) => ....
}

const convex = new ConvexReactClient(address, {optimisticUpdates});
const optimisticUpdates = {
"myMutationFoo": (localStore, args) => ....
}

const convex = new ConvexReactClient(address, {optimisticUpdates});
Would something like this work for you and make this better or not?
whoami
whoami2y ago
I was thinking if we can design the optimistic update such that we can just enable / disable it with a boolean variable as most of the time there is no conflict resolution, for example we can just automatically find all the queries that may be impacted by the mutation and inject the local storage piece of the code for it? is this something that is possible to be implemented?
ian
ian2y ago
The challenge is that each query could be fetching a different subset of results and combining them in different ways, and it’s unclear how to cleanly combine local results with a new or modified value. If you normalized your values and stored them all in a unified store client-side, you could do some things automatically, but that would be a subset of what’s supported by Convex
whoami
whoami2y ago
I am not sure, I imagine the atomic mutation can be propagated to whatever queries that was using them (just like how the reactivity is implemented in convex, but in a local copy of it), if you have all the mutation, queries and db connected as a graph the propagation logic will be clearer (mutation -> db -> query), and such helper function can be built in compile time, and it will be used when I call useMutation('...').withOptimisticUpdate(), this would cover most optimistic update cases unless it requires CRDT like conflict resolution
ian
ian2y ago
One hitch is your mutations & queries could be reading & writing to documents that are never surfaced to the client (and in some cases are intentionally not on the client), and generally not all records that influence the return of a query are available on the client at the time the mutation executes, so it's generally not possible to replay the server logic there. You also generally don't want to ship your server logic to the client if it's using env variables or other secret info. So I believe the design space for the fully-automated optimistic updates is limited to CRUD-style / normalized stores. Does that make sense / am I understanding your proposal right?
whoami
whoami2y ago
I understand your concern now, maybe we can figure out a way to get away from these corner cases? Or maybe in the parameters of withOptimisticUpdates , we can select which queries can be synced in a local first manner automatically and warn users what might be the consequences of it (if I used a secret in an query most likely that involves some external fetch which makes it impossible to mock in the frontend anyways)

Did you find this page helpful?