reactjs - Apollo mutation debounce and race conditions -
(this follow https://github.com/apollographql/apollo-client/issues/1886)
i'm trying build text input update value user types.
first attempt
i first tried use optimisticresponse
update local cache user types. works, except fires off mutation on every key stroke. aside flooding network requests, there problem of inconsistency of network. it's possible last mutation arrive first, , first mutation arrive last. results in server ending stale value. here example of race condition:
type: mutate request: type: b mutate request: ab arrives on server: ab arrives on server:
now server has recorded "a" in graphql, incorrect.
adding debounce
to alleviate this, added debounce keypress event. although race conditions described above, doesn't solve it. it's still possible have race condition if network slower debounce threshold.
because we're debouncing text input, need introduce local state react component updates user types (as @jbaxleyiii suggested in github issue). our state lives in 2 place (the component state , apollo cache).
a big problem component won't update when receives new props. eg. when graphql gets updated , pushes client.
adding network queue
because debounce doesn't solve race condition, added network queue (in addition debounce) manage mutation requests make sure there ever 1 mutation in flight @ time. if receives mutation request while there 1 in flight, queue fired when first 1 comes back. if there mutation queued, discard , replace new 1 (there can ever 1 item in queue @ time). here's example:
type: send mutate request: type: b queues mutate request: ab << wait send until "a" comes type: c replaces queued request: abc << discard queued request "ab", it's old response server: send mutate request: abc << send queued mutation , clear queue response server: abc
this guarantees won't have race condition (at lease client...)
there problem approach though. optimisticresponse
update when mutation goes out. if mutation in flight, need wait network return before update optimisicrespose
gets applied. time long time on slow networks. so, in example above, can't use optimisticresponse
update "abc" until "send mutate request: abc".
this isn't huge deal, delay, seems should able do.
attempt update cache user types
in docs, learned can use withapollo
access client, , update cache user types via writequery
. replaces need optimisticresponse
. however, problem arises when when old response comes , updates cache out under us. here's example:
action | cache -------------------------+------------ type: | mutate request: | type: b | ab queues request: ab | ab response server: | << oh no! mutate request: ab | << we're not using optimisticresponse anymore ... network time ... | response server: ab | ab
i suppose can use client.writequery
update cache user types and optimisticresponse
update when mutate request fires, code getting pretty hard follow.
there might way deal in update
function, haven't gone far.
help?
i'm pretty new apollo maybe i'm missing something. there better way handle many rapid mutations in apollo?
each mutation returns promise, know when out-of-order mutation arrives, keeping track of latest one.
since accept user types, means user's value canonical one, , don't need optimistic response. you're doing making sure server has same value do.
so i'd propose track input in redux , add store listener fires off mutation (with debounce).
if need keep track of server value, use counter see if mutation returned last 1 (store ++counter value @ mutation send, , compare value counter value on mutation return).
Comments
Post a Comment