Search code examples
javaehcache

Changing the TTL of individual entries in EHCache 3


In EHCache 2.x, it was possible to set a time to live on an individual entry in a cache, for example:

Element dependentElement = cache.get(key);
long lastAccessTime = dependentElement.getLastAccessTime();
long creationTime = dependentElement.getCreationTime();
int timeToLive = lastAccessTime == 0 ? 300 : (int)
  (lastAccessTime - creationTime) / 1000 + 300;
timeToLive += 2;
dependentElement.setTimeToLive(timeToLive);

This would update the TTL of the individual item, thus keeping it in cache longer.

In EHCache 3.x this seems no longer possible to do on an individual cache entry basis. After reading the Migration Guide and this question, it seems to me this functionality is not directly migratable.

The guide tells us that in order to modify the TTL, an interface has to be implemented:

CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, 
    String.class, ResourcePoolsBuilder
    .withExpiry(new Expiry<Long, String>() {    
      @Override
      public Duration getExpiryForCreation(Long key, String value) {
        return getTimeToLiveDuration(key, value);   
      }

      @Override
      public Duration getExpiryForAccess(Long key, ValueSupplier<? extends String> value) {
        return null;  // Keeping the existing expiry
      }

      @Override
      public Duration getExpiryForUpdate(Long key, ValueSupplier<? extends String> oldValue, String newValue) {
        return null;  // Keeping the existing expiry
      }
    });

This configuration is then added to a cache to be initialized. However, it does appear that, since it's a cache-level extension point, you can never guarantee that the methods are triggered for the actual entry you want to change?

Looking at the internals of EHCache 3, it seems that the good old net.sf.ehcache.Element is abstracted away and changed into a ValueHolder<V> and that it is no longer possible to access this.

So, the question is: how can we implement the same behaviour in EHCache 3.x?


Solution

  • Expiration duration can only be modified when an entry is created, accessed or updated.

    Now depending on your exact requirements, you could implement your specific logic on getExpiryForAccess and access the mapping to get the updated expiration. However, you cannot differentiate between a regular access and an access that should update expiration. And I would not recommend having such a stateful expiration computation anyway.

    There might be alternative ways to support your use case by changing the caching design altogether, but that's outside of the scope of this question.