diff --git a/redisson/src/main/java/org/redisson/RedissonLocalCachedMap.java b/redisson/src/main/java/org/redisson/RedissonLocalCachedMap.java index effcbe3f7..911f6ed12 100644 --- a/redisson/src/main/java/org/redisson/RedissonLocalCachedMap.java +++ b/redisson/src/main/java/org/redisson/RedissonLocalCachedMap.java @@ -61,6 +61,7 @@ public class RedissonLocalCachedMap extends RedissonMap implements R private int invalidateEntryOnChange; private SyncStrategy syncStrategy; private LocalCachedMapOptions.StoreMode storeMode; + private boolean storeCacheMiss; private LocalCacheListener listener; private LocalCacheView localCacheView; @@ -80,6 +81,7 @@ public class RedissonLocalCachedMap extends RedissonMap implements R private void init(String name, LocalCachedMapOptions options, RedissonClient redisson, EvictionScheduler evictionScheduler) { syncStrategy = options.getSyncStrategy(); storeMode = options.getStoreMode(); + storeCacheMiss = options.isStoreCacheMiss(); listener = new LocalCacheListener(name, commandExecutor, this, codec, options, cacheUpdateLogTime) { @@ -212,7 +214,7 @@ public class RedissonLocalCachedMap extends RedissonMap implements R CacheKey cacheKey = localCacheView.toCacheKey(key); CacheValue cacheValue = cache.get(cacheKey); - if (cacheValue != null && cacheValue.getValue() != null) { + if (cacheValue != null && (storeCacheMiss || cacheValue.getValue() != null)) { return RedissonPromise.newSucceededFuture((V) cacheValue.getValue()); } @@ -226,7 +228,7 @@ public class RedissonLocalCachedMap extends RedissonMap implements R return; } - if (value != null) { + if (storeCacheMiss || value != null) { cachePut(cacheKey, key, value); } }); @@ -244,7 +246,7 @@ public class RedissonLocalCachedMap extends RedissonMap implements R return result; } - + @Override protected RFuture putOperationAsync(K key, V value) { ByteBuf mapKey = encodeMapKey(key); diff --git a/redisson/src/main/java/org/redisson/api/LocalCachedMapOptions.java b/redisson/src/main/java/org/redisson/api/LocalCachedMapOptions.java index 813f6430f..819c6cf4e 100644 --- a/redisson/src/main/java/org/redisson/api/LocalCachedMapOptions.java +++ b/redisson/src/main/java/org/redisson/api/LocalCachedMapOptions.java @@ -136,6 +136,7 @@ public class LocalCachedMapOptions extends MapOptions { private long maxIdleInMillis; private CacheProvider cacheProvider; private StoreMode storeMode; + private boolean storeCacheMiss; protected LocalCachedMapOptions() { } @@ -149,6 +150,7 @@ public class LocalCachedMapOptions extends MapOptions { this.maxIdleInMillis = copy.maxIdleInMillis; this.cacheProvider = copy.cacheProvider; this.storeMode = copy.storeMode; + this.storeCacheMiss = copy.storeCacheMiss; } /** @@ -161,7 +163,8 @@ public class LocalCachedMapOptions extends MapOptions { * .evictionPolicy(EvictionPolicy.NONE) * .reconnectionStrategy(ReconnectionStrategy.NONE) * .cacheProvider(CacheProvider.REDISSON) - * .syncStrategy(SyncStrategy.INVALIDATE); + * .syncStrategy(SyncStrategy.INVALIDATE) + * .storeCacheMiss(false); * * * @param key type @@ -177,7 +180,8 @@ public class LocalCachedMapOptions extends MapOptions { .reconnectionStrategy(ReconnectionStrategy.NONE) .cacheProvider(CacheProvider.REDISSON) .storeMode(StoreMode.LOCALCACHE_REDIS) - .syncStrategy(SyncStrategy.INVALIDATE); + .syncStrategy(SyncStrategy.INVALIDATE) + .storeCacheMiss(false); } public CacheProvider getCacheProvider() { @@ -334,6 +338,21 @@ public class LocalCachedMapOptions extends MapOptions { return this; } + public boolean isStoreCacheMiss() { + return this.storeCacheMiss; + } + + /** + * Defines whether to store a cache miss into the local cache. + * + * @param storeCacheMiss - whether to store a cache miss into the local cache + * @return LocalCachedMapOptions instance + */ + public LocalCachedMapOptions storeCacheMiss(boolean storeCacheMiss) { + this.storeCacheMiss = storeCacheMiss; + return this; + } + @Override public LocalCachedMapOptions writeBehindBatchSize(int writeBehindBatchSize) { return (LocalCachedMapOptions) super.writeBehindBatchSize(writeBehindBatchSize); diff --git a/redisson/src/test/java/org/redisson/RedissonLocalCachedMapTest.java b/redisson/src/test/java/org/redisson/RedissonLocalCachedMapTest.java index fce4ef9d7..292066858 100644 --- a/redisson/src/test/java/org/redisson/RedissonLocalCachedMapTest.java +++ b/redisson/src/test/java/org/redisson/RedissonLocalCachedMapTest.java @@ -9,6 +9,8 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.ExecutionException; +import org.awaitility.Awaitility; +import org.awaitility.Durations; import org.junit.Assert; import org.junit.Test; import org.redisson.api.LocalCachedMapOptions; @@ -466,7 +468,29 @@ public class RedissonLocalCachedMapTest extends BaseMapTest { assertThat(map1.get("14")).isEqualTo(2); assertThat(map1.get("15")).isEqualTo(3); } - + + @Test + public void testGetStoringCacheMiss() { + RLocalCachedMap map = redisson.getLocalCachedMap("test", LocalCachedMapOptions.defaults().storeCacheMiss(true)); + Map cache = map.getCachedMap(); + + assertThat(map.get("19")).isNull(); + + Awaitility.await().atMost(Durations.ONE_SECOND) + .untilAsserted(() -> assertThat(cache.size()).isEqualTo(1)); + } + + @Test + public void testGetNotStoringCacheMiss() { + RLocalCachedMap map = redisson.getLocalCachedMap("test", LocalCachedMapOptions.defaults().storeCacheMiss(false)); + Map cache = map.getCachedMap(); + + assertThat(map.get("19")).isNull(); + + Awaitility.await().atMost(Durations.ONE_SECOND) + .untilAsserted(() -> assertThat(cache.size()).isEqualTo(0)); + } + @Test public void testGetAllCache() { RLocalCachedMap map = redisson.getLocalCachedMap("getAll", LocalCachedMapOptions.defaults());