-
-
Notifications
You must be signed in to change notification settings - Fork 454
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optimistic Updates not Writing to Cache when offline #1042
Comments
@JohnAtFenestra Maybe if you create a REPL with CodeSandBox they can try and understand better. 😃 |
So there are a couple of things I want to unwrap because this isn’t quite listing expected/actual behaviour which may help explain this:
The last point is important because you’d never want optimistic results to be stored permanently. Instead when you reload/restart your app it will retry all mutations that failed while you were offline which will reapply the optimistic updates. So if you’re looking at your query data for debugging, it’s important not to look for optimistic data in your storage because that’s where it shouldn’t be, but instead at the actual query results from the |
Now I'm getting more confused. So, if I have an application which is offline, the changes are only stored in transient memory? Nothing stores the changes to storage? I'm asking because that would blow our use case out of the water. We're running a PWA which will be used offline in schools and then reactivated later in the day to allow the mutations to be written to the GraphQL server. |
@JohnAtFenestra that may still work. But instead the mutation operations are what's stored in your storage and not the changes to the actual data, since the optimistic updates can always be regenerated from scratch |
So, following scenario: Goes offline I can test it but it takes a while to get everything running. I'm hoping you just know off the top of your head. |
@JohnAtFenestra This is the same question I had in my head. Thanks. |
Yes that should work, the thing is that when that one tab is running we don't have a way to sync to the other tab yet. Continuously writing to the storage would impose serious perf concerns. |
Actually, it doesn't work. I just tried it (after setting up local https certificates). Loads the rehydrated data from the cache but no updates are run from the metadata. |
And now, I'm getting the same intermittent issue - once I try a mutation while offline, once I go back online nothing hits the network again. No errors but the debugExchange shows it's hitting only the cache. As a result, none of the mutations are hitting the GraphQL server. I have to do a page reload to get the queries to work again. |
Addendum. If I recreate the client, I can get queries to work. Apparently something is happening which causes the fetchExchange to not be called once the browser goes back online until the client is recreated. |
Are the appropriate listeners firing correctly? Your onOnline event,... After reading the metadata it flushes the queue or when the onOnline from your storage triggers: https://github.com/FormidableLabs/urql/blob/685300cfaf5649edf283163fe62fddf3777ec7b1/exchanges/graphcache/src/offlineExchange.ts#L124-L125 |
The only thing I can think of is that I've found a case which puts the fetchExchange into an unstable state. No errors are generated but it's hung up so that the only thing which can run is the cache part of |
I found part of the problem. In this.reexecuteOperation = (operation: Operation) => {
// Reexecute operation only if any subscribers are still subscribed to the
// operation's exchange results
if (
operation.operationName === 'mutation' ||
(this.activeOperations[operation.key] || 0) > 0
) {
this.queue.push(operation);
if (!isOperationBatchActive) {
Promise.resolve().then(this.dispatchOperation);
}
}
}; I did a debug trace and discovered that this.activeOperations is an empty object. |
Yes, that's correct; queries are only going to fetch when they're active, related to what I was talking about in that other comment about subscriptions. But the same doesn't apply to mutations. However in your code I can see that that doesn't have that fix yet. So basically we pushed out a fix for Graphcache and as part of that I switched over Have you checked that you're on |
Yes. I did a yarn list --pattern urql to get the list from the beginning. ├─ @urql/[email protected] If there is a new fix I can download from npm fairly quickly, that would be good (has to be npm because we run our builds on a server). BTW, the code I posted is from the most current GitHub pull. I'm mapping out an alternative approach, which is to intercept mutation calls at the client proxy and handle them myself if we're offline. Our use case is pretty different than most as I'll have to update the storage data (essential due to the high probability of the person turning their device off and on again all offline). But, I've learned enough over the past week that I'm confident I can implement something which will work. |
@JohnAtFenestra That's really odd! If you check this build of Are there maybe some weird cached build shenanigans going on? |
Very odd. I'll whack node_modules and reload. |
Very weird. From what I can tell, the only line affected is the absence of the mutation check. And this is after whacking everything possible including a purge of all cached information. Oh, and the mutations are still not running for some reason and after that, none of the queries will hit the network. It's very odd.
this.dispatchOperation = function(a) {
m = !0;
for (a && p(a); a = c.queue.shift(); ) {
p(a);
}
m = !1;
};
this.reexecuteOperation = function(a) {
0 < (c.activeOperations[a.key] || 0) && (c.queue.push(a), m || Promise.resolve().then(c.dispatchOperation));
};
a = X(void 0 !== a.exchanges ? a.exchanges : Y);
this.dispatchOperation = function(a) {
m = !0;
for (a && p(a); a = c.queue.shift(); ) {
p(a);
}
m = !1;
};
this.reexecuteOperation = function(a) {
if ("mutation" === a.operationName || 0 < (c.activeOperations[a.key] || 0)) {
c.queue.push(a), m || Promise.resolve().then(c.dispatchOperation);
}
};
a = X(void 0 !== a.exchanges ? a.exchanges : Y); |
So first of all; I'm closing this since so far this has been expected behaviour and other usage quirks 😅 Anyway, I'd say this is something that will somehow relate to your local setup. I do not know how or what, but if you've checked the source and it says what you expect it to say, you've checked the installation and you have no older duplicate of I'd definitely check the source of my build output for |
├─ @urql/[email protected]
├─ @urql/[email protected]
├─ @urql/[email protected]
└─ @urql/[email protected]
Found this while testing offline mode. When I run a mutation with an optimistic update in online mode:
The result is that the pong mutation update is called twice, once with
info.optimistic
as true, followed byinfo.optimistic
as false.The call to
cache.updateQuery
fires off only afterExchange debug
shows the operation has been completed.When I carry out a mutation with the browser set to offline, however, when the optimistic flag is true, nothing is written to the cache:
Resulting in the absence of the newly added M6 mutation:
Have I discovered an edge case bug or is this expected behavior?
The text was updated successfully, but these errors were encountered: