Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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 docs/ReleaseNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
- Adds: Support for `GEOSEARCH` with `.GeoSearch()`/`.GeoSearchAsync()` ([#2089 by slorello89](https://github.com/StackExchange/StackExchange.Redis/pull/2089))
- Adds: Support for `GEOSEARCHSTORE` with `.GeoSearchAndStore()`/`.GeoSearchAndStoreAsync()` ([#2089 by slorello89](https://github.com/StackExchange/StackExchange.Redis/pull/2089))
- Adds: Support for `HRANDFIELD` with `.HashRandomField()`/`.HashRandomFieldAsync()`, `.HashRandomFields()`/`.HashRandomFieldsAsync()`, and `.HashRandomFieldsWithValues()`/`.HashRandomFieldsWithValuesAsync()` ([#2090 by slorello89](https://github.com/StackExchange/StackExchange.Redis/pull/2090))
- Adds: Support for `LMPOP` with `.ListLeftPop()`/`.ListLeftPopAsync()` and `.ListRightPop()`/`.ListRightPopAsync()` ([#2094 by slorello89](https://github.com/StackExchange/StackExchange.Redis/pull/2094))
- Adds: Support for `ZMPOP` with `.SortedSetPop()`/`.SortedSetPopAsync()` ([#2094 by slorello89](https://github.com/StackExchange/StackExchange.Redis/pull/2094))
- Adds: Support for `XAUTOCLAIM` with `.StreamAutoClaim()`/.`StreamAutoClaimAsync()` and `.StreamAutoClaimIdsOnly()`/.`StreamAutoClaimIdsOnlyAsync()` ([#2095 by ttingen](https://github.com/StackExchange/StackExchange.Redis/pull/2095))

## 2.5.61
Expand Down
35 changes: 35 additions & 0 deletions src/StackExchange.Redis/APITypes/ListPopResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System;

namespace StackExchange.Redis;

/// <summary>
/// A contiguous portion of a redis list.
/// </summary>
public readonly struct ListPopResult
{
/// <summary>
/// A null ListPopResult, indicating no results.
/// </summary>
public static ListPopResult Null { get; } = new ListPopResult(RedisKey.Null, Array.Empty<RedisValue>());

/// <summary>
/// Whether this object is null/empty.
/// </summary>
public bool IsNull => Key.IsNull && Values == Array.Empty<RedisValue>();

/// <summary>
/// The key of the list that this set of entries came form.
/// </summary>
public RedisKey Key { get; }

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

internal ListPopResult(RedisKey key, RedisValue[] values)
{
Key = key;
Values = values;
}
}
35 changes: 35 additions & 0 deletions src/StackExchange.Redis/APITypes/SortedSetPopResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System;

namespace StackExchange.Redis;

/// <summary>
/// A contiguous portion of a redis sorted set.
/// </summary>
public readonly struct SortedSetPopResult
{
/// <summary>
/// A null SortedSetPopResult, indicating no results.
/// </summary>
public static SortedSetPopResult Null { get; } = new SortedSetPopResult(RedisKey.Null, Array.Empty<SortedSetEntry>());

/// <summary>
/// Whether this object is null/empty.
/// </summary>
public bool IsNull => Key.IsNull && Entries == Array.Empty<SortedSetEntry>();

/// <summary>
/// The key of the sorted set these entries came form.
/// </summary>
public RedisKey Key { get; }

/// <summary>
/// The provided entries of the sorted set.
/// </summary>
public SortedSetEntry[] Entries { get; }

internal SortedSetPopResult(RedisKey key, SortedSetEntry[] entries)
{
Key = key;
Entries = entries;
}
}
4 changes: 4 additions & 0 deletions src/StackExchange.Redis/Enums/RedisCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ internal enum RedisCommand
LINSERT,
LLEN,
LMOVE,
LMPOP,
LPOP,
LPOS,
LPUSH,
Expand Down Expand Up @@ -212,6 +213,7 @@ internal enum RedisCommand
ZINTERCARD,
ZINTERSTORE,
ZLEXCOUNT,
ZMPOP,
ZMSCORE,
ZPOPMAX,
ZPOPMIN,
Expand Down Expand Up @@ -284,6 +286,7 @@ internal static bool IsPrimaryOnly(this RedisCommand command)
case RedisCommand.INCRBYFLOAT:
case RedisCommand.LINSERT:
case RedisCommand.LMOVE:
case RedisCommand.LMPOP:
case RedisCommand.LPOP:
case RedisCommand.LPUSH:
case RedisCommand.LPUSHX:
Expand Down Expand Up @@ -335,6 +338,7 @@ internal static bool IsPrimaryOnly(this RedisCommand command)
case RedisCommand.ZDIFFSTORE:
case RedisCommand.ZINTERSTORE:
case RedisCommand.ZINCRBY:
case RedisCommand.ZMPOP:
case RedisCommand.ZPOPMAX:
case RedisCommand.ZPOPMIN:
case RedisCommand.ZRANGESTORE:
Expand Down
34 changes: 34 additions & 0 deletions src/StackExchange.Redis/Interfaces/IDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -922,6 +922,17 @@ public interface IDatabase : IRedis, IDatabaseAsync
/// <remarks><seealso href="https://redis.io/commands/lpop"/></remarks>
RedisValue[] ListLeftPop(RedisKey key, long count, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Removes and returns at most <paramref name="count"/> elements from the first non-empty list in <paramref name="keys"/>.
/// Starts on the left side of the list.
/// </summary>
/// <param name="keys">The keys to look through for elements to pop.</param>
/// <param name="count">The maximum number of elements to pop from the list.</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <returns>A span of contiguous elements from the list, or <see cref="ListPopResult.Null"/> if no non-empty lists are found.</returns>
/// <remarks><seealso href="https://redis.io/commands/lmpop"/></remarks>
ListPopResult 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 @@ -1065,6 +1076,17 @@ public interface IDatabase : IRedis, IDatabaseAsync
/// <remarks><seealso href="https://redis.io/commands/rpop"/></remarks>
RedisValue[] ListRightPop(RedisKey key, long count, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Removes and returns at most <paramref name="count"/> elements from the first non-empty list in <paramref name="keys"/>.
/// Starts on the right side of the list.
/// </summary>
/// <param name="keys">The keys to look through for elements to pop.</param>
/// <param name="count">The maximum number of elements to pop from the list.</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <returns>A span of contiguous elements from the list, or <see cref="ListPopResult.Null"/> if no non-empty lists are found.</returns>
/// <remarks><seealso href="https://redis.io/commands/lmpop"/></remarks>
ListPopResult 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 @@ -2110,6 +2132,18 @@ IEnumerable<SortedSetEntry> SortedSetScan(RedisKey key,
/// </remarks>
SortedSetEntry[] SortedSetPop(RedisKey key, long count, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Removes and returns up to <paramref name="count"/> entries from the first non-empty sorted set in <paramref name="keys"/>.
/// Returns <see cref="SortedSetPopResult.Null"/> if none of the sets exist or 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 collection of sorted set entries with the key they were popped from, or <see cref="SortedSetPopResult.Null"/> if no non-empty sorted sets are found.</returns>
/// <remarks><seealso href="https://redis.io/commands/zmpop"/></remarks>
SortedSetPopResult 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
34 changes: 34 additions & 0 deletions src/StackExchange.Redis/Interfaces/IDatabaseAsync.cs
Original file line number Diff line number Diff line change
Expand Up @@ -898,6 +898,17 @@ public interface IDatabaseAsync : IRedisAsync
/// <remarks><seealso href="https://redis.io/commands/lpop"/></remarks>
Task<RedisValue[]> ListLeftPopAsync(RedisKey key, long count, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Removes and returns at most <paramref name="count"/> elements from the first non-empty list in <paramref name="keys"/>.
/// Starts on the left side of the list.
/// </summary>
/// <param name="keys">The keys to look through for elements to pop.</param>
/// <param name="count">The maximum number of elements to pop from the list.</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <returns>A span of contiguous elements from the list, or <see cref="ListPopResult.Null"/> if no non-empty lists are found.</returns>
/// <remarks><seealso href="https://redis.io/commands/lmpop"/></remarks>
Task<ListPopResult> 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 @@ -1041,6 +1052,17 @@ public interface IDatabaseAsync : IRedisAsync
/// <remarks><seealso href="https://redis.io/commands/rpop"/></remarks>
Task<RedisValue[]> ListRightPopAsync(RedisKey key, long count, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Removes and returns at most <paramref name="count"/> elements from the first non-empty list in <paramref name="keys"/>.
/// Starts on the right side of the list.
/// </summary>
/// <param name="keys">The keys to look through for elements to pop.</param>
/// <param name="count">The maximum number of elements to pop from the list.</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <returns>A span of contiguous elements from the list, or <see cref="ListPopResult.Null"/> if no non-empty lists are found.</returns>
/// <remarks><seealso href="https://redis.io/commands/lmpop"/></remarks>
Task<ListPopResult> 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 @@ -2063,6 +2085,18 @@ IAsyncEnumerable<SortedSetEntry> SortedSetScanAsync(RedisKey key,
/// </remarks>
Task<SortedSetEntry[]> SortedSetPopAsync(RedisKey key, long count, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Removes and returns up to <paramref name="count"/> entries from the first non-empty sorted set in <paramref name="keys"/>.
/// Returns <see cref="SortedSetPopResult.Null"/> if none of the sets exist or 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 collection of sorted set entries with the key they were popped from, or <see cref="SortedSetPopResult.Null"/> if no non-empty sorted sets are found.</returns>
/// <remarks><seealso href="https://redis.io/commands/zmpop"/></remarks>
Task<SortedSetPopResult> 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 @@ -227,6 +227,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 ListPopResult 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 @@ -260,6 +263,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 ListPopResult 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 @@ -484,6 +490,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 SortedSetPopResult 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 @@ -238,6 +238,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<ListPopResult> 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 @@ -271,6 +274,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<ListPopResult> 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 @@ -501,6 +507,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<SortedSetPopResult> 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
Loading