diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc
index 53d43c50b..7d063b6ab 100644
--- a/src/main/asciidoc/new-features.adoc
+++ b/src/main/asciidoc/new-features.adoc
@@ -7,6 +7,7 @@ This section briefly covers items that are new and noteworthy in the latest rele
== New in Spring Data Redis 2.6
* Support for `SubscriptionListener` when using `MessageListener` for subscription confirmation callbacks. `ReactiveRedisMessageListenerContainer` and `ReactiveRedisOperations` provide `receiveLater(…)` and `listenToLater(…)` methods to await until Redis acknowledges the subscription.
+* Support Redis 6.2 commands (`LPOP`/`RPOP` with `count`).
[[new-in-2.5.0]]
== New in Spring Data Redis 2.5
diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveListCommands.java b/src/main/java/org/springframework/data/redis/connection/ReactiveListCommands.java
index cb7141684..33516275b 100644
--- a/src/main/java/org/springframework/data/redis/connection/ReactiveListCommands.java
+++ b/src/main/java/org/springframework/data/redis/connection/ReactiveListCommands.java
@@ -922,6 +922,7 @@ public interface ReactiveListCommands {
*
* @param count
* @return a new {@link LSetCommand} with {@literal value} applied.
+ * @since 2.6
*/
public PopCommand count(long count) {
return new PopCommand(getKey(), count, direction);
@@ -954,12 +955,13 @@ public interface ReactiveListCommands {
}
/**
- * Removes and returns first element in list stored at {@literal key}.
+ * Removes and returns first {@code count} elements in list stored at {@literal key}.
*
* @param key must not be {@literal null}.
* @param count
* @return
* @see Redis Documentation: LPOP
+ * @since 2.6
*/
default Flux lPop(ByteBuffer key, long count) {
@@ -983,12 +985,13 @@ public interface ReactiveListCommands {
}
/**
- * Removes and returns last element in list stored at {@literal key}.
+ * Removes and returns last {@code count} elements in list stored at {@literal key}.
*
* @param key must not be {@literal null}.
* @param count
* @return
* @see Redis Documentation: RPOP
+ * @since 2.6
*/
default Flux rPop(ByteBuffer key, long count) {
diff --git a/src/main/java/org/springframework/data/redis/connection/RedisListCommands.java b/src/main/java/org/springframework/data/redis/connection/RedisListCommands.java
index bf60d6a0a..50a58ca10 100644
--- a/src/main/java/org/springframework/data/redis/connection/RedisListCommands.java
+++ b/src/main/java/org/springframework/data/redis/connection/RedisListCommands.java
@@ -202,12 +202,13 @@ public interface RedisListCommands {
byte[] lPop(byte[] key);
/**
- * Removes and returns first element in list stored at {@code key}.
+ * Removes and returns first {@code} elements in list stored at {@code key}.
*
* @param key must not be {@literal null}.
* @param count
* @return {@literal null} when key does not exist or used in pipeline / transaction.
* @see Redis Documentation: LPOP
+ * @since 2.6
*/
@Nullable
List lPop(byte[] key, long count);
@@ -223,12 +224,13 @@ public interface RedisListCommands {
byte[] rPop(byte[] key);
/**
- * Removes and returns last element in list stored at {@code key}.
+ * Removes and returns last {@code} elements in list stored at {@code key}.
*
* @param key must not be {@literal null}.
* @param count
* @return {@literal null} when key does not exist or used in pipeline / transaction.
* @see Redis Documentation: RPOP
+ * @since 2.6
*/
@Nullable
List rPop(byte[] key, long count);
diff --git a/src/main/java/org/springframework/data/redis/connection/StringRedisConnection.java b/src/main/java/org/springframework/data/redis/connection/StringRedisConnection.java
index e57ccc4c4..5b812cedb 100644
--- a/src/main/java/org/springframework/data/redis/connection/StringRedisConnection.java
+++ b/src/main/java/org/springframework/data/redis/connection/StringRedisConnection.java
@@ -843,13 +843,14 @@ public interface StringRedisConnection extends RedisConnection {
String lPop(String key);
/**
- * Removes and returns first element in list stored at {@code key}.
+ * Removes and returns first {@code} elements in list stored at {@code key}.
*
* @param key must not be {@literal null}.
* @param count
* @return
* @see Redis Documentation: LPOP
* @see RedisListCommands#lPop(byte[], long)
+ * @since 2.6
*/
List lPop(String key, long count);
@@ -864,13 +865,14 @@ public interface StringRedisConnection extends RedisConnection {
String rPop(String key);
/**
- * Removes and returns last element in list stored at {@code key}.
+ * Removes and returns last {@code} elements in list stored at {@code key}.
*
* @param key must not be {@literal null}.
* @param count
* @return
* @see Redis Documentation: RPOP
* @see RedisListCommands#rPop(byte[], long)
+ * @since 2.6
*/
List rPop(String key, long count);
diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveListCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveListCommands.java
index 409b103df..9fef5f6fc 100644
--- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveListCommands.java
+++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveListCommands.java
@@ -277,6 +277,7 @@ class LettuceReactiveListCommands implements ReactiveListCommands {
*/
@Override
public Flux>> popList(Publisher commands) {
+
return connection.execute(cmd -> Flux.from(commands).concatMap(command -> {
Assert.notNull(command.getKey(), "Key must not be null!");
diff --git a/src/main/java/org/springframework/data/redis/core/BoundListOperations.java b/src/main/java/org/springframework/data/redis/core/BoundListOperations.java
index bb4b4abec..f73661b95 100644
--- a/src/main/java/org/springframework/data/redis/core/BoundListOperations.java
+++ b/src/main/java/org/springframework/data/redis/core/BoundListOperations.java
@@ -200,6 +200,18 @@ public interface BoundListOperations extends BoundKeyOperations {
@Nullable
V leftPop();
+ /**
+ * Removes and returns first {@code} elements in list stored at {@code key}.
+ *
+ * @param key must not be {@literal null}.
+ * @param count
+ * @return can be {@literal null}.
+ * @see Redis Documentation: LPOP
+ * @since 2.6
+ */
+ @Nullable
+ List leftPop(long count);
+
/**
* Removes and returns first element from lists stored at the bound key .
* Blocks connection until element available or {@code timeout} reached.
@@ -240,6 +252,18 @@ public interface BoundListOperations extends BoundKeyOperations {
@Nullable
V rightPop();
+ /**
+ * Removes and returns last {@code} elements in list stored at {@code key}.
+ *
+ * @param key must not be {@literal null}.
+ * @param count
+ * @return can be {@literal null}.
+ * @see Redis Documentation: RPOP
+ * @since 2.6
+ */
+ @Nullable
+ List rightPop(long count);
+
/**
* Removes and returns last element from lists stored at the bound key.
* Blocks connection until element available or {@code timeout} reached.
diff --git a/src/main/java/org/springframework/data/redis/core/DefaultBoundListOperations.java b/src/main/java/org/springframework/data/redis/core/DefaultBoundListOperations.java
index b33d85b19..6fa5c0bb2 100644
--- a/src/main/java/org/springframework/data/redis/core/DefaultBoundListOperations.java
+++ b/src/main/java/org/springframework/data/redis/core/DefaultBoundListOperations.java
@@ -19,6 +19,7 @@ import java.util.List;
import java.util.concurrent.TimeUnit;
import org.springframework.data.redis.connection.DataType;
+import org.springframework.lang.Nullable;
/**
* Default implementation for {@link BoundListOperations}.
@@ -82,6 +83,15 @@ class DefaultBoundListOperations extends DefaultBoundKeyOperations impl
return ops.leftPop(getKey());
}
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.redis.core.BoundListOperations#leftPop(long)
+ */
+ @Override
+ public List leftPop(long count) {
+ return ops.leftPop(getKey(), count);
+ }
+
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.BoundListOperations#leftPop(long, java.util.concurrent.TimeUnit)
@@ -163,6 +173,15 @@ class DefaultBoundListOperations extends DefaultBoundKeyOperations impl
return ops.rightPop(getKey());
}
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.redis.core.BoundListOperations#rightPop(long)
+ */
+ @Override
+ public List rightPop(long count) {
+ return ops.rightPop(getKey(), count);
+ }
+
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.BoundListOperations#rightPop(long, java.util.concurrent.TimeUnit)
diff --git a/src/main/java/org/springframework/data/redis/core/ListOperations.java b/src/main/java/org/springframework/data/redis/core/ListOperations.java
index eb5a6589d..19125c491 100644
--- a/src/main/java/org/springframework/data/redis/core/ListOperations.java
+++ b/src/main/java/org/springframework/data/redis/core/ListOperations.java
@@ -249,12 +249,13 @@ public interface ListOperations {
V leftPop(K key);
/**
- * Removes and returns first element in list stored at {@code key}.
+ * Removes and returns first {@code} elements in list stored at {@code key}.
*
* @param key must not be {@literal null}.
* @param count
* @return can be {@literal null}.
* @see Redis Documentation: LPOP
+ * @since 2.6
*/
@Nullable
List leftPop(K key, long count);
@@ -303,12 +304,13 @@ public interface ListOperations {
V rightPop(K key);
/**
- * Removes and returns last element in list stored at {@code key}.
+ * Removes and returns last {@code} elements in list stored at {@code key}.
*
* @param key must not be {@literal null}.
* @param count
* @return can be {@literal null}.
* @see Redis Documentation: RPOP
+ * @since 2.6
*/
@Nullable
List rightPop(K key, long count);
diff --git a/src/test/java/org/springframework/data/redis/connection/AbstractConnectionIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/AbstractConnectionIntegrationTests.java
index 61d553aad..4c6485fb4 100644
--- a/src/test/java/org/springframework/data/redis/connection/AbstractConnectionIntegrationTests.java
+++ b/src/test/java/org/springframework/data/redis/connection/AbstractConnectionIntegrationTests.java
@@ -80,6 +80,7 @@ import org.springframework.data.redis.core.types.RedisClientInfo;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.test.condition.EnabledOnCommand;
import org.springframework.data.redis.test.condition.EnabledOnRedisDriver;
+import org.springframework.data.redis.test.condition.EnabledOnRedisVersion;
import org.springframework.data.redis.test.condition.LongRunningTest;
import org.springframework.data.redis.test.condition.RedisDriver;
import org.springframework.data.redis.test.util.HexStringUtils;
@@ -1286,6 +1287,16 @@ public abstract class AbstractConnectionIntegrationTests {
verifyResults(Arrays.asList(new Object[] { 1L, 2L, "hello" }));
}
+ @Test // GH-1987
+ @EnabledOnRedisVersion("6.2")
+ void testLPopWithCount() {
+ actual.add(connection.rPush("PopList", "hello"));
+ actual.add(connection.rPush("PopList", "world"));
+ actual.add(connection.rPush("PopList", "42"));
+ actual.add(connection.lPop("PopList", 2));
+ verifyResults(Arrays.asList(new Object[] { 1L, 2L, 3L, Arrays.asList("hello", "world") }));
+ }
+
@Test
void testLRem() {
actual.add(connection.rPush("PopList", "hello"));
@@ -1335,6 +1346,16 @@ public abstract class AbstractConnectionIntegrationTests {
verifyResults(Arrays.asList(new Object[] { 1L, 2L, "world" }));
}
+ @Test // GH-1987
+ @EnabledOnRedisVersion("6.2")
+ void testRPopWithCount() {
+ actual.add(connection.rPush("PopList", "hello"));
+ actual.add(connection.rPush("PopList", "world"));
+ actual.add(connection.rPush("PopList", "42"));
+ actual.add(connection.rPop("PopList", 2));
+ verifyResults(Arrays.asList(new Object[] { 1L, 2L, 3L, Arrays.asList("42", "world") }));
+ }
+
@Test
void testRPopLPush() {
actual.add(connection.rPush("PopList", "hello"));
diff --git a/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionTests.java b/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionTests.java
index 60191c856..c91725cbc 100644
--- a/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionTests.java
+++ b/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionTests.java
@@ -670,14 +670,14 @@ public class DefaultStringRedisConnectionTests {
verifyResults(Collections.singletonList(bar));
}
- @Test
+ @Test // GH-1987
public void testLPopCountBytes() {
doReturn(Collections.singletonList(barBytes)).when(nativeConnection).lPop(fooBytes, 2);
actual.add(connection.lPop(fooBytes, 2));
verifyResults(Collections.singletonList(bytesList));
}
- @Test
+ @Test // GH-1987
public void testLPopCount() {
doReturn(Collections.singletonList(barBytes)).when(nativeConnection).lPop(fooBytes, 2);
actual.add(connection.lPop(foo, 2));
@@ -852,14 +852,14 @@ public class DefaultStringRedisConnectionTests {
verifyResults(Collections.singletonList(bar));
}
- @Test
+ @Test // GH-1987
public void testRPopCountBytes() {
doReturn(Collections.singletonList(barBytes)).when(nativeConnection).rPop(fooBytes, 2);
actual.add(connection.rPop(fooBytes, 2));
verifyResults(Collections.singletonList(bytesList));
}
- @Test
+ @Test // GH-1987
public void testRPopCount() {
doReturn(Collections.singletonList(barBytes)).when(nativeConnection).rPop(fooBytes, 2);
actual.add(connection.rPop(foo, 2));
diff --git a/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionTxTests.java b/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionTxTests.java
index 888e88bec..c1ef9034c 100644
--- a/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionTxTests.java
+++ b/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionTxTests.java
@@ -509,6 +509,18 @@ public class DefaultStringRedisConnectionTxTests extends DefaultStringRedisConne
super.testLPop();
}
+ @Test // GH-1987
+ public void testLPopCountBytes() {
+ doReturn(Collections.singletonList(Collections.singletonList(barBytes))).when(nativeConnection).exec();
+ super.testLPopCountBytes();
+ }
+
+ @Test // GH-1987
+ public void testLPopCount() {
+ doReturn(Collections.singletonList(Collections.singletonList(barBytes))).when(nativeConnection).exec();
+ super.testLPopCount();
+ }
+
@Test
public void testLPushBytes() {
doReturn(Collections.singletonList(8L)).when(nativeConnection).exec();
@@ -653,6 +665,18 @@ public class DefaultStringRedisConnectionTxTests extends DefaultStringRedisConne
super.testRPop();
}
+ @Test // GH-1987
+ public void testRPopCountBytes() {
+ doReturn(Collections.singletonList(Collections.singletonList(barBytes))).when(nativeConnection).exec();
+ super.testRPopCountBytes();
+ }
+
+ @Test // GH-1987
+ public void testRPopCount() {
+ doReturn(Collections.singletonList(Collections.singletonList(barBytes))).when(nativeConnection).exec();
+ super.testRPopCount();
+ }
+
@Test
public void testRPopLPushBytes() {
doReturn(Arrays.asList(new Object[] { barBytes })).when(nativeConnection).exec();