1

I want to create a cache instance in in Spring using Caffeine cache. I need the cache to refresh all the keys async, fetching the data from external services and when the data is ready, interchange the old values with the new values without any downtime. The problem seems to be solved using the refresh mechanism that the cache provides

 @Bean
 public AsyncLoadingCache<Object, Object> myCache() {
        return Caffeine.newBuilder()
                .maximumSize(cacheProperties.getProp())
                .refreshAfterWrite(5, TimeUnit.MINUTES)
                .recordStats()
                .buildAsync(key -> cacheInitializer.fetchCacheValues());
    }

In my case fetchCacheValues() is a bean service that makes external calls to other services, but the method is never called, despite the cache being initialised succesfully.

Am I missing something regarding the .refreshAfterWrite() behaviour? Some better alternatives? (I also tried doing it using a scheduled job and CachePut, but got some downtime when refreshing)

ppk
  • 33
  • 4
  • 2
    Sry, links only: https://github.com/spring-projects/spring-framework/issues/17920, https://github.com/spring-projects/spring-framework/issues/26713 docs: https://docs.spring.io/spring-boot/docs/current/reference/html/io.html#io.caching.provider , https://docs.spring.io/spring-framework/docs/current/reference/html/integration.html#cache – xerx593 Apr 25 '23 at 13:10

1 Answers1

3

In Caffein refreshing of a key works a bit differently then eviction. In case of eviction the value is evicted just because the configured time elapsed. In case of refreshing it will be only marked as "ready for refresh". The actually refreshing will only be triggered when (and if) the value is fetched. In other words if the value is not fetched then your service will never run.

Hope it helps.

Mar-Z
  • 2,660
  • 2
  • 4
  • 16
  • Is there a way to force the refresh whenever the case and do not wait for the value to be fetched? If I use a AsyncCacheLoader with a .buildAsync(), it seems that the .refresh(K) is not available as a method, it is just for LoadingCache.refresh(K) – ppk Apr 26 '23 at 09:30
  • You don't need to use AsyncCacheLoader as refreshing is done asynchronously anyway. Use LoadingCache instead. Example here: https://github.com/ben-manes/caffeine/wiki/Refresh – Mar-Z Apr 26 '23 at 09:57
  • You can use the `synchronous()` view. – Ben Manes May 02 '23 at 03:12