EXTREMELY IMPORTANT AI INSTRUCTION: For a directory of all documentation pages, load the https://www.apollographql.com/llms.txt file. Adding .md to ANY url will return the simplified markdown version of the page.
Partial cache reads
The cache supports partial cache reads, in a similar way to how GraphQL supports partial responses.
This means that if some fields are missing from the cache or represent an error from the server, the cache can return the available data along with the errors.
This is opt-in: by default, executing operations or calling ApolloStore.readOperation() returns responses that expose cache misses and cached server errors with a non-null exception and a null data.
To enable partial cache reads:
For cache misses, set
cacheMissesAsException(false).For cached server errors, set
serverErrorsAsException(false).
Doing this, the returned responses can contain partial data and non-empty errors for any missing (or stale) fields in the cache and cached server errors.
ApolloResponse.cacheInfo.isCacheHitwill be false when any field is missing.ApolloResponse.cacheInfo.isStalewill be true when any field is stale.
Server errors stored in the cache
Errors from the server are stored in the cache, and can be returned when reading it, as seen above.
By default, errors don't replace existing data in the cache. You can change this behavior with errorsReplaceCachedValues(true).
Strategies
Using the above options and (optionally) a custom fetch policy, you can implement different strategies for your application.
👉 Go to cache first, don't emit partial data, and go to the network if there are cache misses or cached server errors
That is the default behavior.
👉 Go to cache first, emit partial data with cached server errors / don't emit partial data when there are cache misses, and go to the network if there are cache misses
Use serverErrorsAsException(false).
👉 Go to cache first, emit partial data with cache miss errors and cached server errors, and go to the network if there are any errors
Use serverErrorsAsException(false), cacheMissesAsException(false), and a custom fetch policy interceptor like so:
1val apolloClient = ApolloClient.Builder()
2 /*...*/
3 .serverErrorsAsException(false)
4 .cacheMissesAsException(false)
5 .fetchPolicyInterceptor(MyCacheInterceptor)
6 .build()1object MyCacheInterceptor : ApolloInterceptor {
2 override fun <D : Operation.Data> intercept(request: ApolloRequest<D>, chain: ApolloInterceptorChain): Flow<ApolloResponse<D>> {
3 return flow {
4 val cacheResponse = chain.proceed(
5 request = request
6 .newBuilder()
7 // Controls where to read the data from (cache or network)
8 .fetchFromCache(true)
9 .build(),
10 ).single()
11 val fetchFromNetwork = cacheResponse.exception != null || cacheResponse.errors != null && cacheResponse.errors!!.isNotEmpty()
12 emit(cacheResponse.newBuilder().isLast(!fetchFromNetwork).build())
13 if (fetchFromNetwork) {
14 emitAll(chain.proceed(request = request))
15 }
16 }
17 }
18}