Reputation: 1204
I use LoadingCache<KEY, VALUE>
from Google's guava library. It works well. But my use case requires me to recognize when acquired value was returned from cache itself or loaded by given CacheLoader
. Is there a way to recognize source of the value ?
Upvotes: 1
Views: 2753
Reputation: 1
Yes, it is possible to recognize the source by using CacheStats.
CacheStats class provides you methods like hitCount(), loadCount(), loadSuccessCount(), requestCount() (the link above contains explanation for what each method does) that will help you know when data from looked up from cache and when it was loaded from db.
To get the stats, you'll have to use recordStats() method with CacheBuilder when creating a new LoadingCache.
LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
.maximumSize(1000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.removalListener(MY_LISTENER)
.recordStats() // <- add this
.build(
new CacheLoader<Key, Graph>() {
@Override
public Graph load(Key key) throws AnyException {
return createExpensiveGraph(key);
}
});
Upvotes: 0
Reputation: 5723
We had a similar requirement. In our case we set HTTP-headers for debugging purposes, whether the request was a cache hit or a cache miss. There no way to do this in a single cache request. A pattern getting close to what you want looks like:
boolean hit = true;
Object result = cache.getIfPresent(key);
if (result == null) {
hit = false;
result = cache.get(key);
}
// result: either from the cache or loaded
// hit: is true if it was in the cache
In a concurrent scenario there could be multiple request on the same key at the same time. So there are two caveats:
getIfPresent
and get
, so a false miss would be indicatedFor statistical and debugging purposes it is good enough.
You asked for:
But my use case requires me to recognize when acquired value was returned from cache itself or loaded by given
CacheLoader
.
This requirement cannot be fulfilled, since it can happen, in concurrent scenarios, as described above, that the item is not returned from the cache, but blocks because the entry is currently loaded. So outcome is either a miss or hit. Or the outcome is a hit, a load or was blocked for load.
Other approaches:
computeIfAbsent
Please mind that applications might evolve and the caching library might be changed or maybe you want to switch to asynchronous loading. Try to keep things simple, portable and not causing performance overhead.
Ultimately, speak to your downstream consumer and clarify what is needed, what would be sufficient and what is doable. Since caching seems to be in your domain, you have the responsibility that things are not impacting the system performance at the end. So any requirements should be made collaboratively and always need technical compromises.
Upvotes: 2