Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Guava cache asynchronous reload

Tags:

java-8

guava

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;
            }
        });
like image 312
bp4D Avatar asked Nov 01 '25 04:11

bp4D


1 Answers

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));
}
like image 162
Tomasz Avatar answered Nov 02 '25 22:11

Tomasz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!