I'm trying to use caffeine
and spring-boot-starter-cache
to implement the following caching logic:
I worked according to this guide: https://www.baeldung.com/spring-boot-caffeine-cache
I tried all sort of approaches using @CachePut
, @CacheEvict
and @Cacheable
on the getter
method of the object I;m caching but the core issue is that I need to condition the eviction with both an expiration time and another logic but these annotations cannot control whether to evict or not... Perhaps this can be done using a Scheduler
?
I think you are looking for refreshAfterWrite
and override CacheLoader.reload(K, V)
.
Here is the post that explain the details: https://github.com/ben-manes/caffeine/wiki/Refresh
Implementation for your case would be something like:
@Log4j2
@Configuration
public class CacheConfig {
@Bean
public Cache<String,Item> caffeineConfig() {
return Caffeine.newBuilder()
.refreshAfterWrite(10, TimeUnit.SECONDS)
.build(new ConditionalCacheLoader<>(this::shouldReload, this::load));
}
private Item load(String key){
//load the item
return null;
}
private boolean shouldReload(Item oldValue){
//your condition logic here
return true;
}
private static class Item{
// the item value can contain any data
}
private static class ConditionalCacheLoader<K,V> implements CacheLoader<K,V>{
private final Predicate<V> shouldReload;
private final Function<K,V> load;
protected ConditionalCacheLoader(Predicate<V> shouldReload, Function<K, V> load) {
this.shouldReload = shouldReload;
this.load = load;
}
@Override
public V load(K key) throws Exception{
return load.apply(key);
}
@Override
public V reload(K key, V oldValue) throws Exception {
if (shouldReload.test(oldValue)){
return load(key);
}else {
return oldValue;
}
}
}
}