Skip to content

Instantly share code, notes, and snippets.

@leozc
Last active September 11, 2018 02:15
Show Gist options
  • Save leozc/85e98a6f15d2f707a35f45ec73486c26 to your computer and use it in GitHub Desktop.
Save leozc/85e98a6f15d2f707a35f45ec73486c26 to your computer and use it in GitHub Desktop.
FutureCache For Java CompletableFuture - enable enqueue a long running future task into the Future pool, and provide an interface to store and fetch the long running results
package com.leozc.FutureCache;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;
public class FutureCache<T> {
private Long ttlms;
/**
*
* @param ttlms how long a ticket should live for, usually this maps to the default object ttl of the storage. - usually the ttl is way larger than the time needed to perform the task
*/
public FutureCache(Long ttlms) {
this.ttlms = ttlms;
}
/**
* Dispatch the completableFuture and wire it with a Store function and return a ticket for polling
* @param task a completable future indicate a long running computation process that produce T
* @param store a lambda to store result of task to a persistent store - which usually accessible by multiple process.
* @return
*/
public Ticket getTicket(CompletableFuture<T> task, BiFunction<String, T, T> store){
String key = String.valueOf(ThreadLocalRandom.current().nextInt(0, Integer.MAX_VALUE));
long now = System.currentTimeMillis();
BiConsumer<? super T, ? super Throwable> biConsumer = (BiConsumer<T, Throwable>) (t, throwable) -> {
if (throwable == null) {
store.apply(key, t);
}
};
// TODO: emit metrics to calculate the time takes for tasks
task.whenComplete(biConsumer);
return new Ticket(key, now, now + ttlms);
}
public Optional<T> getReady(String key, Function<String, T> lookupStore){
T t = lookupStore.apply(key);
if (Objects.isNull(t))
return Optional.empty();
else
return Optional.of(t);
}
class Ticket{
private String key;
private Long issueTime;
private Long ttl;
public Ticket(String key, Long issueTime, Long ttl) {
this.key = key;
this.issueTime = issueTime;
this.ttl = ttl;
}
public String getKey() {
return key;
}
/**
* The
* @return timestamp in ms
*/
public Long getIssueTime() {
return issueTime;
}
/**
* Get how long the result will store on the server side
* @return the number of ms
*/
public Long getTtl() {
return ttl;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment