diff --git a/redisson/src/main/java/org/redisson/RedissonKeys.java b/redisson/src/main/java/org/redisson/RedissonKeys.java index e8179cb99..dc3029d85 100644 --- a/redisson/src/main/java/org/redisson/RedissonKeys.java +++ b/redisson/src/main/java/org/redisson/RedissonKeys.java @@ -95,10 +95,10 @@ public class RedissonKeys implements RKeys { @Override public Iterable getKeysByPattern(String pattern, int count) { - return getKeysByPattern(RedisCommands.SCAN, pattern, count); + return getKeysByPattern(RedisCommands.SCAN, pattern, 0, count); } - public Iterable getKeysByPattern(RedisCommand command, String pattern, int count) { + public Iterable getKeysByPattern(RedisCommand command, String pattern, int limit, int count) { List> iterables = new ArrayList<>(); for (MasterSlaveEntry entry : commandExecutor.getConnectionManager().getEntrySet()) { Iterable iterable = new Iterable() { @@ -109,7 +109,17 @@ public class RedissonKeys implements RKeys { }; iterables.add(iterable); } - return new CompositeIterable(iterables); + return new CompositeIterable(iterables, limit); + } + + @Override + public Iterable getKeysWithLimit(int limit) { + return getKeysWithLimit(null, limit); + } + + @Override + public Iterable getKeysWithLimit(String pattern, int limit) { + return getKeysByPattern(RedisCommands.SCAN, pattern, limit, limit); } @Override diff --git a/redisson/src/main/java/org/redisson/RedissonLiveObjectService.java b/redisson/src/main/java/org/redisson/RedissonLiveObjectService.java index dadbe56b2..82a6e547a 100644 --- a/redisson/src/main/java/org/redisson/RedissonLiveObjectService.java +++ b/redisson/src/main/java/org/redisson/RedissonLiveObjectService.java @@ -628,7 +628,7 @@ public class RedissonLiveObjectService implements RLiveObjectService { } }); - return keys.getKeysByPattern(command, pattern, count); + return keys.getKeysByPattern(command, pattern, 0, count); } catch (NoSuchFieldException e) { throw new IllegalStateException(e); } diff --git a/redisson/src/main/java/org/redisson/api/RKeys.java b/redisson/src/main/java/org/redisson/api/RKeys.java index 7c833ade6..3a04729f0 100644 --- a/redisson/src/main/java/org/redisson/api/RKeys.java +++ b/redisson/src/main/java/org/redisson/api/RKeys.java @@ -25,6 +25,33 @@ import java.util.stream.Stream; */ public interface RKeys extends RKeysAsync { + /** + * Get keys using iterator with defined limit. + * Keys are traversed with SCAN operation. + * + * @param limit - limit of keys amount + * @return Iterable object + */ + Iterable getKeysWithLimit(int limit); + + /** + * Get keys using iterator with defined limit. + * Keys are traversed with SCAN operation. + *

+ * Supported glob-style patterns: + *

+ * h?llo subscribes to hello, hallo and hxllo + *

+ * h*llo subscribes to hllo and heeeello + *

+ * h[ae]llo subscribes to hello and hallo, but not hillo + * + * @param limit - limit of keys amount + * @param pattern - match pattern + * @return Iterable object + */ + Iterable getKeysWithLimit(String pattern, int limit); + /** * Move object to another database * @@ -183,7 +210,7 @@ public interface RKeys extends RKeysAsync { * @return Iterable object */ Iterable getKeysByPattern(String pattern, int count); - + /** * Get all keys using iterator. Keys traversing with SCAN operation. * Each SCAN operation loads up to 10 keys per request. diff --git a/redisson/src/main/java/org/redisson/misc/CompositeIterable.java b/redisson/src/main/java/org/redisson/misc/CompositeIterable.java index 4be3c4925..eca4003fa 100644 --- a/redisson/src/main/java/org/redisson/misc/CompositeIterable.java +++ b/redisson/src/main/java/org/redisson/misc/CompositeIterable.java @@ -23,11 +23,17 @@ public class CompositeIterable implements Iterable { private List> iterablesList; private Iterable[] iterables; + private int limit; public CompositeIterable(List> iterables) { this.iterablesList = iterables; } + public CompositeIterable(List> iterables, int limit) { + this.iterablesList = iterables; + this.limit = limit; + } + public CompositeIterable(Iterable... iterables) { this.iterables = iterables; } @@ -50,6 +56,6 @@ public class CompositeIterable implements Iterable { } } Iterator> listIterator = iterators.iterator(); - return new CompositeIterator(listIterator); + return new CompositeIterator(listIterator, limit); } } diff --git a/redisson/src/main/java/org/redisson/misc/CompositeIterator.java b/redisson/src/main/java/org/redisson/misc/CompositeIterator.java index 6f983cc4b..e407145a1 100644 --- a/redisson/src/main/java/org/redisson/misc/CompositeIterator.java +++ b/redisson/src/main/java/org/redisson/misc/CompositeIterator.java @@ -25,9 +25,12 @@ public class CompositeIterator implements Iterator { private Iterator> listIterator; private Iterator currentIterator; + private int limit; + private int counter; - public CompositeIterator(Iterator> iterators) { + public CompositeIterator(Iterator> iterators, int limit) { listIterator = iterators; + this.limit = limit; } @Override @@ -37,13 +40,24 @@ public class CompositeIterator implements Iterator { Iterator iterator = listIterator.next(); currentIterator = iterator; if (iterator.hasNext()) { - return true; + if (limit == 0) { + return true; + } else { + return limit >= counter + 1; + } } } return false; } - return currentIterator.hasNext(); + if (currentIterator.hasNext()) { + if (limit == 0) { + return true; + } else { + return limit >= counter + 1; + } + } + return false; } @Override @@ -52,6 +66,7 @@ public class CompositeIterator implements Iterator { throw new NoSuchElementException(); } + counter++; return currentIterator.next(); } diff --git a/redisson/src/test/java/org/redisson/RedissonKeysTest.java b/redisson/src/test/java/org/redisson/RedissonKeysTest.java index e3d9c7bfa..e5b649550 100644 --- a/redisson/src/test/java/org/redisson/RedissonKeysTest.java +++ b/redisson/src/test/java/org/redisson/RedissonKeysTest.java @@ -4,7 +4,6 @@ import static org.assertj.core.api.Assertions.assertThat; import java.io.IOException; import java.util.ArrayList; -import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -25,6 +24,41 @@ import org.redisson.connection.balancer.RandomLoadBalancer; public class RedissonKeysTest extends BaseTest { + @Test + public void testReadKeys() { + for (int i = 0; i < 10; i++) { + redisson.getBucket("test" + i).set(i); + } + + Iterable keys = redisson.getKeys().getKeysWithLimit(3); + assertThat(keys).hasSize(3); + + Iterable keys2 = redisson.getKeys().getKeysWithLimit(20); + assertThat(keys2).hasSize(10); + } + + @Test + public void testReadKeysPattern() { + for (int i = 0; i < 10; i++) { + redisson.getBucket("test" + i).set(i); + } + for (int i = 0; i < 5; i++) { + redisson.getBucket("red" + i).set(i); + } + + Iterable keys = redisson.getKeys().getKeysWithLimit("test*", 3); + assertThat(keys).hasSize(3); + + Iterable keys2 = redisson.getKeys().getKeysWithLimit("test*", 20); + assertThat(keys2).hasSize(10); + + Iterable keys3 = redisson.getKeys().getKeysWithLimit("red*", 3); + assertThat(keys3).hasSize(3); + + Iterable keys4 = redisson.getKeys().getKeysWithLimit("red*", 10); + assertThat(keys4).hasSize(5); + } + @Test public void testTouch() { redisson.getSet("test").add("1");