1

I came across asynchronous caching using Caffeine library. Following https://www.programcreek.com/java-api-examples/?api=com.github.benmanes.caffeine.cache.AsyncCacheLoader, I have following code snippet:

import com.github.benmanes.caffeine.cache.AsyncCacheLoader;
import com.github.benmanes.caffeine.cache.AsyncLoadingCache;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.Weigher;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;

public class CacheManager {
private static AsyncLoadingCache<String, Object> loader;

public static void initLoadingCache(<datatype> obj) {
    if (loader == null) {
        loader = Caffeine.newBuilder()
                .concurrencyLevel(10)
                .expireAfterWrite(60, TimeUnit.MINUTES) // Cache will expire after 60 minutes
                .buildAsync(new AsyncCacheLoader<String, Object>() { // Build the CacheLoader
                    @Override
                    public CompletableFuture<Object> asyncLoad(String key, Executor executor) throws Exception{
                        Object temp = obj.getTemp(key); // my function which does processing
                        if (temp == null)  LOGGER.error("Not found");
                        return temp;
                    }
                });
        }
    }
}

public Object getTemp(String key) {
    Query query = somequery();
    List<Object> val = query.getResultList();
    return val.get(0);
}
  1. It is obvious that the above code will have error as I am returning temp which is Object but the function is expecting CompletableFuture<Object>. How can I achieve this? I am guessing that getTemp() needs to return ListenableFuture<> as well (https://www.programcreek.com/java-api-examples/?code=Netflix%2Ftitus-control-plane%2Ftitus-control-plane-master%2Ftitus-supplementary-component%2Ftasks-publisher%2Fsrc%2Fmain%2Fjava%2Fcom%2Fnetflix%2Ftitus%2Fsupplementary%2Ftaskspublisher%2FTitusClientImpl.java) but I am not sure how can I achieve this since it has DB queries.
harry123
  • 760
  • 1
  • 7
  • 22
  • I think you want to use `CacheLoader` which will wrap your logic in a future [automatically](https://github.com/ben-manes/caffeine/wiki/Population#asynchronously-loading). – Ben Manes Sep 21 '20 at 21:40
  • @BenManes isn't my `loader` an `asyncacheloader`? I am not able to understand what should I put in `buildAsync()` on your github page. or should I just put `.buildAsync(key->obj.getTemp(key))` – harry123 Sep 21 '20 at 21:51
  • If (i understand) your problem "just" Object-> CompletableFuture>, then you can create it, with: `CompletableFuture cf = new CompletableFuture();` ..and as soon you have your "object"(synchronously), you can invoke `cf.complete(temp);` ..and `return cf;` – xerx593 Sep 21 '20 at 22:13
  • @xerx593 CompletableFuture.completedFuture(temp) is what I am thinking but I am not sure what is more efficient way to do as compared to what BenManes is saying. – harry123 Sep 21 '20 at 22:19
  • @amyJ The builder accepts `CacheLoader` or `AsyncCacheLoader`, where the former might be a little easier for you. Otherwise you could return a `CompletableFuture.supplyAs(...)` if you want to create the future directly. – Ben Manes Sep 21 '20 at 22:43
  • @BenManes thank you. Can you please provide a code snippet on how the builder will work with `AsyncCacheLoader`? It will be of great help. Just want to know how it is exactly used rather than doing `CompletableFuture.supplyAsync(()->temp)` – harry123 Sep 22 '20 at 00:07
  • or @BenManes you are saying to put it this way `.buildAsync(new CacheLoader() { // Build the CacheLoader @Override public Object load(String key) throws Exception{ Object temp = obj.getTemp(key); // my function which does processing if (temp == null) LOGGER.error("Not found"); return temp; } });` I want to do `AsyncCaching` – harry123 Sep 22 '20 at 00:17
  • @amyJ The second one, as it also creates an `AsyncLoadingCache` and wraps the synchronous call for you. If you want to use the `AsyncCacheLoader` then change it to `return CompletableFuture.supplyAsync(() -> { /* your code */ });` – Ben Manes Sep 22 '20 at 02:20
  • @amyJ The main benefit of `AsyncLoadingCache` is when your external call is itself asynchronous, e.g. making an http request, so you can return its future. When your code is synchronous then the `CacheLoader` is less verbose and the cache wraps the call into a future for you (see `CacheLoader.asyncLoad` implementation). – Ben Manes Sep 22 '20 at 02:23

0 Answers0