flower
flower

Reputation: 2242

How to pass more than one parameter in google Cache CacheLoader?

I want to use google Cache to cache my data,So I write the code like this.I find that it can only pass one parameter that called key,But In my method,I have the other parameter,How to fix my code?

 private LoadingCacheS<tring, List<Map<String, Long>> getCache(String key,Map<String,String> para1,
 String para2){
 retrun CacheBuilder.newBuilder()
            .refreshAfterWrite(20, TimeUnit.MINUTES)
            .expireAfterWrite(30, TimeUnit.MINUTES)
            .maximumSize(1)
            .build(new CacheLoader<String, List<Map<String, Long>>>() {
                @Override
                public List<Map<String, Long>> load(String key) throws Exception {
                    return queryData(key); //can not get the other para
                }

                @Override
                public ListenableFuture<List<Map<String, Long>>> reload(String key, List<Map<String, Long>> oldValue)
                        throws Exception {
                    ListenableFutureTask<List<Map<String, Long>>> task = ListenableFutureTask
                            .create(() -> queryData(key));
                    executorService.execute(task);
                    return task;
                }

In my queryData method,I have three parameters,How to change my code?

private List<Map<String, Long>> queryData(String key,Map<String,String> para1,
 String para2){
  //query data and return data
  }

Upvotes: 2

Views: 2094

Answers (2)

Oleg Vazhnev
Oleg Vazhnev

Reputation: 24067

Can you just check if value exist in cache and call your custom load method if it doesn't? Something like this (Kotlin)

fun getDataFromCache(val key: Key, para1: Map<String,String>, para2: String) {
    val fromCache = cache.getIfPresent(key)
    if (fromCache != null) {
       return fromCache
    } else {
        val loaded = queryData(key, para1, para2)
        cache.put(key, loaded)
        return loaded
    }
}

Upvotes: 0

Ben Manes
Ben Manes

Reputation: 9621

In these types of cases you have multiple options.

If all of the parameters are part of the mapping, then you can use a composite key. A data class that holds all parameters and correctly implements equals and hashCode is the cache key.

Sometimes these parameters irrelevant to the key but the parameters are part of a lifecycle scoped, e.g. to the http request such as the user's access token. In those cases you may be using a dependency injector like Guice that is aware of this lifecycle. In those cases you can inject a Provider<T> (or equivalent) instead and resolve the parameter at runtime.

The last option is to not use a CacheLoader but instead use cache.get(key, loader). The loader, a Callable, is a "capturing lambda" which means that it has access to parameters in the surrounding scope. The drawback of this approach is that you cannot use refreshAfterWrite since that requires a CacheLoader.

Upvotes: 2

Related Questions