Fixed - RLocalCachedMap doesn't used MapLoader if storeMode = LOCALCACHE. #3617

pull/3663/head
Nikita Koksharov 4 years ago
parent 8ba07e5874
commit 76d134c7ec

@ -29,7 +29,10 @@ import org.redisson.client.codec.StringCodec;
import org.redisson.client.protocol.RedisCommand; import org.redisson.client.protocol.RedisCommand;
import org.redisson.client.protocol.RedisCommands; import org.redisson.client.protocol.RedisCommands;
import org.redisson.client.protocol.convertor.NumberConvertor; import org.redisson.client.protocol.convertor.NumberConvertor;
import org.redisson.client.protocol.decoder.*; import org.redisson.client.protocol.decoder.MapKeyDecoder;
import org.redisson.client.protocol.decoder.ObjectMapEntryReplayDecoder;
import org.redisson.client.protocol.decoder.ObjectMapReplayDecoder;
import org.redisson.client.protocol.decoder.ObjectSetReplayDecoder;
import org.redisson.command.CommandAsyncExecutor; import org.redisson.command.CommandAsyncExecutor;
import org.redisson.eviction.EvictionScheduler; import org.redisson.eviction.EvictionScheduler;
import org.redisson.misc.RPromise; import org.redisson.misc.RPromise;
@ -197,9 +200,28 @@ public class RedissonLocalCachedMap<K, V> extends RedissonMap<K, V> implements R
checkKey(key); checkKey(key);
CacheKey cacheKey = localCacheView.toCacheKey(key); CacheKey cacheKey = localCacheView.toCacheKey(key);
if (!cache.containsKey(cacheKey)) { CacheValue cacheValue = cache.get(cacheKey);
if (cacheValue == null) {
if (storeMode == LocalCachedMapOptions.StoreMode.LOCALCACHE) { if (storeMode == LocalCachedMapOptions.StoreMode.LOCALCACHE) {
return RedissonPromise.newSucceededFuture(false); if (hasNoLoader()) {
return RedissonPromise.newSucceededFuture(false);
}
RPromise<Boolean> result = new RedissonPromise<>();
RPromise<V> valuePromise = new RedissonPromise<>();
loadValue((K) key, valuePromise, false);
valuePromise.onComplete((value, ex) -> {
if (ex != null) {
result.tryFailure(ex);
return;
}
if (storeCacheMiss || value != null) {
cachePut(cacheKey, key, value);
}
result.trySuccess(value != null);
});
return result;
} }
RPromise<V> promise = new RedissonPromise<>(); RPromise<V> promise = new RedissonPromise<>();
@ -214,7 +236,8 @@ public class RedissonLocalCachedMap<K, V> extends RedissonMap<K, V> implements R
}); });
return containsKeyAsync(key, promise); return containsKeyAsync(key, promise);
} }
return RedissonPromise.newSucceededFuture(true);
return RedissonPromise.newSucceededFuture(cacheValue.getValue() != null);
} }
@Override @Override
@ -243,7 +266,23 @@ public class RedissonLocalCachedMap<K, V> extends RedissonMap<K, V> implements R
} }
if (storeMode == LocalCachedMapOptions.StoreMode.LOCALCACHE) { if (storeMode == LocalCachedMapOptions.StoreMode.LOCALCACHE) {
return RedissonPromise.newSucceededFuture(null); if (hasNoLoader()) {
return RedissonPromise.newSucceededFuture(null);
}
RPromise<V> result = new RedissonPromise<>();
loadValue((K) key, result, false);
result.onComplete((value, ex) -> {
if (ex != null) {
result.tryFailure(ex);
return;
}
if (storeCacheMiss || value != null) {
cachePut(cacheKey, key, value);
}
});
return result;
} }
RFuture<V> future = super.getAsync((K) key); RFuture<V> future = super.getAsync((K) key);
@ -591,11 +630,30 @@ public class RedissonLocalCachedMap<K, V> extends RedissonMap<K, V> implements R
} }
} }
RPromise<Map<K, V>> promise = new RedissonPromise<>();
if (storeMode == LocalCachedMapOptions.StoreMode.LOCALCACHE) { if (storeMode == LocalCachedMapOptions.StoreMode.LOCALCACHE) {
return RedissonPromise.newSucceededFuture(result); if (hasNoLoader()) {
return RedissonPromise.newSucceededFuture(result);
}
Set<K> newKeys = new HashSet<>(keys);
newKeys.removeAll(result.keySet());
if (!newKeys.isEmpty()) {
loadAllAsync(newKeys, false, 1, result).onComplete((r, ex) -> {
if (ex != null) {
promise.tryFailure(ex);
return;
}
promise.trySuccess(result);
});
} else {
promise.trySuccess(result);
}
return promise;
} }
RPromise<Map<K, V>> promise = new RedissonPromise<Map<K, V>>();
RFuture<Map<K, V>> future = super.getAllAsync(mapKeys); RFuture<Map<K, V>> future = super.getAllAsync(mapKeys);
future.onComplete((map, e) -> { future.onComplete((map, e) -> {
if (e != null) { if (e != null) {

@ -623,6 +623,11 @@ public class RedissonMap<K, V> extends RedissonExpirable implements RMap<K, V> {
newKeys.removeAll(res.keySet()); newKeys.removeAll(res.keySet());
loadAllAsync(newKeys, false, 1, res).onComplete((r, ex) -> { loadAllAsync(newKeys, false, 1, res).onComplete((r, ex) -> {
if (ex != null) {
result.tryFailure(ex);
return;
}
result.trySuccess(res); result.trySuccess(res);
}); });
} else { } else {
@ -1212,7 +1217,7 @@ public class RedissonMap<K, V> extends RedissonExpirable implements RMap<K, V> {
return loadAllAsync((Iterable<K>) keys, replaceExistingValues, parallelism, null); return loadAllAsync((Iterable<K>) keys, replaceExistingValues, parallelism, null);
} }
private RFuture<Void> loadAllAsync(Iterable<? extends K> keys, boolean replaceExistingValues, int parallelism, Map<K, V> loadedEntires) { protected RFuture<Void> loadAllAsync(Iterable<? extends K> keys, boolean replaceExistingValues, int parallelism, Map<K, V> loadedEntires) {
if (parallelism < 1) { if (parallelism < 1) {
throw new IllegalArgumentException("parallelism can't be lower than 1"); throw new IllegalArgumentException("parallelism can't be lower than 1");
} }

@ -127,7 +127,7 @@ public abstract class BaseMapTest extends BaseTest {
} }
private void destroy(RMap<?, ?> map) { protected void destroy(RMap<?, ?> map) {
if (map instanceof RDestroyable) { if (map instanceof RDestroyable) {
((RDestroyable) map).destroy(); ((RDestroyable) map).destroy();
} }
@ -1479,6 +1479,9 @@ public abstract class BaseMapTest extends BaseTest {
map.put("0", "00"); map.put("0", "00");
assertThat(map.get("0")).isEqualTo("00"); assertThat(map.get("0")).isEqualTo("00");
assertThat(map.size()).isEqualTo(2); assertThat(map.size()).isEqualTo(2);
assertThat(map.containsKey("2")).isTrue();
assertThat(map.size()).isEqualTo(3);
Map<String, String> s = map.getAll(new HashSet<>(Arrays.asList("1", "2", "9", "3"))); Map<String, String> s = map.getAll(new HashSet<>(Arrays.asList("1", "2", "9", "3")));
Map<String, String> expectedMap = new HashMap<>(); Map<String, String> expectedMap = new HashMap<>();

@ -91,6 +91,38 @@ public class RedissonLocalCachedMapTest extends BaseMapTest {
} }
@Test
public void testMapLoaderGet() {
Map<String, String> cache = new HashMap<>();
cache.put("1", "11");
cache.put("2", "22");
cache.put("3", "33");
LocalCachedMapOptions<String, String> options = LocalCachedMapOptions.<String, String>defaults()
.storeMode(LocalCachedMapOptions.StoreMode.LOCALCACHE).loader(createMapLoader(cache));
RMap<String, String> map = redisson.getLocalCachedMap("test", options);
assertThat(map.size()).isEqualTo(0);
assertThat(map.get("1")).isEqualTo("11");
assertThat(map.size()).isEqualTo(1);
assertThat(map.get("0")).isNull();
map.put("0", "00");
assertThat(map.get("0")).isEqualTo("00");
assertThat(map.size()).isEqualTo(2);
assertThat(map.containsKey("2")).isTrue();
assertThat(map.size()).isEqualTo(3);
Map<String, String> s = map.getAll(new HashSet<>(Arrays.asList("1", "2", "9", "3")));
Map<String, String> expectedMap = new HashMap<>();
expectedMap.put("1", "11");
expectedMap.put("2", "22");
expectedMap.put("3", "33");
assertThat(s).isEqualTo(expectedMap);
assertThat(map.size()).isEqualTo(4);
destroy(map);
}
@Override @Override
protected <K, V> RMap<K, V> getMap(String name) { protected <K, V> RMap<K, V> getMap(String name) {
return redisson.getLocalCachedMap(name, LocalCachedMapOptions.<K, V>defaults()); return redisson.getLocalCachedMap(name, LocalCachedMapOptions.<K, V>defaults());
@ -328,7 +360,9 @@ public class RedissonLocalCachedMapTest extends BaseMapTest {
assertThat(map2.get("1")).isEqualTo(1); assertThat(map2.get("1")).isEqualTo(1);
assertThat(map2.get("2")).isEqualTo(2); assertThat(map2.get("2")).isEqualTo(2);
Thread.sleep(50);
assertThat(cache1.size()).isEqualTo(2); assertThat(cache1.size()).isEqualTo(2);
assertThat(cache2.size()).isEqualTo(2); assertThat(cache2.size()).isEqualTo(2);

Loading…
Cancel
Save