Closed
Description
Hi,
I tried to use Caffeine and the time based eviction.
I started with a simple example, to try it but I can't make it work as I expect. Maybe you can help.
Here is my Java class that uses Caffeine :
public class TestCaffeine2 {
static interface CacheableObject {
/**
* Time-to-live of this object, in nanoseconds
*
* @return Time-to-live of this object, in nanoseconds
*/
long getTtl();
}
static class MyCacheableString implements CacheableObject {
private String value;
private long ttl;
MyCacheableString(String value, long ttl) {
this.value = value;
this.ttl = ttl;
}
String getValue() {
return value;
}
public long getTtl() {
return ttl;
}
}
static class Repository {
private ScheduledExecutorService scheduledExecutorService;
private final Random random;
Repository(ScheduledExecutorService scheduledExecutorService, Random random) {
this.scheduledExecutorService = scheduledExecutorService;
this.random = random;
}
CompletableFuture<MyCacheableString> get(String key) {
System.out.println("Looking up for " + key);
CompletableFuture<MyCacheableString> completableFuture = new CompletableFuture<>();
// This is a simulation of an asynchronous call to fetch the object
// matching the given key from an external data storage
scheduledExecutorService.schedule((Runnable) () -> completableFuture.complete(new MyCacheableString(key + "@" + System
.currentTimeMillis(), TimeUnit.NANOSECONDS.convert(1, TimeUnit.SECONDS))),
random.nextInt(5),
TimeUnit.SECONDS);
return completableFuture;
}
}
void run(String[] args) throws InterruptedException {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2);
Random random = new Random(System.currentTimeMillis());
Repository repository = new Repository(scheduledExecutorService, random);
final AsyncLoadingCache<String, MyCacheableString> cache;
cache = Caffeine.newBuilder()
.expireAfter(new Expiry<String, MyCacheableString>() {
public long expireAfterCreate(String key,
MyCacheableString myCacheableString,
long currentTime) {
System.out.println("ExpireAfterCreate : " + currentTime);
return currentTime + myCacheableString.getTtl();
}
public long expireAfterUpdate(String key, MyCacheableString myCacheableString,
long currentTime, long currentDuration) {
System.out.println("ExpireAfterUpdate : " + currentTime + " " + currentDuration);
return currentDuration;
}
public long expireAfterRead(String key, MyCacheableString myCacheableString,
long currentTime, long currentDuration) {
System.out.println("ExpireAfterRead : " + currentTime + " " + currentDuration);
return currentDuration;
}
})
.buildAsync((key, executor) -> repository.get(key));
CompletableFuture<MyCacheableString> object1 = cache.get("foo");
System.out.println("Got the 1st object " + object1);
object1.thenAccept((myCacheableString) -> System.out.println("Got " + myCacheableString.getValue()));
TimeUnit.SECONDS.sleep(12);
// Now, the cached object should have been evicted
CompletableFuture<MyCacheableString> object2 = cache.get("foo");
System.out.println("Got the 2nd object " + object2);
object2.thenAccept((myCacheableString) -> System.out.println("Got " + myCacheableString.getValue()));
if (object1 == object2) {
System.out.println("!!! The object was not evicted !!!");
}
scheduledExecutorService.shutdown();
System.out.println("END");
}
public static void main(String[] args) throws InterruptedException {
new TestCaffeine2().run(args);
}
}
My object is never evicted from the cache. I am also quite surprised to never see my trace for "ExpireAfterCreate".
What did I do wrong ?
Metadata
Metadata
Assignees
Labels
No labels