Skip to content

[Bug] LRU2Cache.put ignores updates for keys already promoted to the main cache #16500

Open

Description

@hickey-ai

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: v1

No 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

Activity

  1. added a commit that references this issue on Oct 13, 2026
    d419b72
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions