-
|
A pattern I keep running into with To be concrete, a program like this: import com.github.benmanes.caffeine.cache.Caffeine;
void main() throws Exception {
var c = Caffeine.newBuilder().<Integer, Integer>buildAsync();
for (var i = 0; i < 10_000; i++) {
c.asMap().remove(42);
try {
c.get(
42,
k -> {
throw new RuntimeException("failed");
})
.get();
} catch (ExecutionException ee) {
assert ee.getCause().getMessage().equals("failed");
}
c.get(42, k -> 19).get();
}
IO.println("success");
}will probably never complete Are there any recommended patterns for this? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
|
You could perform an explicit remove in your own callback, e.g. |
Beta Was this translation helpful? Give feedback.
CompletableFutureuses a stack of dependent actions so your own action is run prior to Caffeine receiving a callback. We have to return the computed future, not the dependent action's, for the asMap() view (reference identity, e.g. replace) and since methods likecancel()do not communicate. That means we really can do anything in the implementation.You could perform an explicit remove in your own callback, e.g.
cache.asMap().remove(key, future), prior to a retry. Or you could return a future that already handles the retry internally (e.g. failsafe example). I usually use.executor(Runnable::run)in tests to disable asynchronous processing unless I am testing for concurrent executions.