diff --git a/src/main/java/org/redisson/RedissonSetCache.java b/src/main/java/org/redisson/RedissonSetCache.java index 656c55b1b..ecc358281 100644 --- a/src/main/java/org/redisson/RedissonSetCache.java +++ b/src/main/java/org/redisson/RedissonSetCache.java @@ -25,6 +25,7 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; +import java.util.Set; import java.util.concurrent.TimeUnit; import org.redisson.client.codec.Codec; @@ -220,7 +221,33 @@ public class RedissonSetCache extends RedissonExpirable implements RSetCache< }; } - private Future> readAllAsync() { + @Override + public Set readAll() { + return get(readAllAsync()); + } + + @Override + public Future> readAllAsync() { + return commandExecutor.evalReadAsync(getName(), codec, RedisCommands.EVAL_SET, + "local expireHead = redis.call('zrange', KEYS[2], 0, 0, 'withscores');" + + "local keys = redis.call('hkeys', KEYS[1]);" + + "local maxDate = ARGV[1]; " + + "local minExpireDate = 92233720368547758;" + + "if #expireHead == 2 and tonumber(expireHead[2]) <= tonumber(maxDate) then " + + "for i = #keys, 1, -1 do " + + "local key = keys[i]; " + + "local expireDate = redis.call('zscore', KEYS[2], key); " + + "if expireDate ~= false and tonumber(expireDate) <= tonumber(maxDate) then " + + "minExpireDate = math.min(tonumber(expireDate), minExpireDate); " + + "table.remove(keys, i); " + + "end;" + + "end;" + + "end; " + + "return redis.call('hmget', KEYS[1], unpack(keys));", + Arrays.asList(getName(), getTimeoutSetName()), System.currentTimeMillis()); + } + + private Future> readAllasListAsync() { return commandExecutor.evalReadAsync(getName(), codec, RedisCommands.EVAL_LIST, "local expireHead = redis.call('zrange', KEYS[2], 0, 0, 'withscores');" + "local keys = redis.call('hkeys', KEYS[1]);" + @@ -242,13 +269,13 @@ public class RedissonSetCache extends RedissonExpirable implements RSetCache< @Override public Object[] toArray() { - List res = (List) get(readAllAsync()); + List res = get(readAllasListAsync()); return res.toArray(); } @Override public T[] toArray(T[] a) { - List res = (List) get(readAllAsync()); + List res = get(readAllasListAsync()); return res.toArray(a); } diff --git a/src/main/java/org/redisson/client/protocol/RedisCommands.java b/src/main/java/org/redisson/client/protocol/RedisCommands.java index 65635267a..c9bace756 100644 --- a/src/main/java/org/redisson/client/protocol/RedisCommands.java +++ b/src/main/java/org/redisson/client/protocol/RedisCommands.java @@ -163,6 +163,7 @@ public interface RedisCommands { RedisStrictCommand EVAL_LONG = new RedisStrictCommand("EVAL"); RedisStrictCommand EVAL_VOID = new RedisStrictCommand("EVAL", new VoidReplayConvertor()); RedisCommand> EVAL_LIST = new RedisCommand>("EVAL", new ObjectListReplayDecoder()); + RedisCommand> EVAL_SET = new RedisCommand>("EVAL", new ObjectSetReplayDecoder()); RedisCommand EVAL_OBJECT = new RedisCommand("EVAL"); RedisCommand EVAL_MAP_VALUE = new RedisCommand("EVAL", ValueType.MAP_VALUE); RedisCommand> EVAL_MAP_VALUE_LIST = new RedisCommand>("EVAL", new ObjectListReplayDecoder(), ValueType.MAP_VALUE); diff --git a/src/main/java/org/redisson/core/RSetCache.java b/src/main/java/org/redisson/core/RSetCache.java index 6707b9b52..a2db04c93 100644 --- a/src/main/java/org/redisson/core/RSetCache.java +++ b/src/main/java/org/redisson/core/RSetCache.java @@ -64,4 +64,11 @@ public interface RSetCache extends Set, RExpirable, RSetCacheAsync { @Override int size(); + /** + * Read all elements at once + * + * @return + */ + Set readAll(); + } diff --git a/src/main/java/org/redisson/core/RSetCacheAsync.java b/src/main/java/org/redisson/core/RSetCacheAsync.java index b4f6b2eba..064b03897 100644 --- a/src/main/java/org/redisson/core/RSetCacheAsync.java +++ b/src/main/java/org/redisson/core/RSetCacheAsync.java @@ -15,6 +15,7 @@ */ package org.redisson.core; +import java.util.Set; import java.util.concurrent.TimeUnit; import io.netty.util.concurrent.Future; @@ -51,4 +52,11 @@ public interface RSetCacheAsync extends RCollectionAsync { @Override Future sizeAsync(); + /** + * Read all elements at once + * + * @return + */ + Future> readAllAsync(); + } diff --git a/src/test/java/org/redisson/RedissonSetCacheTest.java b/src/test/java/org/redisson/RedissonSetCacheTest.java index 61e11cae0..1c1636f95 100644 --- a/src/test/java/org/redisson/RedissonSetCacheTest.java +++ b/src/test/java/org/redisson/RedissonSetCacheTest.java @@ -9,6 +9,7 @@ import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; +import static org.assertj.core.api.Assertions.*; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.Assert; @@ -267,6 +268,17 @@ public class RedissonSetCacheTest extends BaseTest { Assert.assertEquals(5, set.size()); } + @Test + public void testReadAll() { + RSetCache set = redisson.getSetCache("set"); + set.add(1, 2, TimeUnit.MINUTES); + set.add(2); + set.add(3); + set.add(4); + set.add(5); + + assertThat(set.readAll()).containsOnly(1, 2, 3, 4, 5); + } @Test public void testRetainAllEmpty() {