Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ZMPOP and LMPOP #2094

Merged
merged 30 commits into from
Apr 19, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
8d6de09
Adding ZMPOP and LMPOP
slorello89 Apr 14, 2022
48c25bc
merge conflicts
slorello89 Apr 14, 2022
17749fc
trying to reset whitespace changes
slorello89 Apr 15, 2022
1bd5b8b
removing new() syntax
slorello89 Apr 15, 2022
fcf8642
reverting whitespace addition to csproj
slorello89 Apr 15, 2022
916240b
nick's comment updates
slorello89 Apr 15, 2022
8db54f8
adding Null values for newly renamed ListEntries and SortedSetEntries
slorello89 Apr 15, 2022
2818e06
possible solution for key-conflict?
slorello89 Apr 15, 2022
872742d
Docs/tweaks
NickCraver Apr 16, 2022
924218d
Merge branch 'main' into feature/ZMPOP
NickCraver Apr 16, 2022
aeba2a8
Simplify tests
NickCraver Apr 16, 2022
63e6679
SortedSetEntries -> SortedSetPopResult ListEntries -> ListPopResult
slorello89 Apr 16, 2022
321b1fe
Docs and ordering
NickCraver Apr 16, 2022
7716091
Null value updates for the .Null case
NickCraver Apr 16, 2022
6d48c1a
Simplify the procesorrrrrrrrrrrrs
NickCraver Apr 16, 2022
aca1da0
Optimize harder
NickCraver Apr 16, 2022
19d69d3
Merge remote-tracking branch 'origin/main' into feature/ZMPOP
NickCraver Apr 16, 2022
d6378dd
Add release notes
NickCraver Apr 16, 2022
0a6f154
Grammar, lest Elise kills me in my sleep
NickCraver Apr 16, 2022
88810ed
Simplify descriptions
NickCraver Apr 16, 2022
fd8db50
Must was so angry.
NickCraver Apr 16, 2022
a6ef27b
Test tweaks
NickCraver Apr 16, 2022
2991bd8
Tests: remove additional LINQ (makes tests more specific too)
NickCraver Apr 16, 2022
0779e45
SortedSets: de-LINQ
NickCraver Apr 16, 2022
be67266
Optimize SortedSet tests
NickCraver Apr 16, 2022
e682f33
Use \Results folder
NickCraver Apr 16, 2022
d7726ce
Results -> API types
NickCraver Apr 16, 2022
717dd6f
Merge remote-tracking branch 'origin/main' into feature/ZMPOP
NickCraver Apr 17, 2022
a8e435e
Merge remote-tracking branch 'origin/main' into feature/ZMPOP
NickCraver Apr 19, 2022
0e26598
Merge remote-tracking branch 'origin/main' into feature/ZMPOP
NickCraver Apr 19, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/StackExchange.Redis/Enums/RedisCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ internal enum RedisCommand
LINSERT,
LLEN,
LMOVE,
LMPOP,
LPOP,
LPOS,
LPUSH,
Expand Down Expand Up @@ -208,6 +209,7 @@ internal enum RedisCommand
ZMSCORE,
ZPOPMAX,
ZPOPMIN,
ZMPOP,
ZRANDMEMBER,
ZRANGE,
ZRANGEBYLEX,
Expand Down
38 changes: 38 additions & 0 deletions src/StackExchange.Redis/Interfaces/IDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -768,6 +768,19 @@ public interface IDatabase : IRedis, IDatabaseAsync
/// <remarks>https://redis.io/commands/lpop</remarks>
RedisValue[] ListLeftPop(RedisKey key, long count, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Removes and returns at most specified <paramref name="count"/> of elements from the first non-empty list
/// within the set of <paramref name="keys"/> passed into it. Starts on the left side of the list.
/// If the Length of the first non-empty list is less than the the <paramref name="count"/> only the elements within that
/// list are returned.
/// </summary>
/// <param name="keys">The keys to look through for popable elements.</param>
/// <param name="count">The maximum number of eelemnts to pop out of the list</param>
/// <param name="flags"></param>
/// <remarks>https://redis.io/commands/lmpop</remarks>
/// <returns>A span of contiguous elements from the list. Null if no non-empty lists are encountered</returns>
ListSpan? ListLeftPop(RedisKey[] keys, long count, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Scans through the list stored at <paramref name="key"/> looking for <paramref name="element"/>, returning the 0-based
/// index of the first matching element.
Expand Down Expand Up @@ -905,6 +918,19 @@ public interface IDatabase : IRedis, IDatabaseAsync
/// <remarks>https://redis.io/commands/rpop</remarks>
RedisValue[] ListRightPop(RedisKey key, long count, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Removes and returns at most specified <paramref name="count"/> of elements from the first non-empty list
/// within the set of <paramref name="keys"/> passed into it. Starts on the right side of the list.
/// If the Length of the first non-empty list is less than the the <paramref name="count"/> only the elements within that
/// list are returned.
/// </summary>
/// <param name="keys">The keys to look through for popable elements.</param>
/// <param name="count">The maximum number of eelemnts to pop out of the list</param>
/// <param name="flags"></param>
/// <remarks>https://redis.io/commands/lmpop</remarks>
/// <returns>A span of contiguous elements from the list.</returns>
ListSpan? ListRightPop(RedisKey[] keys, long count, CommandFlags flags = CommandFlags.None);

/// <summary>
/// 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.
/// </summary>
Expand Down Expand Up @@ -1913,6 +1939,18 @@ IEnumerable<SortedSetEntry> SortedSetScan(RedisKey key,
/// <remarks>https://redis.io/commands/zpopmax</remarks>
SortedSetEntry[] SortedSetPop(RedisKey key, long count, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Removes and returns up to the the specified <paramref name="count"/> of entries from the first non-empty sorted set specified by <paramref name="keys"/>
/// returns <see langword="null"/> if none of the specified <paramref name="keys"/> contain any elements.
/// </summary>
/// <param name="keys">The keys to check.</param>
/// <param name="count">The maximum number of records to pop out of the sorted set.</param>
/// <param name="order">The order to sort by when popping items out of the set.</param>
/// <param name="flags">The flags to use for the operation.</param>
/// <returns>A contiguous portion of sorted set entry with the key they were popped from.</returns>
/// <remarks>https://redis.io/commands/zmpop</remarks>
SortedSetSpan? SortedSetPop(RedisKey[] keys, long count, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Allow the consumer to mark a pending message as correctly processed. Returns the number of messages acknowledged.
/// </summary>
Expand Down
38 changes: 38 additions & 0 deletions src/StackExchange.Redis/Interfaces/IDatabaseAsync.cs
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,19 @@ public interface IDatabaseAsync : IRedisAsync
/// <remarks>https://redis.io/commands/lpop</remarks>
Task<RedisValue[]> ListLeftPopAsync(RedisKey key, long count, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Removes and returns at most specified <paramref name="count"/> of elements from the first non-empty list
/// within the set of <paramref name="keys"/> passed into it. Starts on the left side of the list.
/// If the Length of the first non-empty list is less than the the <paramref name="count"/> only the elements within that
/// list are returned.
/// </summary>
/// <param name="keys">The keys to look through for popable elements.</param>
/// <param name="count">The maximum number of eelemnts to pop out of the list</param>
/// <param name="flags"></param>
/// <remarks>https://redis.io/commands/lmpop</remarks>
/// <returns>A span of contiguous elements from the list.</returns>
slorello89 marked this conversation as resolved.
Show resolved Hide resolved
Task<ListSpan?> ListLeftPopAsync(RedisKey[] keys, long count, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Scans through the list stored at <paramref name="key"/> looking for <paramref name="element"/>, returning the 0-based
/// index of the first matching element.
Expand Down Expand Up @@ -881,6 +894,19 @@ public interface IDatabaseAsync : IRedisAsync
/// <remarks>https://redis.io/commands/rpop</remarks>
Task<RedisValue[]> ListRightPopAsync(RedisKey key, long count, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Removes and returns at most specified <paramref name="count"/> of elements from the first non-empty list
/// within the set of <paramref name="keys"/> passed into it. Starts on the right side of the list.
/// If the Length of the first non-empty list is less than the the <paramref name="count"/> only the elements within that
/// list are returned.
/// </summary>
/// <param name="keys">The keys to look through for popable elements.</param>
/// <param name="count">The maximum number of eelemnts to pop out of the list</param>
/// <param name="flags"></param>
/// <remarks>https://redis.io/commands/lmpop</remarks>
/// <returns>A span of contiguous elements from the list. Null if no non-empty lists are encountered.</returns>
Task<ListSpan?> ListRightPopAsync(RedisKey[] keys, long count, CommandFlags flags = CommandFlags.None);

/// <summary>
/// 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.
/// </summary>
Expand Down Expand Up @@ -1865,6 +1891,18 @@ IAsyncEnumerable<SortedSetEntry> SortedSetScanAsync(RedisKey key,
/// <remarks>https://redis.io/commands/zpopmax</remarks>
Task<SortedSetEntry[]> SortedSetPopAsync(RedisKey key, long count, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Removes and returns up to the the specified <paramref name="count"/> of entries from the first non-empty sorted set specified by <paramref name="keys"/>
/// returns <see langword="null"/> if none of the specified <paramref name="keys"/> contain any elements.
/// </summary>
/// <param name="keys">The keys to check.</param>
/// /// <param name="count">The maximum number of records to pop out of the sorted set.</param>
/// <param name="order">The order to sort by when popping items out of the set.</param>
/// <param name="flags">The flags to use for the operation.</param>
/// <returns>A contiguous portion of sorted set entry with the key they were popped from.</returns>
/// <remarks>https://redis.io/commands/zmpop</remarks>
Task<SortedSetSpan?> SortedSetPopAsync(RedisKey[] keys, long count, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Allow the consumer to mark a pending message as correctly processed. Returns the number of messages acknowledged.
/// </summary>
Expand Down
9 changes: 9 additions & 0 deletions src/StackExchange.Redis/KeyspaceIsolation/DatabaseWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,9 @@ public RedisValue ListLeftPop(RedisKey key, CommandFlags flags = CommandFlags.No
public RedisValue[] ListLeftPop(RedisKey key, long count, CommandFlags flags = CommandFlags.None) =>
Inner.ListLeftPop(ToInner(key), count, flags);

public ListSpan? ListLeftPop(RedisKey[] keys, long count, CommandFlags flags = CommandFlags.None) =>
Inner.ListLeftPop(ToInner(keys), count, flags);

public long ListPosition(RedisKey key, RedisValue element, long rank = 1, long maxLength = 0, CommandFlags flags = CommandFlags.None) =>
Inner.ListPosition(ToInner(key), element, rank, maxLength, flags);

Expand Down Expand Up @@ -239,6 +242,9 @@ public RedisValue ListRightPop(RedisKey key, CommandFlags flags = CommandFlags.N
public RedisValue[] ListRightPop(RedisKey key, long count, CommandFlags flags = CommandFlags.None) =>
Inner.ListRightPop(ToInner(key), count, flags);

public ListSpan? ListRightPop(RedisKey[] keys, long count, CommandFlags flags = CommandFlags.None) =>
Inner.ListRightPop(ToInner(keys), count, flags);

public RedisValue ListRightPopLeftPush(RedisKey source, RedisKey destination, CommandFlags flags = CommandFlags.None) =>
Inner.ListRightPopLeftPush(ToInner(source), ToInner(destination), flags);

Expand Down Expand Up @@ -463,6 +469,9 @@ public long SortedSetRemoveRangeByValue(RedisKey key, RedisValue min, RedisValue
public SortedSetEntry[] SortedSetPop(RedisKey key, long count, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetPop(ToInner(key), count, order, flags);

public SortedSetSpan? SortedSetPop(RedisKey[] keys, long count, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetPop(ToInner(keys), count, order, flags);

public long StreamAcknowledge(RedisKey key, RedisValue groupName, RedisValue messageId, CommandFlags flags = CommandFlags.None) =>
Inner.StreamAcknowledge(ToInner(key), groupName, messageId, flags);

Expand Down
9 changes: 9 additions & 0 deletions src/StackExchange.Redis/KeyspaceIsolation/WrapperBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,9 @@ public Task<RedisValue> ListLeftPopAsync(RedisKey key, CommandFlags flags = Comm
public Task<RedisValue[]> ListLeftPopAsync(RedisKey key, long count, CommandFlags flags = CommandFlags.None) =>
Inner.ListLeftPopAsync(ToInner(key), count, flags);

public Task<ListSpan?> ListLeftPopAsync(RedisKey[] keys, long count, CommandFlags flags = CommandFlags.None) =>
Inner.ListLeftPopAsync(ToInner(keys), count, flags);

public Task<long> ListPositionAsync(RedisKey key, RedisValue element, long rank = 1, long maxLength = 0, CommandFlags flags = CommandFlags.None) =>
Inner.ListPositionAsync(ToInner(key), element, rank, maxLength, flags);

Expand Down Expand Up @@ -250,6 +253,9 @@ public Task<RedisValue> ListRightPopAsync(RedisKey key, CommandFlags flags = Com
public Task<RedisValue[]> ListRightPopAsync(RedisKey key, long count, CommandFlags flags = CommandFlags.None) =>
Inner.ListRightPopAsync(ToInner(key), count, flags);

public Task<ListSpan?> ListRightPopAsync(RedisKey[] keys, long count, CommandFlags flags = CommandFlags.None) =>
Inner.ListRightPopAsync(ToInner(keys), count, flags);

public Task<RedisValue> ListRightPopLeftPushAsync(RedisKey source, RedisKey destination, CommandFlags flags = CommandFlags.None) =>
Inner.ListRightPopLeftPushAsync(ToInner(source), ToInner(destination), flags);

Expand Down Expand Up @@ -480,6 +486,9 @@ public IAsyncEnumerable<SortedSetEntry> SortedSetScanAsync(RedisKey key, RedisVa
public Task<SortedSetEntry[]> SortedSetPopAsync(RedisKey key, long count, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetPopAsync(ToInner(key), count, order, flags);

public Task<SortedSetSpan?> SortedSetPopAsync(RedisKey[] keys, long count, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetPopAsync(ToInner(keys), count, order, flags);

public Task<long> StreamAcknowledgeAsync(RedisKey key, RedisValue groupName, RedisValue messageId, CommandFlags flags = CommandFlags.None) =>
Inner.StreamAcknowledgeAsync(ToInner(key), groupName, messageId, flags);

Expand Down
24 changes: 24 additions & 0 deletions src/StackExchange.Redis/ListSpan.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
namespace StackExchange.Redis;

/// <summary>
/// A contiguous portion of a list.
/// </summary>
public readonly struct ListSpan
{
/// <summary>
/// The key of the list that this span came form.
/// </summary>
public RedisKey Key { get; }


/// <summary>
/// The values from the list
/// </summary>
public RedisValue[] Values { get; }

internal ListSpan(RedisKey key, RedisValue[] values)
{
Key = key;
Values = values;
}
}
Loading