diff --git a/docs/ReleaseNotes.md b/docs/ReleaseNotes.md
index 97d4f1d45..a12a5b801 100644
--- a/docs/ReleaseNotes.md
+++ b/docs/ReleaseNotes.md
@@ -6,6 +6,7 @@
- fix potential errors getting socket bytes (#1836 via NickCraver)
- logging additions (.NET Version and timestamps) for better debugging (#1796 via philon-msft)
- add: `Condition` API (transactions) now supports `StreamLengthEqual` and variants (#1807 via AlphaGremlin)
+- Add support for count argument to `ListLeftPop`, `ListLeftPopAsync`, `ListRightPop`, and `ListRightPopAsync` (#1850 via jjfmarket)
- fix potential task/thread exhaustion from the backlog processor (#1854 via mgravell)
## 2.2.62
diff --git a/src/StackExchange.Redis/Interfaces/IDatabase.cs b/src/StackExchange.Redis/Interfaces/IDatabase.cs
index a4d14ab2f..31e4e3bc9 100644
--- a/src/StackExchange.Redis/Interfaces/IDatabase.cs
+++ b/src/StackExchange.Redis/Interfaces/IDatabase.cs
@@ -639,6 +639,17 @@ public interface IDatabase : IRedis, IDatabaseAsync
/// https://redis.io/commands/lpop
RedisValue ListLeftPop(RedisKey key, CommandFlags flags = CommandFlags.None);
+ ///
+ /// Removes and returns count elements from the tail of the list stored at key.
+ /// If there are less elements in the list than count, removes and returns all the elements in the list.
+ ///
+ /// The key of the list.
+ /// The number of items to remove.
+ /// The flags to use for this operation.
+ /// Array of values that were popped, or nil if the key doesn't exist.
+ /// https://redis.io/commands/lpop
+ RedisValue[] ListLeftPop(RedisKey key, long count, CommandFlags flags = CommandFlags.None);
+
///
/// Insert the specified value at the head of the list stored at key. If key does not exist, it is created as empty list before performing the push operations.
///
@@ -719,6 +730,17 @@ public interface IDatabase : IRedis, IDatabaseAsync
/// https://redis.io/commands/rpop
RedisValue ListRightPop(RedisKey key, CommandFlags flags = CommandFlags.None);
+ ///
+ /// Removes and returns count elements from the head of the list stored at key.
+ /// If there are less elements in the list than count, removes and returns all the elements in the list.
+ ///
+ /// The key of the list.
+ /// tThe number of items to remove.
+ /// The flags to use for this operation.
+ /// Array of values that were popped, or nil if the key doesn't exist.
+ /// https://redis.io/commands/rpop
+ RedisValue[] ListRightPop(RedisKey key, long count, CommandFlags flags = CommandFlags.None);
+
///
/// Atomically returns and removes the last element (tail) of the list stored at source, and pushes the element at the first element (head) of the list stored at destination.
///
diff --git a/src/StackExchange.Redis/Interfaces/IDatabaseAsync.cs b/src/StackExchange.Redis/Interfaces/IDatabaseAsync.cs
index 496722667..79d0d6ff0 100644
--- a/src/StackExchange.Redis/Interfaces/IDatabaseAsync.cs
+++ b/src/StackExchange.Redis/Interfaces/IDatabaseAsync.cs
@@ -616,6 +616,17 @@ public interface IDatabaseAsync : IRedisAsync
/// https://redis.io/commands/lpop
Task ListLeftPopAsync(RedisKey key, CommandFlags flags = CommandFlags.None);
+ ///
+ /// Removes and returns count elements from the head of the list stored at key.
+ /// If the list contains less than count elements, removes and returns the number of elements in the list
+ ///
+ /// The key of the list.
+ /// The number of elements to remove
+ /// The flags to use for this operation.
+ /// Array of values that were popped, or nil if the key doesn't exist
+ /// https://redis.io/commands/lpop
+ Task ListLeftPopAsync(RedisKey key, long count, CommandFlags flags = CommandFlags.None);
+
///
/// Insert the specified value at the head of the list stored at key. If key does not exist, it is created as empty list before performing the push operations.
///
@@ -696,6 +707,17 @@ public interface IDatabaseAsync : IRedisAsync
/// https://redis.io/commands/rpop
Task ListRightPopAsync(RedisKey key, CommandFlags flags = CommandFlags.None);
+ ///
+ /// Removes and returns count elements from the end the list stored at key.
+ /// If the list contains less than count elements, removes and returns the number of elements in the list
+ ///
+ /// The key of the list.
+ /// The number of elements to pop
+ /// The flags to use for this operation.
+ /// Array of values that were popped, or nil if the key doesn't exist
+ /// https://redis.io/commands/rpop
+ Task ListRightPopAsync(RedisKey key, long count, CommandFlags flags = CommandFlags.None);
+
///
/// Atomically returns and removes the last element (tail) of the list stored at source, and pushes the element at the first element (head) of the list stored at destination.
///
diff --git a/src/StackExchange.Redis/KeyspaceIsolation/DatabaseWrapper.cs b/src/StackExchange.Redis/KeyspaceIsolation/DatabaseWrapper.cs
index e6f6f506a..88585d3ef 100644
--- a/src/StackExchange.Redis/KeyspaceIsolation/DatabaseWrapper.cs
+++ b/src/StackExchange.Redis/KeyspaceIsolation/DatabaseWrapper.cs
@@ -301,6 +301,11 @@ public RedisValue ListLeftPop(RedisKey key, CommandFlags flags = CommandFlags.No
return Inner.ListLeftPop(ToInner(key), flags);
}
+ public RedisValue[] ListLeftPop(RedisKey key, long count, CommandFlags flags = CommandFlags.None)
+ {
+ return Inner.ListLeftPop(ToInner(key), count, flags);
+ }
+
public long ListLeftPush(RedisKey key, RedisValue[] values, CommandFlags flags = CommandFlags.None)
{
return Inner.ListLeftPush(ToInner(key), values, flags);
@@ -336,6 +341,11 @@ public RedisValue ListRightPop(RedisKey key, CommandFlags flags = CommandFlags.N
return Inner.ListRightPop(ToInner(key), flags);
}
+ public RedisValue[] ListRightPop(RedisKey key, long count, CommandFlags flags = CommandFlags.None)
+ {
+ return Inner.ListRightPop(ToInner(key), count, flags);
+ }
+
public RedisValue ListRightPopLeftPush(RedisKey source, RedisKey destination, CommandFlags flags = CommandFlags.None)
{
return Inner.ListRightPopLeftPush(ToInner(source), ToInner(destination), flags);
diff --git a/src/StackExchange.Redis/KeyspaceIsolation/WrapperBase.cs b/src/StackExchange.Redis/KeyspaceIsolation/WrapperBase.cs
index d4b124f86..fc5f9abeb 100644
--- a/src/StackExchange.Redis/KeyspaceIsolation/WrapperBase.cs
+++ b/src/StackExchange.Redis/KeyspaceIsolation/WrapperBase.cs
@@ -286,6 +286,11 @@ public Task ListLeftPopAsync(RedisKey key, CommandFlags flags = Comm
return Inner.ListLeftPopAsync(ToInner(key), flags);
}
+ public Task ListLeftPopAsync(RedisKey key, long count, CommandFlags flags = CommandFlags.None)
+ {
+ return Inner.ListLeftPopAsync(ToInner(key), count, flags);
+ }
+
public Task ListLeftPushAsync(RedisKey key, RedisValue[] values, CommandFlags flags = CommandFlags.None)
{
return Inner.ListLeftPushAsync(ToInner(key), values, flags);
@@ -321,6 +326,11 @@ public Task ListRightPopAsync(RedisKey key, CommandFlags flags = Com
return Inner.ListRightPopAsync(ToInner(key), flags);
}
+ public Task ListRightPopAsync(RedisKey key, long count, CommandFlags flags = CommandFlags.None)
+ {
+ return Inner.ListRightPopAsync(ToInner(key), count, flags);
+ }
+
public Task ListRightPopLeftPushAsync(RedisKey source, RedisKey destination, CommandFlags flags = CommandFlags.None)
{
return Inner.ListRightPopLeftPushAsync(ToInner(source), ToInner(destination), flags);
diff --git a/src/StackExchange.Redis/RedisDatabase.cs b/src/StackExchange.Redis/RedisDatabase.cs
index be3b5d991..825b511b1 100644
--- a/src/StackExchange.Redis/RedisDatabase.cs
+++ b/src/StackExchange.Redis/RedisDatabase.cs
@@ -922,12 +922,24 @@ public RedisValue ListLeftPop(RedisKey key, CommandFlags flags = CommandFlags.No
return ExecuteSync(msg, ResultProcessor.RedisValue);
}
+ public RedisValue[] ListLeftPop(RedisKey key, long count, CommandFlags flags = CommandFlags.None)
+ {
+ var msg = Message.Create(Database, flags, RedisCommand.LPOP, key, count);
+ return ExecuteSync(msg, ResultProcessor.RedisValueArray);
+ }
+
public Task ListLeftPopAsync(RedisKey key, CommandFlags flags = CommandFlags.None)
{
var msg = Message.Create(Database, flags, RedisCommand.LPOP, key);
return ExecuteAsync(msg, ResultProcessor.RedisValue);
}
+ public Task ListLeftPopAsync(RedisKey key, long count, CommandFlags flags = CommandFlags.None)
+ {
+ var msg = Message.Create(Database, flags, RedisCommand.LPOP, key, count);
+ return ExecuteAsync(msg, ResultProcessor.RedisValueArray);
+ }
+
public long ListLeftPush(RedisKey key, RedisValue value, When when = When.Always, CommandFlags flags = CommandFlags.None)
{
WhenAlwaysOrExists(when);
@@ -1016,12 +1028,24 @@ public RedisValue ListRightPop(RedisKey key, CommandFlags flags = CommandFlags.N
return ExecuteSync(msg, ResultProcessor.RedisValue);
}
+ public RedisValue[] ListRightPop(RedisKey key, long count, CommandFlags flags = CommandFlags.None)
+ {
+ var msg = Message.Create(Database, flags, RedisCommand.RPOP, key, count);
+ return ExecuteSync(msg, ResultProcessor.RedisValueArray);
+ }
+
public Task ListRightPopAsync(RedisKey key, CommandFlags flags = CommandFlags.None)
{
var msg = Message.Create(Database, flags, RedisCommand.RPOP, key);
return ExecuteAsync(msg, ResultProcessor.RedisValue);
}
+ public Task ListRightPopAsync(RedisKey key, long count, CommandFlags flags = CommandFlags.None)
+ {
+ var msg = Message.Create(Database, flags, RedisCommand.RPOP, key, count);
+ return ExecuteAsync(msg, ResultProcessor.RedisValueArray);
+ }
+
public RedisValue ListRightPopLeftPush(RedisKey source, RedisKey destination, CommandFlags flags = CommandFlags.None)
{
var msg = Message.Create(Database, flags, RedisCommand.RPOPLPUSH, source, destination);
@@ -1933,7 +1957,7 @@ public bool StreamCreateConsumerGroup(RedisKey key, RedisValue groupName, RedisV
key,
groupName,
position,
- true,
+ true,
flags);
}
@@ -2251,7 +2275,7 @@ public Task StreamReadGroupAsync(RedisKey key, RedisValue groupNa
false,
flags);
}
-
+
public Task StreamReadGroupAsync(RedisKey key, RedisValue groupName, RedisValue consumerName, RedisValue? position = null, int? count = null, bool noAck = false, CommandFlags flags = CommandFlags.None)
{
var actualPosition = position ?? StreamPosition.NewMessages;
@@ -2815,7 +2839,7 @@ private Message GetMultiStreamReadMessage(StreamPosition[] streamPositions, int?
* [7] = id1
* [8] = id2
* [9] = id3
- *
+ *
* */
var pairCount = streamPositions.Length;
diff --git a/tests/StackExchange.Redis.Tests/DatabaseWrapperTests.cs b/tests/StackExchange.Redis.Tests/DatabaseWrapperTests.cs
index f9b539394..1455e0603 100644
--- a/tests/StackExchange.Redis.Tests/DatabaseWrapperTests.cs
+++ b/tests/StackExchange.Redis.Tests/DatabaseWrapperTests.cs
@@ -369,6 +369,13 @@ public void ListLeftPop()
mock.Verify(_ => _.ListLeftPop("prefix:key", CommandFlags.None));
}
+ [Fact]
+ public void ListLeftPop_1()
+ {
+ wrapper.ListLeftPop("key", 123, CommandFlags.None);
+ mock.Verify(_ => _.ListLeftPop("prefix:key", 123, CommandFlags.None));
+ }
+
[Fact]
public void ListLeftPush_1()
{
@@ -420,6 +427,13 @@ public void ListRightPop()
mock.Verify(_ => _.ListRightPop("prefix:key", CommandFlags.None));
}
+ [Fact]
+ public void ListRightPop_1()
+ {
+ wrapper.ListRightPop("key", 123, CommandFlags.None);
+ mock.Verify(_ => _.ListRightPop("prefix:key", 123, CommandFlags.None));
+ }
+
[Fact]
public void ListRightPopLeftPush()
{
diff --git a/tests/StackExchange.Redis.Tests/WrapperBaseTests.cs b/tests/StackExchange.Redis.Tests/WrapperBaseTests.cs
index 3f1ee9f28..286fb8c5a 100644
--- a/tests/StackExchange.Redis.Tests/WrapperBaseTests.cs
+++ b/tests/StackExchange.Redis.Tests/WrapperBaseTests.cs
@@ -330,6 +330,13 @@ public void ListLeftPopAsync()
mock.Verify(_ => _.ListLeftPopAsync("prefix:key", CommandFlags.None));
}
+ [Fact]
+ public void ListLeftPopAsync_1()
+ {
+ wrapper.ListLeftPopAsync("key", 123, CommandFlags.None);
+ mock.Verify(_ => _.ListLeftPopAsync("prefix:key", 123, CommandFlags.None));
+ }
+
[Fact]
public void ListLeftPushAsync_1()
{
@@ -381,6 +388,13 @@ public void ListRightPopAsync()
mock.Verify(_ => _.ListRightPopAsync("prefix:key", CommandFlags.None));
}
+ [Fact]
+ public void ListRightPopAsync_1()
+ {
+ wrapper.ListRightPopAsync("key", 123, CommandFlags.None);
+ mock.Verify(_ => _.ListRightPopAsync("prefix:key", 123, CommandFlags.None));
+ }
+
[Fact]
public void ListRightPopLeftPushAsync()
{