Skip to content

Commit bbe2c4a

Browse files
author
Gabriel Erzse
committed
Add dedicated enum for MIN/MAX
Add a dedicated enum for the MIN and MAX arguments. It feels cleaner than using Order and having to mentally map Ascending to Min and Descending to Max.
1 parent 0a8047a commit bbe2c4a

File tree

4 files changed

+85
-20
lines changed

4 files changed

+85
-20
lines changed

src/NRedisStack/CoreCommands/CoreCommandBuilder.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using NRedisStack.RedisStackCommands;
22
using NRedisStack.Core.Literals;
33
using NRedisStack.Core;
4+
using NRedisStack.Core.DataTypes;
45
using StackExchange.Redis;
56

67
namespace NRedisStack
@@ -20,7 +21,7 @@ public static SerializedCommand ClientSetInfo(SetInfoAttr attr, string value)
2021
return new SerializedCommand(RedisCoreCommands.CLIENT, RedisCoreCommands.SETINFO, attrValue, value);
2122
}
2223

23-
public static SerializedCommand BzmPop(int timeout, RedisKey[] keys, Order order, long? count)
24+
public static SerializedCommand BzmPop(int timeout, RedisKey[] keys, MinMaxModifier minMaxModifier, long? count)
2425
{
2526
if (keys.Length == 0)
2627
{
@@ -31,7 +32,7 @@ public static SerializedCommand BzmPop(int timeout, RedisKey[] keys, Order order
3132
timeout,
3233
keys.Length,
3334
.. keys.Cast<object>(),
34-
order == Order.Ascending ? CoreArgs.MIN : CoreArgs.MAX
35+
minMaxModifier == MinMaxModifier.Min ? CoreArgs.MIN : CoreArgs.MAX
3536
];
3637

3738
if (count != null)

src/NRedisStack/CoreCommands/CoreCommands.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,16 @@ public static bool ClientSetInfo(this IDatabase db, SetInfoAttr attr, string val
4646
/// <param name="db">The <see cref="IDatabase"/> class where this extension method is applied.</param>
4747
/// <param name="timeout">Server-side timeout for the wait. A value of <c>0</c> means to wait indefinitely.</param>
4848
/// <param name="keys">The keys to check.</param>
49-
/// <param name="order">The order to sort by when popping items out of the set. If set to <c>Order.ascending</c>
49+
/// <param name="minMaxModifier">Specify from which end of the sorted set to pop values. If set to <c>MinMaxModifier.Min</c>
5050
/// then the minimum elements will be popped, otherwise the maximum values.</param>
5151
/// <param name="count">The maximum number of records to pop out. If set to <c>null</c> then the server default
5252
/// will be used.</param>
5353
/// <returns>A collection of sorted set entries paired with their scores, together with the key they were popped
5454
/// from, or <c>null</c> if the server timeout expires.</returns>
5555
/// <remarks><seealso href="https://redis.io/commands/bzmpop"/></remarks>
56-
public static Tuple<RedisKey, List<RedisValueWithScore>>? BzmPop(this IDatabase db, int timeout, RedisKey[] keys, Order order, long? count = null)
56+
public static Tuple<RedisKey, List<RedisValueWithScore>>? BzmPop(this IDatabase db, int timeout, RedisKey[] keys, MinMaxModifier minMaxModifier, long? count = null)
5757
{
58-
var command = CoreCommandBuilder.BzmPop(timeout, keys, order, count);
58+
var command = CoreCommandBuilder.BzmPop(timeout, keys, minMaxModifier, count);
5959
return db.Execute(command).ToSortedSetPopResult();
6060
}
6161

@@ -66,16 +66,16 @@ public static bool ClientSetInfo(this IDatabase db, SetInfoAttr attr, string val
6666
/// <param name="db">The <see cref="IDatabase"/> class where this extension method is applied.</param>
6767
/// <param name="timeout">Server-side timeout for the wait. A value of <c>0</c> means to wait indefinitely.</param>
6868
/// <param name="key">The key to check.</param>
69-
/// <param name="order">The order to sort by when popping items out of the set. If set to <c>Order.ascending</c>
69+
/// <param name="minMaxModifier">Specify from which end of the sorted set to pop values. If set to <c>MinMaxModifier.Min</c>
7070
/// then the minimum elements will be popped, otherwise the maximum values.</param>
7171
/// <param name="count">The maximum number of records to pop out. If set to <c>null</c> then the server default
7272
/// will be used.</param>
7373
/// <returns>A collection of sorted set entries paired with their scores, together with the key they were popped
7474
/// from, or <c>null</c> if the server timeout expires.</returns>
7575
/// <remarks><seealso href="https://redis.io/commands/bzmpop"/></remarks>
76-
public static Tuple<RedisKey, List<RedisValueWithScore>>? BzmPop(this IDatabase db, int timeout, RedisKey key, Order order, long? count = null)
76+
public static Tuple<RedisKey, List<RedisValueWithScore>>? BzmPop(this IDatabase db, int timeout, RedisKey key, MinMaxModifier minMaxModifier, long? count = null)
7777
{
78-
return BzmPop(db, timeout, [key], order, count);
78+
return BzmPop(db, timeout, [key], minMaxModifier, count);
7979
}
8080
}
8181
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using StackExchange.Redis;
2+
3+
namespace NRedisStack.Core.DataTypes;
4+
5+
/// <summary>
6+
/// Modifier that can be used for sorted set commands, where a MIN/MAX argument is expected by the Redis server.
7+
/// </summary>
8+
public enum MinMaxModifier
9+
{
10+
/// <summary>
11+
/// Maps to the <c>MIN</c> argument on the Redis server.
12+
/// </summary>
13+
Min,
14+
15+
/// <summary>
16+
/// Maps to the <c>MAX</c> argument on the Redis server.
17+
/// </summary>
18+
Max
19+
}
20+
21+
/// <summary>
22+
/// Conversion methods from/to other common data types.
23+
/// </summary>
24+
public static class MinMaxModifierExtensions
25+
{
26+
/// <summary>
27+
/// Convert from <see cref="Order"/> to <see cref="MinMaxModifier"/>.
28+
/// </summary>
29+
public static MinMaxModifier ToMinMax(this Order order) => order switch
30+
{
31+
Order.Ascending => MinMaxModifier.Min,
32+
Order.Descending => MinMaxModifier.Max,
33+
_ => throw new ArgumentOutOfRangeException(nameof(order))
34+
};
35+
}

tests/NRedisStack.Tests/Core Commands/CoreTests.cs

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
using Xunit;
22
using NRedisStack.Core;
3-
using NRedisStack;
43
using static NRedisStack.Auxiliary;
54
using StackExchange.Redis;
6-
using System.Xml.Linq;
7-
using System.Reflection;
5+
using NRedisStack.Core.DataTypes;
86
using NRedisStack.RedisStackCommands;
97

108

@@ -164,7 +162,7 @@ public void TestBzmPop()
164162
db.SortedSetAdd(sortedSetKey, "e", 7.76);
165163

166164
// Pop two items with default order, which means it will pop the minimum values.
167-
var resultWithDefaultOrder = db.BzmPop(0, [sortedSetKey], Order.Ascending, 2);
165+
var resultWithDefaultOrder = db.BzmPop(0, [sortedSetKey], MinMaxModifier.Min, 2);
168166

169167
Assert.NotNull(resultWithDefaultOrder);
170168
Assert.Equal(sortedSetKey, resultWithDefaultOrder!.Item1);
@@ -173,7 +171,7 @@ public void TestBzmPop()
173171
Assert.Equal("c", resultWithDefaultOrder.Item2[1].Value.ToString());
174172

175173
// Pop one more item, with descending order, which means it will pop the maximum value.
176-
var resultWithDescendingOrder = db.BzmPop(0, [sortedSetKey], Order.Descending, 1);
174+
var resultWithDescendingOrder = db.BzmPop(0, [sortedSetKey], MinMaxModifier.Max, 1);
177175

178176
Assert.NotNull(resultWithDescendingOrder);
179177
Assert.Equal(sortedSetKey, resultWithDescendingOrder!.Item1);
@@ -190,7 +188,7 @@ public void TestBzmPopNull()
190188
db.Execute("FLUSHALL");
191189

192190
// Nothing in the set, and a short server timeout, which yields null.
193-
var result = db.BzmPop(1, ["my-set"], Order.Ascending, null);
191+
var result = db.BzmPop(1, ["my-set"], MinMaxModifier.Min, null);
194192

195193
Assert.Null(result);
196194
}
@@ -207,7 +205,7 @@ public void TestBzmPopMultiplexerTimeout()
207205
db.Execute("FLUSHALL");
208206

209207
// Server would wait forever, but the multiplexer times out in 1 second.
210-
Assert.Throws<RedisTimeoutException>(() => db.BzmPop(0, ["my-set"], Order.Ascending));
208+
Assert.Throws<RedisTimeoutException>(() => db.BzmPop(0, ["my-set"], MinMaxModifier.Min));
211209
}
212210

213211
[SkipIfRedis(Is.OSSCluster, Comparison.LessThan, "7.0.0")]
@@ -224,28 +222,28 @@ public void TestBzmPopMultipleSets()
224222
db.SortedSetAdd("set-two", "d", 9.4);
225223
db.SortedSetAdd("set-two", "e", 7.76);
226224

227-
var result = db.BzmPop(0, "set-two", Order.Descending);
225+
var result = db.BzmPop(0, "set-two", MinMaxModifier.Max);
228226

229227
Assert.NotNull(result);
230228
Assert.Equal("set-two", result!.Item1);
231229
Assert.Single(result.Item2);
232230
Assert.Equal("d", result.Item2[0].Value.ToString());
233231

234-
result = db.BzmPop(0, ["set-two", "set-one"], Order.Ascending);
232+
result = db.BzmPop(0, ["set-two", "set-one"], MinMaxModifier.Min);
235233

236234
Assert.NotNull(result);
237235
Assert.Equal("set-two", result!.Item1);
238236
Assert.Single(result.Item2);
239237
Assert.Equal("e", result.Item2[0].Value.ToString());
240238

241-
result = db.BzmPop(0, ["set-two", "set-one"], Order.Descending);
239+
result = db.BzmPop(0, ["set-two", "set-one"], MinMaxModifier.Max);
242240

243241
Assert.NotNull(result);
244242
Assert.Equal("set-one", result!.Item1);
245243
Assert.Single(result.Item2);
246244
Assert.Equal("b", result.Item2[0].Value.ToString());
247245

248-
result = db.BzmPop(0, "set-one", Order.Ascending, count: 2);
246+
result = db.BzmPop(0, "set-one", MinMaxModifier.Min, count: 2);
249247

250248
Assert.NotNull(result);
251249
Assert.Equal("set-one", result!.Item1);
@@ -263,6 +261,37 @@ public void TestBzmPopNoKeysProvided()
263261
db.Execute("FLUSHALL");
264262

265263
// Server would wait forever, but the multiplexer times out in 1 second.
266-
Assert.Throws<ArgumentException>(() => db.BzmPop(0, [], Order.Ascending));
264+
Assert.Throws<ArgumentException>(() => db.BzmPop(0, [], MinMaxModifier.Min));
265+
}
266+
267+
[SkipIfRedis(Is.OSSCluster, Comparison.LessThan, "7.0.0")]
268+
public void TestBzmPopWithOrderEnum()
269+
{
270+
var redis = ConnectionMultiplexer.Connect("localhost");
271+
272+
var db = redis.GetDatabase(null);
273+
db.Execute("FLUSHALL");
274+
275+
var sortedSetKey = "my-set";
276+
277+
db.SortedSetAdd(sortedSetKey, "a", 1.5);
278+
db.SortedSetAdd(sortedSetKey, "b", 5.1);
279+
db.SortedSetAdd(sortedSetKey, "c", 3.7);
280+
281+
// Pop two items with default order, which means it will pop the minimum values.
282+
var resultWithDefaultOrder = db.BzmPop(0, [sortedSetKey], Order.Ascending.ToMinMax());
283+
284+
Assert.NotNull(resultWithDefaultOrder);
285+
Assert.Equal(sortedSetKey, resultWithDefaultOrder!.Item1);
286+
Assert.Single(resultWithDefaultOrder.Item2);
287+
Assert.Equal("a", resultWithDefaultOrder.Item2[0].Value.ToString());
288+
289+
// Pop one more item, with descending order, which means it will pop the maximum value.
290+
var resultWithDescendingOrder = db.BzmPop(0, [sortedSetKey], Order.Descending.ToMinMax());
291+
292+
Assert.NotNull(resultWithDescendingOrder);
293+
Assert.Equal(sortedSetKey, resultWithDescendingOrder!.Item1);
294+
Assert.Single(resultWithDescendingOrder.Item2);
295+
Assert.Equal("b", resultWithDescendingOrder.Item2[0].Value.ToString());
267296
}
268297
}

0 commit comments

Comments
 (0)