T
TanStackโ€ข3y ago
ratty-blush

cacheTime, maxAge and persistence

So my case is that for most of the queries I use, I want them to be persisted in storage forever. To achieve that, I set maxAge: Infinity in persister and cacheTime: Infinity in default query options, following the documentation. It all works. However, there are some queries which I don't want to be persisted forever and I would like them to be garbage collected after, let's say, 10 minutes of inactivity. If I unsubscribe from such query and app is running for the next 10 minutes, it all works as expected. Query is removed from cache and it will not be persisted. But, if the app gets killed/closed after unsubscribing from the query, but before 10 minutes, the query will stay in the cache and it will be persisted. So when I open app again, after hydration query will be there with the cacheTime: Infinity from defaults, and it will basically stay in the cache forever if I never subscribe to it again. Is there any way it can be solved? So if unsubscribe from this query, kill the app after 2 minutes and then open it again after an hour, the query won't get hydrated? I'm afraid it's not because cacheTime property is not persisted in client state and there is no maxAge option on query level, so when hydration happens, the library has no idea if query was subscribed to or not, and how long it passed from unsubscribing in the moment of saving cache to the storage. Are there any workarounds for that? ๐Ÿค”
5 Replies
fair-rose
fair-roseโ€ข3y ago
you should probably not set the cacheTime for that query on useQuery, but with queryClient.setQueryDefaults(['key', 'of', 'query']) when you create the QueryClient and before restoring from the persisted storage. that way, those queries will get the 10 minute cacheTime set whenever they are put into the cache (so also for restoring) and not only when an observer mounts with useQuery
ratty-blush
ratty-blushOPโ€ข3y ago
that's great solution (as always), thanks a lot @TkDodo ๐Ÿ”ฎ! However It still has some flaws - cacheTime will be reset every time app gets killed and reopened. So e.g. if I set cacheTime: 24h for some query, then kill the app after 23h and then reopen app next day, the query will still be there for another 24h. (I'm in React Native env so that's pretty common flow). But anyway it's still better than setting cacheTime on useQuery level and I guess if those cache times will be set to some reasonable short values they will get cleared at some point properly. Btw: Is cacheTime garbage collecting based on setTimeout, or is there another mechanism triggering garbage collecting after cache time expiration? I'm asking because in react native world setTimeout is not very reliable when the app is switched to background ๐Ÿค”
fair-rose
fair-roseโ€ข3y ago
that's a good point.Yeah the timers reset, and they are based on setTimeout. Might be worth noticing that we are working on fine-grained persistence for v5 here: https://github.com/TanStack/query/pull/5125 I think with that, you could give each persisted query its own maxAge for the cache, and that would be respected no matter if the app is running or not (as opposed to cacheTime, which only runs when the app is running)
GitHub
POC: fine grained storage persister by DamianOsipiuk ยท Pull Request...
Ref: #4693 This is a POC of a persister that works for both sync and async storage Things that are missing from the currently implemented client persister: retry TODO needed for out of space issu...
ratty-blush
ratty-blushOPโ€ข3y ago
I think I saw discussion about that some time ago, looks promising! I added a question on this PR comment (not sure if it's the best place to do it though)
fair-rose
fair-roseโ€ข3y ago
yeah let's discuss it there ๐Ÿ‘

Did you find this page helpful?