caffeinecaffeine-cache

Caffeine cache, perform eviction of expired element only when put succeds


I use Caffeine cache to cache data coming from the DB that need to served to a rest endpoint. So the cache is updated ONLY on read operations on the DB.

In the nominal case, I want the cache to take the lead of responding until the data is not older than some point of time ( => this case is ok by defining the correct expiration options)

In case of DB access failure, I want to fallback to the cache even if the data in the cache is expired. This use case supposes that expired data are not yet removed.

The solution I'm thinking of is to make Eviction of Items from the cache only after a successful PUT (a successful PUT means the DB is working correctly). Is that possible to do?


Solution

  • This could be accomplished by using a victim cache to capture recently expired entries and resurrect from it on a load if the db is down. The victim cache would need its own bounding, e.g. a longer expiration threshold.

    Cache<K, V> victimCache = Caffeine.newBuilder()
        .expireAfterWrite(10, TimeUnit.MINUTE)
        .build();
    LoadingCache<K, V> mainCache = Caffeine.newBuilder()
        .expireAfterWrite(1, TimeUnit.MINUTE)
        .writer(new CacheWriter<K, V>() {
          public void write(K key, V value) { /* ignored */ }
          public void delete(K key, V value, RemovalCause cause) {
            if (cause == RemovalCause.EXPIRED) {
              victimCache.put(key, value);
            }
          })
         .build(key -> {
           try {
             // load from db
           } catch (DatabaseAccessException e) {
             return victimCache.asMap().remove(key);
           }
         });
    

    This would allow a load failure to resurrect the entry from the victim cache, if the entry is present.