We are playing with the normalized cache on both iOS and Android and we can’t seem to understand when the SQLite cache expires and how we can set a custom expiration time for it.
The use case is the following: if I make a query to fetch a user with a specific ID and this user gets cached on the normalized SQLite cache, for how long will this user be cached?
If there is a change to the user object on the back end, for example a new profile picture, how can I be sure that after a while the SQLite cache will expire and the new changes for the user will be fetched?
I know that I can invalidate manually the entire SQLite cache but this doesn’t seem right to me, because I would expect that every entry should expire after a custom time.
What is the suggested way to deal with this and what’s the purpose of the SQLite cache if it is not possible to set a custom expiration time per entry/object?
At least on Apollo Kotlin for now there is no expiration mechanism on the SQLite cache. We’re aware it’s missing and it is on the roadmap (along with other cache improvements!). Here is an issue tracking this and don’t hesitate to comment on it if you have feedback!
In the meantime I think one way to refresh data selectively could be to keep track of when a specific query was made from the network last time, and adjust the FetchPolicy accordingly. Currently this would be manual / custom logic.
Hi @Benoit_Lubek, thank you for the answer. I’m also interested in the topic of cache expiration.
I have a couple of questions regarding the MemoryCache:
I see that this cache has a expireAfterMillis parameter: is the time calculated independently for every entry? I guess it is, but I’d like a confirmation
I’m chaining multiple caches as suggested here: what happens if the memory cache has a value but it’s expired? Will fall back to the SQL cache or will go straight to the network call? I guess it will fall back but, again, I’d like a confirmation.
Am I wrong or the SQL cache is pretty much useless for content that changes over time?
You guessed correctly . If will fallback to the next cache in the chain first (and then go to network, depending on the FetchPolicy)
I wouldn’t say the SQL cache is useless even though it’s true that eviction/expiration must be done manually at the moment. For instance one use-case that the persisted cache helps is the CacheAndNetwork policy (introduced in 3.1.0), which allows the UI to display the latest known data from the cache, while the fresh one is being fetched from the network.
We are playing with the normalized cache on both iOS and Android and we can’t seem to understand when the SQLite cache expires and how we can set a custom expiration time for it.
The cache implementation on iOS is very naive and simple so unfortunately there is no concept of automatic cache expiration yet. The caching API on apollo-ios does allow you to invalidate the entire cache, which it seems you are already aware of, and v0.45.0 introduced the removeRecords(matching:) API which you can use to target specific cached objects. This will require you to know the cache key mechanism to use effectively though.
how can I be sure that after a while the SQLite cache will expire and the new changes for the user will be fetched?
The answer to this question I think depends on the cache policy you use in requests. The documentation I linked to explains the options pretty well and you might need to combine one of those with manual cache manipulation depending on your use case.
It won’t always be this way though. Right now we’re focused on the first major release (v1.0) of apollo-ios which overhauls code generation to be Swift-based; Alpha 1 was released last week and Alpha 2 should be available soon. The plan after v1.0 is a modernization of the network stack for v2.0 and a major revision to caching in v3.0.