13

I read this document explaining Guava Cache: CachesExplained. I do understand what refreshAfterWrite and expireAfterWrite are doing. However, while explaining refreshAfterWrite, the document also mentions this:

"So, for example, you can specify both refreshAfterWrite and expireAfterWrite on the same cache, so that the expiration timer on an entry isn't blindly reset whenever an entry becomes eligible for a refresh, so if an entry isn't queried after it comes eligible for refreshing, it is allowed to expire."

This is the part that confuses me. For my understanding, if you want a key to be automatically refreshed, you only need to specify refreshAfterWrite. Why do we even want to use expireAfterWrite when ever refreshAfterWrite is used?

Z.SP
  • 319
  • 1
  • 2
  • 12

1 Answers1

20

There are scenarios in which you'll want the cached entries to be relevant so you set a refresh duration (which might be lighter to perform (and async), rather then a full fetch after eviction and hence, different), but at the same time, if your cache is bounded, you'll want to evict entries, that's what the expireAfterWrite is for. By setting them both, you'll make sure that a entry is evicted after a certain time, even if it was refreshed.

Also note that both are differs in the way they are operate:

Refreshing is not quite the same as eviction. As specified in LoadingCache.refresh(K), refreshing a key loads a new value for the key, possibly asynchronously. The old value (if any) is still returned while the key is being refreshed, in contrast to eviction, which forces retrievals to wait until the value is loaded anew.

Shmulik Klein
  • 3,754
  • 19
  • 34
  • 6
    Make sense. But I also have this question: If I just use expireAfterWrite(), it should also be enough right? expireAfterWrite() evicts old entries. Whenever I call get(), either a new value loaded by cache or value in the cache, depending on if the value expired or not, will be return to me. The document explaining refreshAfterWrite() says this **a refresh will only be actually initiated when the entry is queried**. So what's the point of having refreshAfterWrite()? Could you give me an example? – Z.SP Sep 10 '17 at 23:09
  • 1
    The refresh operation might be lighter (and async) then a full fetch operation after eviction. I've added this note to the answer body. – Shmulik Klein Sep 11 '17 at 07:10
  • 7
    A refresh will reset the expiration's write time stamp. The intent is that some entries may be very hot and when expiring there is user-visible latency when callers block for the load. The refresh lets active entries be reloaded without incurring this cost. If inactive, then the expiration will kick in and evict. – Ben Manes Sep 11 '17 at 16:58
  • Could someone explain what combination of expire/refresh should I use if I want 1) refresh approximately once a minute 2) always async 3) automatic clean-up (if item was deleted it should be deleted from the cache too in ~1 minute). Am I correct that if my CacheLoader is synchronous then guava cache is synchronous too? – Oleg Vazhnev Mar 22 '21 at 22:07
  • 2
    Yes @OlegVazhnev if you do not implement a async refresh method your gets will wait every refresh intervall. If you set your refreshAfterWrite(50s) and expireAfterWrite(5m) then the first get isd loaded sync, then for 50s all gets are served from the cache. After 50s it is still served from the cache but the loader is started. The loader then may return a value (or missing). As long as you get requests before 5m the entry will never be expired because of age (since refresh will write it). – eckes Mar 22 '22 at 19:59