Sandy
Sandy

Reputation: 1012

How to check for expired entry in Ehcache 2.10.x

I am a newbie in implementing cache technique in my project and after reading some blogs, have decided to use Ehcache. Now I am facing a bit problem in identifying the correct approach of how can I check for the expired entries in the cache so that I can refresh my cache synchronously/asynchronously.

The Ehcache configuration doc says

timeToLiveSeconds – The maximum number of seconds an element can exist in the cache regardless of use. The element expires at this limit and will no longer be returned from the cache.

Below is my cache config

    <cache name="userCache"
           maxEntriesLocalHeap="500"
           eternal="false"
           timeToIdleSeconds="30"
           timeToLiveSeconds="30"
           memoryStoreEvictionPolicy="LRU"
           transactionalMode="off">
        <persistence strategy="none" />
    </cache>

I was in assumption that the entry stays in the cache even after expiry. I wanted to do something like below:

get an element from the cache
   if not expired, return the element
   if expired, return the stale entry and reload the cache asynchronously.

but it seems, Ehcache removes the cache entry on expiry on its own and therefore I am facing challenges to implement the above said algorithm. Is there any config that I can set not to remove from cache even after expiry?

Upvotes: 0

Views: 2782

Answers (3)

Sandy
Sandy

Reputation: 1012

As per my usecase, re-loading the cache entries is very expensive and I cant afford, refreshing the cache when expired and return the latest record.

Here is the approach that I have decided for implementing my usecase.

  1. set eternal="true" so that the elements in the cache never expire. the timeToLive and timeoIdeal setting will become inoperable if eternal set to true.
  2. Hence, maintain timeToLive configuration for the cache in my code. Each time I retrieve an element from the cache, check if the cached element has exceeded its timeToLive period. If the cache expired, refresh the cache element asynchronously, returning the stale entry for the current call (Cache.get()).

    private int timeToLiveSeconds;
    
    private boolean isElementInCacheExpired(Element element) {
      // The synchronized block prevents multiple threads from checking the expiration condition at the same time.
      synchronized (element) {
        long now = System.currentTimeMillis();
         return (now > element.getLatestOfCreationAndUpdateTime() + TimeUtil.toMillis((int) this.timeToLiveSeconds));
      }
    } 
    

Reference: solving-a-classic-ehcache-problem-retrieving-expired-data

Upvotes: 0

Louis Jacomet
Louis Jacomet

Reputation: 14500

As documented, expired entries are no longer returned.

You have different options:

  1. As described in the other answer, simply try to hit the cache, when getting nothing, simply load, put back in cache, return. This is the standard way of using a cache.
  2. You really need soon to expire entries to be refreshed - Ehcache provides features to help you do this: refresh ahead and scheduled refresh
  3. You need the fine grained control - just put an object into the cache that contains your own expiration information, relying on the cache to never expire. Do the checks yourself and implement the logic you describe

I purposely ordered these answers because that's how you should approach the problem: try 1, if not enough move to 2 and if still not enough you will have to go with 3.

Upvotes: 2

Guenther
Guenther

Reputation: 2045

The way caches usually work is that elements are removed there is not enough room in the cache (or for other reasons, e.g. expiry polocies) The way you work with a cache is that you first try to retrieve the value from the cache. If it's not found, you retrieve it the usually more time consuming way from it's original source. Once retrieved, you add it to the cache and return the value to the caller. You usually don't need to be informed about an item being removed from the cache. If you really, really do need to know for whatever reason, you could add a CacheEventListener http://www.ehcache.org/apidocs/2.6.9/net/sf/ehcache/event/CacheEventListener.html

Btw. I wouldn't use ehcache directly for simple caching. I'd go for the standard java-cache implementation JSR107 and use ehcache as a JSR107 provider. That way you don't have any references to 3rd party cache code.

Upvotes: 0

Related Questions