Leonardo
Leonardo

Reputation: 1363

Spring Cache perform action after expires

I'm using Caffeine as Cache Manager integrated with Spring Cache to avoid multiple unnecesary file downloads. Once I download the file, I have its path, which is returned by the download method.

I would like to delete the file once the cache expires. I tried with removalListener but it seems it is only triggered when cache is manually cleared.

This is my cache configuration:

@Bean
fun getCacheBuilder() = Caffeine.newBuilder()
    .expireAfterWrite(3, TimeUnit.SECONDS)
    .removalListener { _: Any?, filePath: Any?, _: RemovalCause ->
        Files.delete(Paths.get(filePath.toString()))
    }

@Bean
fun getCacheManager(caffeine: Caffeine<Any, Any>): CacheManager {
    val caffeineCacheManager = CaffeineCacheManager("myStoredData")
    caffeineCacheManager.setCaffeine(caffeine)
    return caffeineCacheManager
}

Is there something wrong with this code? Is there any way to automatically trigger the listener when the cache expires?

Upvotes: 2

Views: 1974

Answers (2)

HereAndBeyond
HereAndBeyond

Reputation: 1504

Redis cache and @EventListener approach

For those who come here with the same question, but regarding Redis:

I've done this in next way, using Spring's @EventListener.

@Slf4j
@EnableRedisRepositories(enableKeyspaceEvents = RedisKeyValueAdapter.EnableKeyspaceEvents.ON_STARTUP)
@Configuration
public class RedisListenerConfig {

    @EventListener
    public void handleRedisKeyExpiredEvent(RedisKeyExpiredEvent<String> event) {
        String eventId = new String(event.getId());
        log.info("Key {} has expired. Value {}", eventId, event.getValue());
    }

}

The whole manual can be found here Baeldung.com

Working on Java 17 and Spring Boot 3.x.x as well as on Java 8 and Spring Boot 2.5.x

Upvotes: 0

Ben Manes
Ben Manes

Reputation: 9621

By default expiration is handled as a side-effect of other activity on the cache triggering a maintenance cycle. If the cache is idle then the notification will be delayed. To resolve this you will need a thread to schedule expiration events on, so that it can trigger a cache.cleanUp() call. This can be done using Caffeine.scheduler(Scheduler) configuration. The systemScheduler relies on a Java 9+ feature of a JVM-wide scheduler thread.

Caffeine.newBuilder()
    .expireAfterWrite(3, TimeUnit.SECONDS)
    .scheduler(Scheduler.systemScheduler())
    .removalListener { _: Any?, filePath: Any?, _: RemovalCause ->
        Files.delete(Paths.get(filePath.toString()))
    }

Upvotes: 2

Related Questions