From 7265dbe93a7c27f2b2edd29fbc577f7a399e0f83 Mon Sep 17 00:00:00 2001 From: Nikita Koksharov Date: Wed, 6 Dec 2023 10:50:24 +0300 Subject: [PATCH] Fixed - transactional Map and MapCache keySet method returns inconsistent state. --- .../transaction/BaseTransactionalMap.java | 19 ++++++++++++++++++- .../transaction/RedissonTransactionalMap.java | 8 +++++++- .../RedissonTransactionalMapCache.java | 6 ++++++ .../RedissonBaseTransactionalMapTest.java | 4 ++-- .../RedissonTransactionalMapCacheTest.java | 4 ++-- 5 files changed, 35 insertions(+), 6 deletions(-) diff --git a/redisson/src/main/java/org/redisson/transaction/BaseTransactionalMap.java b/redisson/src/main/java/org/redisson/transaction/BaseTransactionalMap.java index 328f614b7..be1aae7fd 100644 --- a/redisson/src/main/java/org/redisson/transaction/BaseTransactionalMap.java +++ b/redisson/src/main/java/org/redisson/transaction/BaseTransactionalMap.java @@ -615,7 +615,24 @@ public class BaseTransactionalMap extends BaseTransactionalObject { }); return new CompletableFutureWrapper<>(f); } - + + protected Set keySet(String pattern, int count) { + Set keys = map.keySet(pattern, count); + return keys.stream() + .map(k -> Collections.singletonMap(k, toKeyHash(k))) + .filter(k -> { + HashValue hash = k.values().iterator().next(); + if (state.get(hash) == null + || state.get(hash) != BaseTransactionalMap.MapEntry.NULL) { + return true; + } + return false; + }) + .map(m -> m.keySet().iterator().next()) + .collect(Collectors.toSet()); + } + + protected RFuture removeOperationAsync(K key) { long threadId = Thread.currentThread().getId(); return executeLocked(key, () -> { diff --git a/redisson/src/main/java/org/redisson/transaction/RedissonTransactionalMap.java b/redisson/src/main/java/org/redisson/transaction/RedissonTransactionalMap.java index 21defa555..416630954 100644 --- a/redisson/src/main/java/org/redisson/transaction/RedissonTransactionalMap.java +++ b/redisson/src/main/java/org/redisson/transaction/RedissonTransactionalMap.java @@ -211,7 +211,13 @@ public class RedissonTransactionalMap extends RedissonMap { checkState(); return transactionalMap.removeOperationAsync(key); } - + + @Override + public Set keySet(String pattern, int count) { + checkState(); + return transactionalMap.keySet(pattern, count); + } + @Override protected RFuture removeOperationAsync(Object key, Object value) { checkState(); diff --git a/redisson/src/main/java/org/redisson/transaction/RedissonTransactionalMapCache.java b/redisson/src/main/java/org/redisson/transaction/RedissonTransactionalMapCache.java index 0befcfb50..e0be74cb8 100644 --- a/redisson/src/main/java/org/redisson/transaction/RedissonTransactionalMapCache.java +++ b/redisson/src/main/java/org/redisson/transaction/RedissonTransactionalMapCache.java @@ -332,4 +332,10 @@ public class RedissonTransactionalMapCache extends RedissonMapCache throw new UnsupportedOperationException("getReadWriteLock method is not supported in transaction"); } + @Override + public Set keySet(String pattern, int count) { + checkState(); + return transactionalMap.keySet(pattern, count); + } + } diff --git a/redisson/src/test/java/org/redisson/transaction/RedissonBaseTransactionalMapTest.java b/redisson/src/test/java/org/redisson/transaction/RedissonBaseTransactionalMapTest.java index a92277902..4656bf4d3 100644 --- a/redisson/src/test/java/org/redisson/transaction/RedissonBaseTransactionalMapTest.java +++ b/redisson/src/test/java/org/redisson/transaction/RedissonBaseTransactionalMapTest.java @@ -2,7 +2,7 @@ package org.redisson.transaction; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import org.redisson.BaseTest; +import org.redisson.RedisDockerTest; import org.redisson.api.RMap; import org.redisson.api.RTransaction; import org.redisson.api.TransactionOptions; @@ -17,7 +17,7 @@ import java.util.concurrent.TimeUnit; import static org.assertj.core.api.Assertions.assertThat; -public abstract class RedissonBaseTransactionalMapTest extends BaseTest { +public abstract class RedissonBaseTransactionalMapTest extends RedisDockerTest { protected abstract RMap getMap(); diff --git a/redisson/src/test/java/org/redisson/transaction/RedissonTransactionalMapCacheTest.java b/redisson/src/test/java/org/redisson/transaction/RedissonTransactionalMapCacheTest.java index 7b285232e..8600e7961 100644 --- a/redisson/src/test/java/org/redisson/transaction/RedissonTransactionalMapCacheTest.java +++ b/redisson/src/test/java/org/redisson/transaction/RedissonTransactionalMapCacheTest.java @@ -14,13 +14,13 @@ import static org.assertj.core.api.Assertions.assertThat; public class RedissonTransactionalMapCacheTest extends RedissonBaseTransactionalMapTest { @Test - public void testSyncWait() throws IOException, InterruptedException { + public void testSyncWait() { String mapCacheName = "map"; String dataKey = "key"; Config redisConfig = new Config(); redisConfig.useReplicatedServers() - .addNodeAddress(RedisRunner.getDefaultRedisServerBindAddressAndPort()); + .addNodeAddress(redisson.getConfig().useSingleServer().getAddress()); RedissonClient client = Redisson.create(redisConfig); RTransaction transaction = client.createTransaction(TransactionOptions.defaults());