Closed jfrancos closed 3 years ago
Cache consisting of multiple layers - with optimistic layers that made up projection but are not actually applied. When designed optimistic operations were made typically short lived as they lifespan is usually couple seconds.
Persisting those is going to introduce number of challenges:
See also https://github.com/aerogear/offix/issues/118
Saving optimistic data would require changes in Apollo Client itself (to restore them) later so this is more like feature request
Hi Wojtek,
Thanks for that info. It sounds like you're saying there would be difficulty in persisting the data in each layer of the cache, and then restoring the data back to the specific layers that they came from.
Would it be correct to say though, that if I could figure out how to move the data from the short-lived optimistic response layer to the longer-lived cache layer, that cache-persist would then automatically persist and restore that data? I don't need optimistic data to be restored as optimistic data, I'd rather just figure out how to have optimistic data automatically move into the longer-lived layer.
I've tried doing this using useMutation's update
field, but this was confusing for me because with
update(cache, {data}) {
...
console.log(cache.extract())
//optimistic not set, should default to false
...
}
showing me the data that I'd just inserted via optimisticResponse
, it looked as thought the data I was trying to put in the longer-lived layer of the cache was already in the longer-lived layer of the cache.
Can you give me any hints as far as
optimisticResponse
short-lived data into the longer-lived data (so that cache-persist then does its thing with that data)If we apply changes to cache that is not representing state of server, we are hitting cache invalidation issue (from famous "there are two things hard in software.."
I have feeling that you are looking probably for something like WORA library done by @morrys. WORA applies changes first and then Devs need to reject them if error. Cache persist would be just one component to enable it.
Thanks for the feedback. I've been trying to do offline-first with @apollo/client + persistCache, retryLink, queueLink. Based on your comments, I'll see if I get further with offix, and I'll check out wora as well.
WORA would be more suitable for the case explained.
I've attempted to achieve offline-first support based on Apollo (& link family) about a year ago. I've somewhat achieved that following this article. It explains one approach on how to achieve restorable offline mutation with optimistic response support (and update handlers) at the end of the article.
I'd like to warn you about that approach though - as the app is getting bigger, maintaining everything in sync is a mess and requires a lot of boilerplate. As of today, I'd experiment with Offix, watermelonDB or WORA.
Thanks @wodCZ, I was looking at that article as well. I don't really understand what the pros and cons are in functionality in wora vs offix (@wtrocki can you comment on this?) but my thoughts on the three you mention:
As per wtrocki, offix may not be the right tool for me, but instinct says to at least try it out and see if I get further than with apollo + link family
Edit: I realized Wora has in fact been updated recently, just not in master.
I've ended up with some kind of Model - View - Controller architecture. I maintain a store (https://github.com/s-KaiNet/react-simple-hook-store) which the View (react) uses to render data and update the local copy using "actions". Point being, thorough the app I only work with the store, which is reliable and only source of truth. I don't use Apollo in my components. Then, the model (store) knows how to sync the local state with server - this is where queries and mutations are called. Finally the "controller" (plain JS classes) manages the model - restoring the state on app startup, triggering sync when the internet connection is restored etc.
As I'm writing this I realise how this sounds like overkill. I've came to conclusion that apps with read-only support are just fine with simple react + apollo + cache-persist approach, but at the moment you need read-and-write offline functionality, any attempts to abuse apollo cache for such support is not worth the hassle. I was a bit relieved when I saw wtrocki confirm my thoughts saying this:
If the app needs to be fully offline using the existing Apollo API to deliver offline is challenging as it wasn't designed to cover this case
Having the model separated from the view seems like clear way to work with fully offline apps. At least, I feel more confident about the app ever since I've rewritten the app 3 months ago.
In any case, I can't call myself an expert 😁 also, at the time, I didn't find Offix nor Wora - maybe they'd satisfy my needs.
I’m going to close this issue given the wealth of detail provided in the comments. I’d also like to add for such use-cases something like react-query
might be a solution to consider (if you’re not tied to the Apollo client and are using react).
I'm doing some exploring with apollo-cache-persist and apollo-link-queue. My mutations set an optimisticResponse, which, aside from apollo-cache-persist not persisting data when queueLink is closed, does seem to do what I expect:
cache
tab of Apollo Client DevtoolsI think that (but not 100% on) setting an optimisticResponse doesn't necessarily directly affect the cache even though it updates variables created with useQuery But
cache
tab of Apollo Client Devtools is actually in the cache, and not in this possible other place mentioned in the previous point.With the cache-persist
debug
option set totrue
, I do see a message about persisted data arrive in the appropriate moment, but it mentions storing only 2 characters of data ({}
).Again, the above is what I observe when queueLink is closed. When queueLink is open, cache-persist does work the way I expect (because it's coming from the server response), and gives a message about storing a larger, more appropriate number of characters.
Based on what I'm observing, it seems like either:
cache
tab of Apollo Client Devtools actually shows more than justcache
.Neither of which would be expected.
What am I doing wrong here? How can I persist data that winds up in the cache only in virtue of optimisticResponse, rather than coming from a server response?
Thanks so much!
Justin