From fb2e29b39730821e1983dfc6df9f8c78642fc9f4 Mon Sep 17 00:00:00 2001 From: Chen Li <717626659@qq.com> Date: Thu, 17 Feb 2022 13:57:31 +0800 Subject: [PATCH 1/3] Support for scan in RedisTemplate. --- .../data/redis/core/RedisOperations.java | 12 +++++++++++- .../data/redis/core/RedisTemplate.java | 16 +++++++++++++++- .../core/RedisTemplateIntegrationTests.java | 17 +++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/springframework/data/redis/core/RedisOperations.java b/src/main/java/org/springframework/data/redis/core/RedisOperations.java index d4404435d7..67fb405577 100644 --- a/src/main/java/org/springframework/data/redis/core/RedisOperations.java +++ b/src/main/java/org/springframework/data/redis/core/RedisOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2021 the original author or authors. + * Copyright 2011-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -45,6 +45,7 @@ * @author Mark Paluch * @author ihaohong * @author Todd Merrill + * @author Chen Li */ public interface RedisOperations { @@ -259,6 +260,15 @@ T execute(RedisScript script, RedisSerializer argsSerializer, RedisSer @Nullable Set keys(K pattern); + /** + * Use a {@link Cursor} to iterate over keys. + * + * @param options must not be {@literal null}. + * @return never {@literal null}. + * @see Redis Documentation: SCAN + */ + Cursor scan(ScanOptions options); + /** * Return a random key from the keyspace. * diff --git a/src/main/java/org/springframework/data/redis/core/RedisTemplate.java b/src/main/java/org/springframework/data/redis/core/RedisTemplate.java index 9075f96933..d67295496a 100644 --- a/src/main/java/org/springframework/data/redis/core/RedisTemplate.java +++ b/src/main/java/org/springframework/data/redis/core/RedisTemplate.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2021 the original author or authors. + * Copyright 2011-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -83,6 +83,7 @@ * @author Mark Paluch * @author Denis Zavedeev * @author ihaohong + * @author Chen Li * @param the Redis key type against which the template works (usually a String) * @param the Redis value type against which the template works * @see StringRedisTemplate @@ -897,6 +898,19 @@ public Set keys(K pattern) { return keySerializer != null ? SerializationUtils.deserialize(rawKeys, keySerializer) : (Set) rawKeys; } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.core.RedisOperations#scan(java.lang.Object) + */ + @Override + public Cursor scan(ScanOptions options) { + Assert.notNull(options, "ScanOptions must not be null!"); + + return executeWithStickyConnection( + (RedisCallback>) connection -> new ConvertingCursor<>(connection.scan(options), + this::deserializeKey)); + } + /* * (non-Javadoc) * @see org.springframework.data.redis.core.RedisOperations#persist(java.lang.Object) diff --git a/src/test/java/org/springframework/data/redis/core/RedisTemplateIntegrationTests.java b/src/test/java/org/springframework/data/redis/core/RedisTemplateIntegrationTests.java index caaecbb800..8f470920d3 100644 --- a/src/test/java/org/springframework/data/redis/core/RedisTemplateIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/core/RedisTemplateIntegrationTests.java @@ -62,6 +62,7 @@ * @author Mark Paluch * @author ihaohong * @author Hendrik Duerkop + * @author Chen Li */ @MethodSource("testParams") public class RedisTemplateIntegrationTests { @@ -126,6 +127,22 @@ void testKeys() throws Exception { assertThat(redisTemplate.keys(keyPattern)).isNotNull(); } + @ParameterizedRedisTest // GH-2260 + void testScan() { + K key1 = keyFactory.instance(); + V value1 = valueFactory.instance(); + assumeThat(key1 instanceof String || key1 instanceof byte[]).isTrue(); + redisTemplate.opsForValue().set(key1, value1); + Cursor cursor = redisTemplate.scan(ScanOptions.scanOptions().count(1).build()); + long count = 0; + while (cursor.hasNext()) { + assertThat(cursor.next()).isEqualTo(key1); + count++; + } + cursor.close(); + assertThat(count).isEqualTo(1); + } + @SuppressWarnings("rawtypes") @ParameterizedRedisTest void testTemplateNotInitialized() throws Exception { From 9a8c032693fbdae357631b471ac7217981ce8c8b Mon Sep 17 00:00:00 2001 From: Chen Li <717626659@qq.com> Date: Thu, 17 Feb 2022 14:36:55 +0800 Subject: [PATCH 2/3] Add notification for scan. --- .../org/springframework/data/redis/core/RedisOperations.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/springframework/data/redis/core/RedisOperations.java b/src/main/java/org/springframework/data/redis/core/RedisOperations.java index 67fb405577..6420746ca1 100644 --- a/src/main/java/org/springframework/data/redis/core/RedisOperations.java +++ b/src/main/java/org/springframework/data/redis/core/RedisOperations.java @@ -262,6 +262,7 @@ T execute(RedisScript script, RedisSerializer argsSerializer, RedisSer /** * Use a {@link Cursor} to iterate over keys. + * Important: Call {@link Cursor#close()} when done to avoid resource leak. * * @param options must not be {@literal null}. * @return never {@literal null}. From b0c7b11fae0deac872df8da2d87508d71f375f7e Mon Sep 17 00:00:00 2001 From: Chen Li <717626659@qq.com> Date: Thu, 17 Feb 2022 14:44:01 +0800 Subject: [PATCH 3/3] New line for notification. --- .../org/springframework/data/redis/core/RedisOperations.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/springframework/data/redis/core/RedisOperations.java b/src/main/java/org/springframework/data/redis/core/RedisOperations.java index 6420746ca1..e9a153b569 100644 --- a/src/main/java/org/springframework/data/redis/core/RedisOperations.java +++ b/src/main/java/org/springframework/data/redis/core/RedisOperations.java @@ -261,7 +261,7 @@ T execute(RedisScript script, RedisSerializer argsSerializer, RedisSer Set keys(K pattern); /** - * Use a {@link Cursor} to iterate over keys. + * Use a {@link Cursor} to iterate over keys.
* Important: Call {@link Cursor#close()} when done to avoid resource leak. * * @param options must not be {@literal null}.