'Guava cache asynchronous reload
I have followed guava cache documentation and coded asynchronous cache reloading in my application. Additionally, during application start, I am loading the cache using cache.put
. I am reloading it every 15 mins afterwards (provided there is an incoming request at/after 15 mins). While debugging, I found that reload is called correctly and my application is not waiting for the updated graph from DB.
My Question is: Do I need to continue to override load method in my application? As described above, the initial loading of cache is done on application startup.
Below is my paraphrased code (about same as in documentation):
private LoadingCache<String, Graph> cache = CacheBuilder.newBuilder()
.refreshAfterWrite(2, TimeUnit.MINUTES)
.recordStats()
.build(new CacheLoader<String, Graph>() {
@Override
public Graph load(String key) {
return getGraphFromDB(key);
}
public ListenableFuture<Graph> reload(final String key, Graph prev) {
ListenableFutureTask<Graph> task = ListenableFutureTask.create(new Callable<Graph>() {
public Graph call() {
Graph graph = prev;
try {
graph = getGraphFromDB(key);
} catch (Exception e) {
logger.error("There was an exception when reloading the cache",e);
}
finally {
return graph;
}
}
});
executor.execute(task);
return task;
}
});
Solution 1:[1]
I think its a good idea to use asyncReloading. In example we reload cache, containing PublicKeys every 1 minute. Also for debuging we use RemovalListener.
@Value("${security.jwks-cache-refresh-milliseconds:60000}") // 1 min
private Integer jwksCacheRefreshMilliseconds;
private Cache<String, PublicKey> jwksCache;
@PostConstruct
private void init() {
TimeUnit timeUnit = TimeUnit.MILLISECONDS;
RemovalListener<String, PublicKey> removalListener = n -> {
if (n.wasEvicted() && log.isDebugEnabled()) {
log.debug("jwksCache remove key : {}, reason : {}", n.getKey(), n.getCause().name());
}
};
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(5);
jwksCache = CacheBuilder.newBuilder()
.refreshAfterWrite(Long.valueOf(jwksCacheRefreshMilliseconds), timeUnit)
.removalListener(removalListener)
.build(CacheLoader.asyncReloading(new CacheLoader<String, PublicKey>() {
@Override
public PublicKey load(String kid) throws Exception { // code to refresh key from jwks
}
}, scheduler));
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Tomasz |