Repository navigation
[Bug] LRU2Cache.put ignores updates for keys already promoted to the main cache #16500
Description
Pre-check
- I am sure that all the content I provide is in English.
Search before asking
- I had searched in the issues and found no similar issues.
Apache Dubbo Component
Java SDK (apache/dubbo)
Dubbo Version
Apache Dubbo source: 3.3.7-SNAPSHOT, branch 3.3, commit ae809de2fc81b408194240965eb20bf27e6971df.
Windows, OpenJDK 21, Maven 3.6.3.
Verification used an isolated Maven/JUnit harness: eight relevant implementation/interface files were copied byte-for-byte from this commit, with released Dubbo 3.3.6 artifacts supplying supporting dependencies. The paths under review were compiled from the current source, not taken from those dependency jars. This is not a full current-branch reactor build or a networked RPC deployment.
Steps to reproduce this issue
After a key has been promoted into the main cache by two puts, a subsequent put for the same key does not update its value. The third put only records the key in the history/pre-cache, while the main cache keeps the earlier value.
Minimal JUnit Jupiter regression:
import org.apache.dubbo.common.utils.LRU2Cache;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
class LRU2UpdateTest {
@Test void promotedKeyMustAcceptUpdates() {
LRU2Cache<String, String> cache = new LRU2Cache<>(10);
cache.put("key", "v1"); // history
cache.put("key", "v1"); // promotion
assertEquals("v1", cache.get("key"));
cache.put("key", "v2"); // update existing key
assertEquals("v2", cache.get("key")); // FAILS: v1
}
}The same result was reproduced through the current org.apache.dubbo.cache.support.lru.LruCache implementation:
LruCache cache = new LruCache(
URL.valueOf("dubbo://127.0.0.1:20880/example.Service?cache.size=10"));
cache.put("key", "v1");
cache.put("key", "v1");
cache.put("key", "v2");
assertEquals("v2", cache.get("key")); // FAILS: v1No concurrency, registry, or remote service is needed.
What you expected to happen
put must update an entry that is already in the main cache; the two-touch admission policy for a new key should not discard an update to an admitted key.
Actual output from both regressions:
LRU2 after update: v1
LruCache plugin after update: v1
expected: <v2> but was: <v1>
Anything else
Root cause: LRU2Cache.put checks only preCache.containsKey(key). Promotion removes the key from preCache; an update therefore enters the history-only branch even though super.containsKey(key) is true. The cache plugin delegates writes directly to this method.
A possible fix is to handle keys already in the main cache before applying new-key admission. Add a regression for the third write after promotion.
Searched LRU2Cache and LRU update-related issues/PRs. #16170 concerns computeIfAbsent concurrency and #16038/#16053 concern capacity reduction; this report concerns deterministic, single-threaded put updates and is independent of those changes.
Do you have a (mini) reproduction demo?
- Yes, I have a minimal reproduction demo to help resolve this issue more effectively!
Are you willing to submit a pull request to fix on your own?
- Yes I am willing to submit a pull request on my own!
Code of Conduct
- I agree to follow this project's Code of Conduct
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsTodo
Activity
fix: update entries already admitted to LRU2Cache