5
votes

I have a Guava Cache with a CacheLoader. There is an external condition I track in a Thread, and if this happens I want to refresh() all entries asynchronously. For this reason I do not use invalidateAll() since the next get() would have to wait for load to succeed.

Instead I iterate over the keys contained in the cache and refresh(k) all of them, as I could not find a refreshAll() method. Here is the code (but not really related to the question):

    Set<ResourceLoaderKey> keys = resourceLoaderCache.asMap().keySet();
    for(ResourceLoaderKey k : keys)
    {
        resourceLoaderCache.refresh(k);
    }

My problem is now, that reload() in the CacheLoader might detect, that a resource is actually not any longer available. Currently the reload() throws a ResourceNotFound exception which works for the get() case. But it does not work for the refresh() case, as the old value will be served as long as the reload() fails.

I can now trap the not-found exception in the load/reload methods and invalidate the entry somehow, but I wonder if there is a official way to do it (returning null or a null future is logged as a warning and ignored)? It would be good to be able to remove the key/absent-value instead of keeping a placeholder object around.

1
similar problem here, my current solution is ugly, wish there was a supported way to do this - Stephan

1 Answers

0
votes

A supported way to do this doesn't currently exist in guava r17.

Have you tried getting all the keys, then invalidating all, then attempting to get all the keys you had saved?

Set<ResourceLoaderKey> keys = resourceLoaderCache.asMap().keySet();
resourceLoaderCache.invalidateAll(keys);
for(ResourceLoaderKey k : keys) {
    resourceLoaderCache.get(k);        //or getUnchecked() whichever you prefer
}

That should make sure no stale values stay in the cache, and recache all values that exist.

(My problem was slightly different, I had to change my assumptions to solve mine)