Skip to content
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

Cache went stale and wasn't recreated - explanation #168

Open
theobat opened this issue Jul 4, 2017 · 3 comments
Open

Cache went stale and wasn't recreated - explanation #168

theobat opened this issue Jul 4, 2017 · 3 comments

Comments

@theobat
Copy link
Contributor

theobat commented Jul 4, 2017

So I experienced the issue pointed out by @dustinfarris, the culprit is here.

The reason why this "invalidation" cause the "cache went stale..." exception is that the flushDependencies function essentially walk the path of denormalizedDeps and find all the dependencies in common with the denormalized response of the server. Then for all the ops(key) in denormalizedDeps, it removes the response in cachedResponse.
Practically speaking, if I have thingA, thingB fetched by getAB and thingD, thingC fetched by getDC, and if A and D are owned by personA (thing and person beeing graphql Types) then we'll have an issue if:

  • we already called getAB
  • then we call getDC => getAB is now "invalidated" the hard way (no response, without refetch)
  • and then if getAB had a mutation handler for a mutation that we trigger at this point, we'll get the "cache went stale.." thing.

@mattkrick I know you don't have time these days, but perhaps a small hint as to why the flush dependencies is important and more specifically why not:

  • refetching there instead of removing the responses (a short and simple attempt gave me infinite loops).
  • In the exemple that I give above, I don't see why anyone would want to invalidate query getAB simply based on the fact the it shares information that the server just returned. Why can't we just remove the "stale" information from query getAB and replace it (but just the common ground) by information getDC...?

I can see numerous solutions to this issue but I don't use subscriptions yet and I'd like to make a fix that maintain the subscriptions part unchanged (if there's no bug there of course).

@mattkrick
Copy link
Owner

a dependency links the op (usually your viewmodel container) to the model. without flushing deps, your app won't ever know what got updated, and could update when one isn't required.

is your mutationhandler referencing all the ops that it will mutate? if not, that's usually how it goes stale (the mutation updates the underlying data, but the query hasn't been updated by the mutation).

the cachedResponse will always get removed if any of the underlying doc fields get changed. if we didn't cache, then the object would get recreated every time dispatch got called.

@theobat
Copy link
Contributor Author

theobat commented Jul 4, 2017

is your mutationhandler referencing all the ops that it will mutate? if not, that's usually how it goes stale (the mutation updates the underlying data, but the query hasn't been updated by the mutation).

Well the thing is I don't use mutation as a mean to return data in this case, I only use the invalidate function in the mutationHandler (which by the way is not working on master, and I made a PR to solve that, the 'this' keyword does not refer to the singleton which means this._willInvalidate... is never set to true).
This is brutal in a sense, but should get the job done while I work on better mutation handling.

the cachedResponse will always get removed if any of the underlying doc fields get changed. if we didn't cache, then the object would get recreated every time dispatch got called.

So the flushDependencies function removes the cachedResponse of a query that just fired... Meaning that if I query a list of post, get into a post detail view (so the list is not "observed" anymore it's in a different view) modify this post with a mutation that triggers a mutationHandler on the list query, it will trigger the exception (no matter what this mutationHandler does btw, since this happens after the exception). Will try to isolate a test case for you to grasp what's going on.

@mattkrick
Copy link
Owner

yeah, an example might be good. whenever dispatch is called, all the invalidated queries will get recalculated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants