Skip to content
Advertisement

Modify logic of what to do when cache is full in Retrofit/OkHttp?

I am trying to define my own logic of how is cache handled when it is full, because actual behavior is not wanted. I do not know if it is possible (I have not found any documentation on this topic), so I am asking here.

When cache is full, Retrofit/OkHttp is removing cached responses based on their validity duration, prioritizing these, that expire sooner.

Simple example:

If we have an empty cache of for example 1MB and there comes response of size 700KB that expires in 1 hour (Cache-Control: max-age=3600) and after this comes different response of size 800KB (it does not fit in cache anymore) that expires in 30 minutes, the second response is not cached.

Another example:

In 1MB cache we have 800KB response that expires in 1 hour from now and then another response comes that have 800KB that expires in 5 hours. The 1 hour response is removed and 5 hour response is stored.

I want to change this behavior, to be that responses are removed from cache based on their receival time (OkHttp-Received-Millis attribute), not their expiration time, so oldest reponses are removed first.

Creation of http client and retrofit initialization:

private Retrofit retrofit(String baseUrl) {
        return new Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(cachingClient(CACHE_IDENTIFIER))
                .addConverterFactory(GsonConverterFactory.create(gson()))
                .build();
}

private OkHttpClient cachingClient(String identifier) {
        return new OkHttpClient.Builder()
                .cache(cache(identifier))
                .addInterceptor(InterceptorsKt.authorizationInterceptor(Credentials.basic(USER, PASSWD)))
                .build();
}

private Cache cache(String identifier) {
        return new Cache(new File(context.get().getCacheDir(), identifier), CACHE_SIZE);
}

Structure of cached response call:

http://example.com:8754/random/hello
GET
0
HTTP/1.1 200 
11
Cache-Control: max-age=2592000, immutable
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-Frame-Options: DENY
Content-Type: application/json
Transfer-Encoding: chunked
Date: Wed, 21 Sep 2022 08:01:31 GMT
Keep-Alive: timeout=60
Connection: keep-alive
OkHttp-Sent-Millis: 1663747322078
OkHttp-Received-Millis: 1663747322254

One more time, actual behavior is that responses are removed from cache (when its full) based on calculation time now + max-age (lowest are removed first) and wanted behavior is that oldest are removed, based on OkHttp-Received-Millis.

Is something like this possible to do?

Advertisement

Answer

OkHttp’s cache evicts the least-recently used items. It does not consider when an item’a freshness time when making eviction decisions.

There is no API to change this policy. If you’d like to manually evict items from the cache, you may use the cache’s iterator and call remove on the items you decide should be evicted.

3 People found this is helpful
Advertisement