-
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
LoadingCache with expireAfterAccess(...) effectively ignores invalidateAll() if cache reload is in progress #251
Comments
Unfortunately this is a limitation imposed by the underlying If no bounds are configured, then When a bound is configured, then The only solution to this would be if we forked I haven't looked at the internal iterators recently, so I don't recall if they block or not ( |
That is unfortunate. Thanks for the quick response. |
Sorry for the bad news. The only other option that I've thought of is to maintain an in-flight key set, e.g. |
I found the thread where I discussed this with Doug Lea.
|
This may be related to #193, in that a cache load takes precedence over a cache invalidate operation in some situations.
Consider the following scenario involving a LoadingCache:
invalidateAll()
on the cacheinvalidateAll()
completes, Thread-2 performs a cache read for the same key in step 2.For the initial read (on Thread-1), I would expect the result to be indeterminate; since there's a race between the lambda's execution and the write performed by Thread-2. However, I think it is reasonable to expect that after the call to
invalidateAll()
, the cache read performed by Thread-2 should result in a cache re-load, which would read the newly written value.For a LoadingCache without
expireAfterAccess(...)
/expireAfterWrite(...)
, this appears to be the case. TheinvalidateAll()
call is blocked until the initial cache load completes, and the second cache read causes a reload.However, if
expireAfterAccess(...)
/expireAfterWrite(...)
is called when creating the LoadingCache,invalidateAll()
is NOT blocked. The cache read on Thread-2 is still blocked by the cache load on Thread-1 (since they are accessing the same key), however, the cache is never actually invalidated. Subsequent cache reads yield the stale value from the initial load.Code to reproduce (Java version: 1.8.0_162, Caffeine version: 2.6.2):
Executing the above test yields the following output:
Notice how the cache invalidation completes immediately and the second cache read returns the stale cached result.
Executing the same test with the
expireAfterAccess(...)
removed yields the following output:Note that this time, the
invalidateAll()
operation is blocked until the initial cache load completes. Additionally, the second cache read results in a cache reload, which returns the updated value.In fairness, the javadocs for
invalidateAll(...)
do state that "The behavior of this operation is undefined for an entry that is being loaded and is otherwise not present." That said, it feels extreme that callinginvalidateAll(...)
will be ignored without any indication, if a load happens to be in-progress.Additionally for what it's worth, if the
invalidateAll(...)
call is replaced withinvalidate(KEY)
, the invalidation is blocked and the cache is invalidated as I would expect (even if.expireAfterAccess(...)
is present).Just wondering if this is all expected, and if so, is there a way to do an
invalidateAll()
operation and be guaranteed that the next cache read will result in a cache re-load?Thanks in advance!
The text was updated successfully, but these errors were encountered: