0

I'm using the CaffeineCache implementation and used refreshAfterWrite along with cacheLoader. This will return the stale value if key is present while it loads the new value in cache but what if I want it to return null when key is not present but also fetch the value asynchronously for subsequent requests.

private CaffeineCache buildCache(String cacheName, Ticker ticker, Long maxSize, Long ttl, TimeUnit ttlUnit,
                                 CacheLoader<Object, Object> cacheLoader){

    Caffeine<Object, Object> cacheBuilder = Caffeine.newBuilder();

    // TTL
    if (ttl != null && ttl > 0 && ttlUnit != null) {
        if (cacheLoader != null) {
            cacheBuilder.refreshAfterWrite(ttl, ttlUnit);
            cacheBuilder.expireAfterWrite(180, TimeUnit.MINUTES);
        } else {
            cacheBuilder.expireAfterWrite(ttl, ttlUnit);
        }
    }

    // Max size
    if (maxSize != null && maxSize > 0){
        cacheBuilder.maximumSize(maxSize);
    }

    // Ticker
    cacheBuilder.ticker(ticker);

    if (cacheLoader != null) {
        return new CaffeineCache(cacheName, cacheBuilder.build(cacheLoader));
    }

    return new CaffeineCache(cacheName, cacheBuilder.build());
}

This is my cache config currently, refreshAfterWrite is much less than expireAfterWrite.

  • I am not familiar with Spring, but I believe that Spring Cache is too basic of an abstraction to support this. You might try using an [async extension](https://github.com/spring-projects/spring-framework/issues/17920#issuecomment-1274584533) or Caffeine's apis. For our apis then either use LoadingCache's `getIfPresent` + `refresh` if absent, or AsyncLoadingCache's `get` with the future's `getNow` for the value if done. – Ben Manes Nov 11 '22 at 16:56
  • AsyncLoadingCache works well for my usecase. Thanks @BenManes – saket agarwal Nov 14 '22 at 06:16
  • @BenManes I assumed that for a particular key, only one thread will try and reload value in the cache if value for that key is not present in the cache but that doesn't seem to be the case. Any config I need to set for this or any work around you can suggest? – saket agarwal Jan 12 '23 at 19:58
  • What do you mean by "for a particular key, only one thread will try and reload value in the cache if value for that key is not present in the cache"? If you want to reload absent entries then you can use a scheduled task. The cache refresh is to hide latency of a load for active entries that would otherwise expire, e.g. configuration values used on every request, to avoid periodic spikes when callers wait for a fresh load when the expired entry was evicted. – Ben Manes Jan 13 '23 at 18:38
  • @BenManes I mean if multiple requests/threads are trying to access an absent entry(entry not yet present in the cache) at the same time, I just need one thread to go and fetch the value and not all of them. Is that possible? – saket agarwal Jan 18 '23 at 08:43
  • Yep, that is how it works if you load through the cache. – Ben Manes Jan 18 '23 at 09:16

0 Answers0