Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redis: Set different time to live for methods annotated with @Cacheable

I have a set of cached methods that look somewhat like this:

@Cacheable(value = "myCacheName", keyGenerator = "myKeyGenerator")
public Product getProduct(ProductRequest request) {
    // ...
}

And I need to set different time to live (expiration interval) for objects returned by these methods.

Problem: According to the documentation, the offered way is using @RedisHash(timeToLive=…​) or @TimeToLive annotations on the return type of the methods. However, I don't want to pollute my domain classes with caching related logic. In addition, some of my methods return strings or objects of classes which I can not modify. I would prefer to implement it in a more configurable way. There is also a configuration property called spring.cache.redis.time-to-live, but it applies the same time-to-live in all places.

Question: Is there a way to specify time to live/expiration interval on the method level? Or generally, how to implement it in a more elegant way?

like image 935
Sasha Shpota Avatar asked Jun 12 '19 14:06

Sasha Shpota


1 Answers

Hi if you want to use only Spring annotations one way to do this is the following. @CacheConfig annotation allows you to define specific CacheManager to use further more the @Cacheable annotation also allows defining cacheManager

@CacheConfig(cacheNames="myCacheName",cacheManager="timeoutCacheManager")
class ProductReader {

    @Cacheable(value = "myCacheName", keyGenerator = "myKeyGenerator")
   public Product getProduct(ProductRequest request) {
      // ...
   }

}


@Bean
public CacheManager timeoutCacheManager(RedisTemplate redisTemplate) {
    RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
    cacheManager.setDefaultExpiration(mytimeToLive);
    return cacheManager;
}

Here is also a fragment of a more extensive cache configuration that is resulting again in a CacheManager. This time it configures multiple regions:

@Bean (name="cacheManager")
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
    RedisCacheConfiguration conf_ready_info = RedisCacheConfiguration.defaultCacheConfig()
            .entryTtl(Duration.ofMillis(50000));

    RedisCacheConfiguration conf_base_info = RedisCacheConfiguration.defaultCacheConfig()
            .entryTtl(Duration.ofMillis(60000));

    Map<String, RedisCacheConfiguration> cacheConfigurations = new HashMap<String, RedisCacheConfiguration>();
    cacheConfigurations.put("base_info", conf_base_info);
    cacheConfigurations.put("ready_info", conf_ready_info);

    return RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(connectionFactory)
            .withInitialCacheConfigurations(cacheConfigurations).build();
}

I took the last example from: set expire key at specific time when using Spring caching with Redis

Using only @Cacheable(value = "myCacheName", keyGenerator = "timeoutCacheManager")

like image 143
Alexander Petrov Avatar answered Oct 03 '22 22:10

Alexander Petrov