You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by da...@apache.org on 2026/10/06 04:40:18 UTC

(jackrabbit-oak) 07/15: OAK-12425 : add test coverage for receive() broadcast metadata replacement

This is an automated email from the ASF dual-hosted git repository.

rishabhdaim pushed a commit to branch issue/OAK-12436
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git

commit 4808204297ccddf16ab875ac76e33c44bbd831c1
Author: rishabhdaim <ri...@gmail.com>
AuthorDate: Wed Sep 30 14:33:45 2026 +0530

    OAK-12425 : add test coverage for receive() broadcast metadata replacement
    
    Adds a regression test verifying that NodeCache.receive() correctly
    replaces CacheMetadata for the received value, so a late eviction of
    the previously-cached (stale) value is not persisted while eviction
    of the newly-received value is.
    
    Co-authored-by: Copilot <22...@users.noreply.github.com>
---
 .../document/persistentCache/AsyncQueueTest.java   | 64 +++++++++++++++++++++-
 1 file changed, 63 insertions(+), 1 deletion(-)

diff --git a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/persistentCache/AsyncQueueTest.java b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/persistentCache/AsyncQueueTest.java
index d40bf8e8d2..13f5e7e3e1 100644
--- a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/persistentCache/AsyncQueueTest.java
+++ b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/persistentCache/AsyncQueueTest.java
@@ -25,12 +25,14 @@ import org.apache.jackrabbit.oak.cache.api.EvictionCause;
 import org.apache.jackrabbit.oak.cache.CacheLIRS;
 import org.apache.jackrabbit.oak.commons.collections.ListUtils;
 import org.apache.jackrabbit.oak.plugins.document.DocumentMKBuilderProvider;
+import org.apache.jackrabbit.oak.plugins.document.MemoryDiffCache;
 import org.apache.jackrabbit.oak.plugins.document.Path;
 import org.apache.jackrabbit.oak.plugins.document.PathRev;
 import org.apache.jackrabbit.oak.plugins.document.Revision;
 import org.apache.jackrabbit.oak.plugins.document.RevisionVector;
 import org.apache.jackrabbit.oak.plugins.document.persistentCache.async.CacheWriteQueue;
 import org.apache.jackrabbit.oak.plugins.document.util.StringValue;
+import org.h2.mvstore.WriteBuffer;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
@@ -39,6 +41,7 @@ import org.mockito.Mockito;
 
 import java.io.File;
 import java.io.IOException;
+import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -76,7 +79,7 @@ public class AsyncQueueTest {
     @Before
     public void setup() throws IOException {
         FileUtils.deleteDirectory(new File("target/cacheTest"));
-        pCache = new PersistentCache("target/cacheTest");
+        pCache = new PersistentCache("target/cacheTest,+asyncDiff");
         final AtomicReference<NodeCache<PathRev, StringValue>> nodeCacheRef = new AtomicReference<NodeCache<PathRev, StringValue>>();
         CacheLIRS<PathRev, StringValue> lirs = new CacheLIRS.Builder<PathRev, StringValue>().maximumSize(1).evictionCallback((key, value, cause) -> {
             if (nodeCacheRef.get() != null) {
@@ -133,6 +136,35 @@ public class AsyncQueueTest {
         assertEquals(asList(k), putActions);
     }
 
+    @Test
+    public void receivedBroadcastReplacesMetadataWithoutPersistingStaleValue() {
+        NodeCache<MemoryDiffCache.Key, StringValue> cache = newDiffCache(
+                CacheBuilder.<MemoryDiffCache.Key, StringValue>newBuilder().maximumSize(100).build());
+        DiffCacheWriteQueueWrapper writeQueue = (DiffCacheWriteQueueWrapper) cache.writeQueue;
+        MemoryDiffCache.Key key = new MemoryDiffCache.Key(Path.fromString("/broadcast"),
+                RevisionVector.fromString("r1-0-1"), RevisionVector.fromString("r2-0-1"));
+        StringValue receivedValue = new StringValue("received");
+        cache.put(key, VAL);
+        cache.getIfPresent(key);
+
+        WriteBuffer broadcast = new WriteBuffer(1024);
+        CacheType.DIFF.writeKey(broadcast, key);
+        broadcast.put((byte) 1);
+        CacheType.DIFF.writeValue(broadcast, receivedValue);
+        ByteBuffer buffer = broadcast.getBuffer();
+        buffer.rewind();
+        cache.receive(buffer);
+
+        cache.evicted(key, VAL, EvictionCause.SIZE);
+        assertEquals(emptyList(), writeQueue.putActions);
+
+        StringValue cachedValue = cache.getIfPresent(key);
+        assertEquals(receivedValue, cachedValue);
+        cache.evicted(key, cachedValue, EvictionCause.SIZE);
+        assertEquals(asList(key), writeQueue.putActions);
+        assertEquals(Collections.singletonList("received"), writeQueue.putValues);
+    }
+
     @Test
     public void staleEvictionShouldNotPersistReinsertedValue() {
         PathRev k = generatePathRev();
@@ -378,6 +410,15 @@ public class AsyncQueueTest {
         return cache;
     }
 
+    private NodeCache<MemoryDiffCache.Key, StringValue> newDiffCache(
+            Cache<MemoryDiffCache.Key, StringValue> memCache) {
+        NodeCache<MemoryDiffCache.Key, StringValue> cache =
+                (NodeCache<MemoryDiffCache.Key, StringValue>) pCache.wrap(
+                        builderProvider.newBuilder().getNodeStore(), null, memCache, CacheType.DIFF);
+        cache.writeQueue = new DiffCacheWriteQueueWrapper(cache.writeQueue);
+        return cache;
+    }
+
     private interface Replacement {
         void apply(NodeCache<PathRev, StringValue> cache, PathRev key, StringValue newValue);
     }
@@ -420,4 +461,25 @@ public class AsyncQueueTest {
         }
     }
 
+    private static class DiffCacheWriteQueueWrapper extends CacheWriteQueue<MemoryDiffCache.Key, StringValue> {
+
+        private final CacheWriteQueue<MemoryDiffCache.Key, StringValue> wrapped;
+
+        private final List<MemoryDiffCache.Key> putActions = new ArrayList<>();
+
+        private final List<String> putValues = new ArrayList<>();
+
+        public DiffCacheWriteQueueWrapper(CacheWriteQueue<MemoryDiffCache.Key, StringValue> wrapped) {
+            super(null, null, null);
+            this.wrapped = wrapped;
+        }
+
+        @Override
+        public boolean addPut(MemoryDiffCache.Key key, StringValue value) {
+            putActions.add(key);
+            putValues.add(value.asString());
+            return wrapped.addPut(key, value);
+        }
+    }
+
 }