Open kapilsukhyani opened 5 months ago
Hi 👋
Can you share how you're setting up the HTTP cache?
DiskLruCache
accesses are synchronized so I would expect that part to write concurrently as long as it's the same instance of DiskLruCache
being used.
Here is what it looks like
@[Provides AccountScope]
fun provideApolloClient(
site: Site,
@Authenticated okHttpClient: OkHttpClient,
@CacheDir cacheDir: File,
@SentryApolloIntegration sentryApolloIntegration: Boolean,
): ApolloClient {
return buildApolloClient(
site.graphQLUrl,
okHttpClient,
cacheDir
ApolloBreadcrumbInterceptor("cc-gql"),
sentryApolloIntegration = sentryApolloIntegration,
)
}
@[Provides AccountScope Agg]
fun provideAggApolloClient(
site: Site,
@Authenticated okHttpClient: OkHttpClient,
@CacheDir cacheDir: File,
@SentryApolloIntegration sentryApolloIntegration: Boolean,
): ApolloClient {
return buildApolloClient(
site.aggGraphQLUrl,
okHttpClient,
cacheDir,
ApolloBreadcrumbInterceptor("AGG"),
sentryApolloIntegration = sentryApolloIntegration,
)
}
@[Provides CacheDir]
fun provideCacheDir(application: Application): File = application.cacheDir
fun buildApolloClient(
graphQLUrl: HttpUrl,
okHttpClient: OkHttpClient,
cacheDir: File
interceptor: ApolloInterceptor,
sentryApolloIntegration: Boolean = false,
additionalInterceptors: List<ApolloInterceptor> = emptyList()
): ApolloClient {
val builder = ApolloClient.Builder()
.serverUrl(graphQLUrl.toString())
.httpCache(File(cacheDir, "apolloCache"), HTTP_CACHE_SIZE)
.httpFetchPolicy(HttpFetchPolicy.NetworkOnly)
.okHttpClient(okHttpClient)
.addInterceptor(interceptor)
.run {
if (sentryApolloIntegration) {
addInterceptor(SentryApollo3Interceptor())
} else {
this
}
}
.addHttpInterceptor(LoggingApollo3HttpInterceptor())
additionalInterceptors.forEach {
builder.addInterceptor(it)
}
return builder.build()
}
Thanks for sending this! My DI skills are a bit lacking (what is @[Provides CacheDir]
? Dagger? Something else?) but my guess is that you're sharing the CacheDir
which isn't locked. Instead, you should share the DiskLruHttpCache
and use the httpCache()
overload that takes an ApolloHttpCache
.
provideCacheDir
provides a new instance of a File
, but essentially points to the same location, and also the said overload is not available on 3.8.2
, the version we are using.
3.8.2, would essentially an instance of cache for each client configured separately, which could then produce the issue as mentioned in the description
For now though, I am choosing to use different sub directory for each client, which should also prevent such issues
I think 3.x
should have the overload? See https://github.com/apollographql/apollo-kotlin/blob/release-3.x/libraries/apollo-http-cache/src/main/kotlin/com/apollographql/apollo3/cache/http/HttpCacheExtensions.kt#L82. I would say something like so:
val sharedCache = DiskLruHttpCache(FileSystem.SYSTEM, File("someDirectory"), HTTP_CACHE_SIZE)
ApolloClient.Builder()
.serverUrl("https://...")
.httpCache(sharedCache)
...
.build()
// Same with other clients
But using different directories work too 👍
@kapilsukhyani anything else we can help with here?
Question
Can an HTTP cache be shared for multiple ApolloClient instances?
Although the cache policy that we have for now is
NetworkOnly
, it seems like the queries do get written to the cache respectively here.Right now we have two clients using the same cache with same cache policy of
NetworkOnly
but we do see issues with cache where the tmp cache file is sometimes not found, and my assumption here is, that it probably is because of the same cache being used, where a query execution through one client might delete the same file as being used by the other client.