-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Exception in CacheLoader prevents further refreshing #1807
Comments
The refresh feature is defined as an asynchronous load, so it always delegates to caffeine/caffeine/src/main/java/com/github/benmanes/caffeine/cache/Caffeine.java Lines 816 to 827 in 047021c
The unit test thread races with the refresh, so it asserts before the reload has completed. If you wait until that completes then the test is successful. Without changing your configuration, adding this line before the final assertion causes the test to pass. ForkJoinPool.commonPool().awaitQuiescence(1, TimeUnit.SECONDS); A different executor could be specified, such as When the future completes immediately we will override the return value, which was the stale value looked up, and return the reloaded one instead. Of course most of the time that won't happen if the reload is async, but it was requested by a few users to return it if an immediate future (#520, #688, #699). |
Hi |
It sounds like you want expiration, in which the entry is not usable and must be loaded anew. In that case you would use refreshAfterWrite is intended to be used in conjunction with an expiration policy as a latency hiding technique. If the entry is popular, such as an auth token used on every lookup, then when it expires many requests would observe a periodic latency spike as they waited for the new value to be loaded. If popular then an optimistic reload could be performed in the background to hide this penalty for a better user experience. Some users confused this feature with a periodic full reload of the cache contents where they never want eviction, like in your example. That is an easy mistake of confusing a replica with a cache, which are similar but different concepts, and the main design choice is the replication strategy (hot, warm, cold). In the periodic case (warm replication), using a scheduled task to reload an unmodifiable wrt terminology, synchronous refers to whether the caller's api is blocking or non-blocking ("happening or existing at the same time"). The refresh is an optimistic load so by its nature it is non-blocking and generally not user visible api, except when explicit called using |
When using a synchronous Caffeine Cache with
refreshAfterWrite
, throwing an exception in theCacheLoader
leads to the cache not being refreshed anymore.Scenario:
Expected behavior: The Exception should be completely swallowed and the existing entry still marked as expired so that the third call will lead to a reload again.
Minimal example using Caffeine 3.1.8:
There's also an exception logged by Caffeine on the call with the exception which is probably ok in order to log the source problem:
Interestingly, the above test is green when adding this method to the CacheLoader:
It appears that even though my cache was configured to be synchonous, some calls are still done asynchronous.
The text was updated successfully, but these errors were encountered: