I'd like to have a cache that works like this:
- A. If request is not cached: load and return results.
- B. If request is cached, has not expired: return results.
- C. If request is cached, has expired: start to reload results, return old results immediately.
- D. If request is cached, has expired, reload is already running: return old results immediately.
- E. If reloading fails (Exception): continue to return previous successful load results to requests.
(After a failed reload (case E), next request is handled following case C.)
(If case A ends in Exception, Exception is thrown)
Does anyone know an existing implementation, or will I have to implement it myself?
In cache2k I implemented exactly the behavior you described above. Here is how you build a cache with these features:
The
exipryDuration
is the duration the value is considered valid after it war inserted or modified. The separate setting forexceptionExpiryDuration
is the time until the next refresh is tried after an exception happens.If an exception happens, but there is no valid entry, the exception is cached and rethrown for the
exceptionExpiryDuration
time.You can also dynamically compute the expiry duration, e.g. based on the exception type. Some more information is in the blog entry About caching exceptions
With
backgroundRefresh
an entry is refreshed after it is expired. When no access happens after an refresh within the expiry time, the entry will not get refreshed any more and then eventually evicted.Unfortunately, I am really behind in documenting all these useful features properly. If you have any more questions you can use the tag
cache2k
. If you like some improvements, open an issue on GitHub.The code works well in our production applications for about a year now. Actually,
suppressExceptions
is always the default. It helps very well, e.g. if there is a short network outage.BTW: Meanwhile, I subsume these semantics under the term cache resiliency.