12

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?

Sasha Shpota
  • 9,436
  • 14
  • 75
  • 148
  • If you have limited cache names, you can setting TTL for each cache name by configuring `CacheManager` bean. It would be great if SDR allows config TTL as property of `@Cacheable` – Mạnh Quyết Nguyễn Jun 17 '19 at 02:18
  • Did you tried https://stackoverflow.com/questions/8181768/can-i-set-a-ttl-for-cacheable – Ori Marko Jun 17 '19 at 05:12
  • @MạnhQuyếtNguyễn I do have limited cache names. Could you please elaborate on the solution. – Sasha Shpota Jun 17 '19 at 21:35
  • 1
    @OleksandrShpota You can look at [this](https://stackoverflow.com/questions/51054774/how-to-configure-different-ttl-for-each-redis-cache-when-using-cacheable-in-spr). The idea is to configure different cache manager with different TTL. – Mạnh Quyết Nguyễn Jun 18 '19 at 02:09

1 Answers1

8

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")

JustCurious
  • 111
  • 3
  • 14
Alexander Petrov
  • 9,204
  • 31
  • 70