Java 咖啡因:当AsyncLoader无法刷新时使用过时的值

Java 咖啡因:当AsyncLoader无法刷新时使用过时的值,java,kotlin,kotlin-coroutines,caffeine,caffeine-cache,Java,Kotlin,Kotlin Coroutines,Caffeine,Caffeine Cache,我想配置我的caffee缓存,以便在加载程序无法刷新缓存时返回过时的结果。以下Kotlin代码演示了这种情况: @测试 fun`completeble future`()=运行阻塞{ val cache=Caffeine.newBuilder() .refreshAfterWrite(持续时间秒(1)) .expireAfterWrite(持续时间秒(1)) .buildAsync{key:String,executor-> GlobalScope.future(executor.ascourt

我想配置我的
caffee
缓存,以便在加载程序无法刷新缓存时返回过时的结果。以下Kotlin代码演示了这种情况:

@测试
fun`completeble future`()=运行阻塞{
val cache=Caffeine.newBuilder()
.refreshAfterWrite(持续时间秒(1))
.expireAfterWrite(持续时间秒(1))
.buildAsync{key:String,executor->
GlobalScope.future(executor.ascourtineDispatcher()){
抛出异常(“==错误==”)
}
}
cache.put(“id”,CompletableFuture.completedFuture(“value”))
延迟(2000年)
assertEquals(“value”,cache.get(“id”).await())
}
我希望此测试能够通过,但却出现以下错误:

WARNING: Exception thrown during asynchronous load
java.lang.Exception: == Error ==
    at fsra.manager.TranslationManagerImplTest$completeble future$1$cache$1$1.invokeSuspend(TranslationManagerImplTest.kt:93)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
    at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1426)
    at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
    at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
    at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
    at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
    at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:177)




java.lang.Exception: == Error ==

    at fsra.manager.TranslationManagerImplTest$completeble future$1$cache$1$1.invokeSuspend(TranslationManagerImplTest.kt:93)
    at |b|b|b(Coroutine boundary.|b(|b)
    at fsra.manager.TranslationManagerImplTest$completeble future$1.invokeSuspend(TranslationManagerImplTest.kt:101)
Caused by: java.lang.Exception: == Error ==
    at fsra.manager.TranslationManagerImplTest$completeble future$1$cache$1$1.invokeSuspend(TranslationManagerImplTest.kt:93)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
    at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1426)
    at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
    at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
    at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
    at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
    at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:177)

我用Kotlin编写了代码,但我不认为这个问题与Kotlin协同程序有关。我想将咖啡因配置为在刷新时不抛出,而是返回缓存中以前的结果。

缓存设置为在1秒后过期条目,测试等待2秒。然后,下一个调用将强制重新加载该条目,因为该条目不可用,您将抛出一个异常

刷新大于或等于到期时间时无效。小于时,该条目过时但可用,因此返回并异步重新加载。这是为了允许流行项目(如配置)保留在缓存中,而不会在重新加载时受到定期惩罚。不受欢迎的项目是那些在过期时间间隔内未访问的项目,并且允许被逐出。如果刷新无法成功,则到期将生效,条目将被删除,因为到期设置了被认为可用的最长时间


更大的过期值(如5秒)将通过测试。如果您的用例是周期性地盲目地重新加载缓存的所有内容,那么您可以使用常规的
映射和
ScheduledExecutorService
来刷新它。

您是否看到由堆栈跟踪中的
异常引起的另一个
?是@sidgate。我已经在问题中添加了所有的异常细节。谢谢你的回答。我想要的是回退到当前缓存的值,即使它已过时。对于这个用例来说,咖啡因似乎是杀伤力过大(或不合适),对吗?@alisabzevari,这可能会起作用,但过期时间会迫使它被逐出,所以你需要将它设置得更高。但是,它不是回退,它返回过时的值并触发刷新。如果您希望执行阻塞重新加载,然后在失败时回退,那么您需要自己构建该逻辑。这可以利用咖啡因,例如受害者缓存回退层,但它太过自定义,无法提供内置模式。我们可以通过github问题/电子邮件进行讨论,因为这是一个更大的话题,这很有意义。我的意思是退回到以前的值。