Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Immutable collection with expiration

Tags:

java

guava

What I'm doing: I'm gathering a potentially large collection of objects and asking the user for input based on the collection. I want to cache the objects to avoid reacquiring them, but I want the collection to expire after a short time in case the user flakes out. If needed, I'll reacquire the objects. The collection will not change over the short time span involved.

What I've looked at: Guava's Cache looks promising because of the time-based expiration. However, a couple of things bother me about it. I don't really need a map -- the collection will be accessed in its entirety or not at all. And I'm worried that I can run into a race condition where items in the Cache start expiring as I'm accessing the Cache. That adds a level of complexity, having to track if all my items are in the Cache, eliminating some of the value of the cache.

My Question: Am I asking for trouble if, instead of placing individual items in the Cache, I make a Guava ImmutableCollection of them and place that into the Cache? It seems that way I access the entire collection in one go, and the collection is either in the cache or it isn't (in which case I rebuild it all). Are there pitfalls with this approach that I'm not seeing?

like image 505
KathyA. Avatar asked Aug 12 '26 02:08

KathyA.


1 Answers

It's not unusual to have a static, singleton key for a Guava cache. Cache provides a lot of benefit even when not used as a Map. I would just do something like this:

 private static final Object CACHE_KEY = new Object();

 private LoadingCache<Object, List<SomeType>> cache = 
      CacheBuilder.newBuilder()
        .expireAfterWrite(5, TimeUnit.MINUTES)
        .softValues()
        .build(valuesLoader());

 //...
 List<SomeType> values = cache.get(CACHE_KEY);

In my code base, I use caches with single values in a few places, so I've abstracted this to a SingleValueLoadingCache<T> which exposes a no-arg get() method and encapsulates the cache and key.

It seems that way I access the entire collection in one go, and the collection is either in the cache or it isn't (in which case I rebuild it all). Are there pitfalls with this approach that I'm not seeing?

Just in case you haven't found it yet, you probably want a LoadingCache by passing a CacheLoader to the build method of the CacheBuilder. That way you just always call get(), and if the value isn't in the cache, it is loaded for you automatically and synchronously, using the CacheLoader you've provided.

like image 138
Mark Peters Avatar answered Aug 14 '26 15:08

Mark Peters