From 9aacf936c2b0ebb6462f86938c5478dc5eeafbd4 Mon Sep 17 00:00:00 2001 From: Todd Tingen Date: Tue, 12 Apr 2022 00:59:45 -0400 Subject: [PATCH 1/6] Support the ZMSCORE command. --- src/StackExchange.Redis/Enums/RedisCommand.cs | 1 + .../Interfaces/IDatabase.cs | 14 +++ .../Interfaces/IDatabaseAsync.cs | 14 +++ .../KeyspaceIsolation/DatabaseWrapper.cs | 3 + .../KeyspaceIsolation/WrapperBase.cs | 3 + src/StackExchange.Redis/PublicAPI.Shipped.txt | 2 + src/StackExchange.Redis/RawResult.cs | 3 + src/StackExchange.Redis/RedisDatabase.cs | 12 +++ src/StackExchange.Redis/ResultProcessor.cs | 22 +++++ .../DatabaseWrapperTests.cs | 7 ++ tests/StackExchange.Redis.Tests/SortedSets.cs | 90 +++++++++++++++++++ .../WrapperBaseTests.cs | 7 ++ 12 files changed, 178 insertions(+) diff --git a/src/StackExchange.Redis/Enums/RedisCommand.cs b/src/StackExchange.Redis/Enums/RedisCommand.cs index 4b7ec84da..96c5702fa 100644 --- a/src/StackExchange.Redis/Enums/RedisCommand.cs +++ b/src/StackExchange.Redis/Enums/RedisCommand.cs @@ -198,6 +198,7 @@ internal enum RedisCommand ZINCRBY, ZINTERSTORE, ZLEXCOUNT, + ZMSCORE, ZPOPMAX, ZPOPMIN, ZRANGE, diff --git a/src/StackExchange.Redis/Interfaces/IDatabase.cs b/src/StackExchange.Redis/Interfaces/IDatabase.cs index e29e8b1d9..b68edd1e7 100644 --- a/src/StackExchange.Redis/Interfaces/IDatabase.cs +++ b/src/StackExchange.Redis/Interfaces/IDatabase.cs @@ -1697,6 +1697,20 @@ IEnumerable SortedSetScan(RedisKey key, /// https://redis.io/commands/zscore double? SortedSetScore(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None); + /// + /// Returns the scores of members in the sorted set at key. + /// If a member does not exist in the sorted set, or key does not exist, nil is returned. + /// + /// The key of the sorted set. + /// The members to get a score for. + /// The flags to use for this operation. + /// + /// The scores of the members in the same order as the array. If a member does + /// not exist in the set, nil is returned. + /// + /// https://redis.io/commands/zmscore + double?[] SortedSetScore(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None); + /// /// Removes and returns the first element from the sorted set stored at key, by default with the scores ordered from low to high. /// diff --git a/src/StackExchange.Redis/Interfaces/IDatabaseAsync.cs b/src/StackExchange.Redis/Interfaces/IDatabaseAsync.cs index 1a02671f2..2991cb621 100644 --- a/src/StackExchange.Redis/Interfaces/IDatabaseAsync.cs +++ b/src/StackExchange.Redis/Interfaces/IDatabaseAsync.cs @@ -1650,6 +1650,20 @@ IAsyncEnumerable SortedSetScanAsync(RedisKey key, /// https://redis.io/commands/zscore Task SortedSetScoreAsync(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None); + /// + /// Returns the scores of members in the sorted set at key. + /// If a member does not exist in the sorted set, or key does not exist, nil is returned. + /// + /// The key of the sorted set. + /// The members to get a score for. + /// The flags to use for this operation. + /// + /// The scores of the members in the same order as the array. If a member does + /// not exist in the set, nil is returned. + /// + /// https://redis.io/commands/zmscore + Task SortedSetScoreAsync(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None); + /// /// Removes and returns the first element from the sorted set stored at key, by default with the scores ordered from low to high. /// diff --git a/src/StackExchange.Redis/KeyspaceIsolation/DatabaseWrapper.cs b/src/StackExchange.Redis/KeyspaceIsolation/DatabaseWrapper.cs index a35ec0c5e..eac91be5b 100644 --- a/src/StackExchange.Redis/KeyspaceIsolation/DatabaseWrapper.cs +++ b/src/StackExchange.Redis/KeyspaceIsolation/DatabaseWrapper.cs @@ -412,6 +412,9 @@ public long SortedSetRemoveRangeByValue(RedisKey key, RedisValue min, RedisValue public double? SortedSetScore(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) => Inner.SortedSetScore(ToInner(key), member, flags); + public double?[] SortedSetScore(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None) => + Inner.SortedSetScore(ToInner(key), members, flags); + public SortedSetEntry? SortedSetPop(RedisKey key, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None) => Inner.SortedSetPop(ToInner(key), order, flags); diff --git a/src/StackExchange.Redis/KeyspaceIsolation/WrapperBase.cs b/src/StackExchange.Redis/KeyspaceIsolation/WrapperBase.cs index 798524999..483429331 100644 --- a/src/StackExchange.Redis/KeyspaceIsolation/WrapperBase.cs +++ b/src/StackExchange.Redis/KeyspaceIsolation/WrapperBase.cs @@ -425,6 +425,9 @@ public Task SortedSetRemoveRangeByValueAsync(RedisKey key, RedisValue min, public Task SortedSetScoreAsync(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) => Inner.SortedSetScoreAsync(ToInner(key), member, flags); + public Task SortedSetScoreAsync(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None) => + Inner.SortedSetScoreAsync(ToInner(key), members, flags); + public IAsyncEnumerable SortedSetScanAsync(RedisKey key, RedisValue pattern, int pageSize, long cursor, int pageOffset, CommandFlags flags) => Inner.SortedSetScanAsync(ToInner(key), pattern, pageSize, cursor, pageOffset, flags); diff --git a/src/StackExchange.Redis/PublicAPI.Shipped.txt b/src/StackExchange.Redis/PublicAPI.Shipped.txt index ab7b9031e..5074802f7 100644 --- a/src/StackExchange.Redis/PublicAPI.Shipped.txt +++ b/src/StackExchange.Redis/PublicAPI.Shipped.txt @@ -615,6 +615,7 @@ StackExchange.Redis.IDatabase.SortedSetRemoveRangeByValue(StackExchange.Redis.Re StackExchange.Redis.IDatabase.SortedSetScan(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue pattern = default(StackExchange.Redis.RedisValue), int pageSize = 250, long cursor = 0, int pageOffset = 0, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Collections.Generic.IEnumerable! StackExchange.Redis.IDatabase.SortedSetScan(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue pattern, int pageSize, StackExchange.Redis.CommandFlags flags) -> System.Collections.Generic.IEnumerable! StackExchange.Redis.IDatabase.SortedSetScore(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue member, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> double? +StackExchange.Redis.IDatabase.SortedSetScore(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! members, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> double?[]! StackExchange.Redis.IDatabase.StreamAcknowledge(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue groupName, StackExchange.Redis.RedisValue messageId, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> long StackExchange.Redis.IDatabase.StreamAcknowledge(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue groupName, StackExchange.Redis.RedisValue[]! messageIds, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> long StackExchange.Redis.IDatabase.StreamAdd(StackExchange.Redis.RedisKey key, StackExchange.Redis.NameValueEntry[]! streamPairs, StackExchange.Redis.RedisValue? messageId = null, int? maxLength = null, bool useApproximateMaxLength = false, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> StackExchange.Redis.RedisValue @@ -804,6 +805,7 @@ StackExchange.Redis.IDatabaseAsync.SortedSetRemoveRangeByScoreAsync(StackExchang StackExchange.Redis.IDatabaseAsync.SortedSetRemoveRangeByValueAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue min, StackExchange.Redis.RedisValue max, StackExchange.Redis.Exclude exclude = StackExchange.Redis.Exclude.None, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task! StackExchange.Redis.IDatabaseAsync.SortedSetScanAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue pattern = default(StackExchange.Redis.RedisValue), int pageSize = 250, long cursor = 0, int pageOffset = 0, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Collections.Generic.IAsyncEnumerable! StackExchange.Redis.IDatabaseAsync.SortedSetScoreAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue member, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task! +StackExchange.Redis.IDatabaseAsync.SortedSetScoreAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! members, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task! StackExchange.Redis.IDatabaseAsync.StreamAcknowledgeAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue groupName, StackExchange.Redis.RedisValue messageId, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task! StackExchange.Redis.IDatabaseAsync.StreamAcknowledgeAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue groupName, StackExchange.Redis.RedisValue[]! messageIds, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task! StackExchange.Redis.IDatabaseAsync.StreamAddAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.NameValueEntry[]! streamPairs, StackExchange.Redis.RedisValue? messageId = null, int? maxLength = null, bool useApproximateMaxLength = false, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task! diff --git a/src/StackExchange.Redis/RawResult.cs b/src/StackExchange.Redis/RawResult.cs index 4620fe17e..b4a5e5ebd 100644 --- a/src/StackExchange.Redis/RawResult.cs +++ b/src/StackExchange.Redis/RawResult.cs @@ -253,6 +253,9 @@ internal bool GetBoolean() [MethodImpl(MethodImplOptions.AggressiveInlining)] internal Sequence GetItems() => _items.Cast(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal double?[]? GetItemsAsDoubles() => this.ToArray((in RawResult x) => x.TryGetDouble(out double val) ? val : null); + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal RedisKey[]? GetItemsAsKeys() => this.ToArray((in RawResult x) => x.AsRedisKey()); diff --git a/src/StackExchange.Redis/RedisDatabase.cs b/src/StackExchange.Redis/RedisDatabase.cs index 6602f2060..8907e97f1 100644 --- a/src/StackExchange.Redis/RedisDatabase.cs +++ b/src/StackExchange.Redis/RedisDatabase.cs @@ -1827,12 +1827,24 @@ private CursorEnumerable SortedSetScanAsync(RedisKey key, RedisV return ExecuteSync(msg, ResultProcessor.NullableDouble); } + public double?[] SortedSetScore(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None) + { + var msg = Message.Create(Database, flags, RedisCommand.ZMSCORE, key, members); + return ExecuteSync(msg, ResultProcessor.NullableDoubleArray, defaultValue: Array.Empty()); + } + public Task SortedSetScoreAsync(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) { var msg = Message.Create(Database, flags, RedisCommand.ZSCORE, key, member); return ExecuteAsync(msg, ResultProcessor.NullableDouble); } + public Task SortedSetScoreAsync(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None) + { + var msg = Message.Create(Database, flags, RedisCommand.ZMSCORE, key, members); + return ExecuteAsync(msg, ResultProcessor.NullableDoubleArray, defaultValue: Array.Empty()); + } + public SortedSetEntry? SortedSetPop(RedisKey key, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None) { var msg = Message.Create(Database, flags, order == Order.Descending ? RedisCommand.ZPOPMAX : RedisCommand.ZPOPMIN, key); diff --git a/src/StackExchange.Redis/ResultProcessor.cs b/src/StackExchange.Redis/ResultProcessor.cs index e9ab9026c..657fc2992 100644 --- a/src/StackExchange.Redis/ResultProcessor.cs +++ b/src/StackExchange.Redis/ResultProcessor.cs @@ -55,6 +55,10 @@ public static readonly ResultProcessor public static readonly ResultProcessor NullableDouble = new NullableDoubleProcessor(); + + public static readonly ResultProcessor + NullableDoubleArray = new NullableDoubleArrayProcessor(); + public static readonly ResultProcessor NullableInt64 = new NullableInt64Processor(); @@ -1083,6 +1087,24 @@ protected override bool SetResultCore(PhysicalConnection connection, Message mes } } + private sealed class NullableDoubleArrayProcessor : ResultProcessor + { + protected override bool SetResultCore(PhysicalConnection connection, Message message, in RawResult result) + { + switch (result.Type) + { + case ResultType.Integer: + case ResultType.SimpleString: + case ResultType.BulkString: + case ResultType.MultiBulk: + var values = result.GetItemsAsDoubles()!; + SetResult(message, values); + return true; + } + return false; + } + } + private sealed class NullableDoubleProcessor : ResultProcessor { protected override bool SetResultCore(PhysicalConnection connection, Message message, in RawResult result) diff --git a/tests/StackExchange.Redis.Tests/DatabaseWrapperTests.cs b/tests/StackExchange.Redis.Tests/DatabaseWrapperTests.cs index 5a48e6809..210e6c80d 100644 --- a/tests/StackExchange.Redis.Tests/DatabaseWrapperTests.cs +++ b/tests/StackExchange.Redis.Tests/DatabaseWrapperTests.cs @@ -883,6 +883,13 @@ public void SortedSetScore() mock.Verify(_ => _.SortedSetScore("prefix:key", "member", CommandFlags.None)); } + [Fact] + public void SortedSetScore_Multiple() + { + wrapper.SortedSetScore("key", new RedisValue[] { "member1", "member2" }, CommandFlags.None); + mock.Verify(_ => _.SortedSetScore("prefix:key", new RedisValue[] { "member1", "member2" }, CommandFlags.None)); + } + [Fact] public void StreamAcknowledge_1() { diff --git a/tests/StackExchange.Redis.Tests/SortedSets.cs b/tests/StackExchange.Redis.Tests/SortedSets.cs index e7cdcc59c..f51a06490 100644 --- a/tests/StackExchange.Redis.Tests/SortedSets.cs +++ b/tests/StackExchange.Redis.Tests/SortedSets.cs @@ -639,5 +639,95 @@ public void SortedSetRangeStoreFailExclude() var exception = Assert.Throws(()=>db.SortedSetRangeAndStore(sourceKey, destinationKey,0,-1, exclude: Exclude.Both)); Assert.Equal("exclude", exception.ParamName); } + + [Fact] + public void SortedSetScoreSingle() + { + using var conn = Create(); + Skip.IfBelow(conn, RedisFeatures.v2_1_0); + + var db = conn.GetDatabase(); + var me = Me(); + + var setKey = $"{me}:ZScoreSet"; + var memberName = $"{me}:ZScoreMember"; + + db.SortedSetAdd(setKey, memberName, 1.5); + var score = db.SortedSetScore(setKey, memberName); + + Assert.NotNull(score); + Assert.Equal((double)1.5, score.Value); + } + + [Fact] + public void SortedSetScoreSingle_ReturnsNull() + { + using var conn = Create(); + Skip.IfBelow(conn, RedisFeatures.v2_1_0); + + var db = conn.GetDatabase(); + var me = Me(); + + var setKey = $"{me}:ZScoreSetNullValue"; + var score = db.SortedSetScore(setKey, "bogusMemberName"); + + Assert.Null(score); + } + + [Fact] + public void SortedSetScoreMultiple() + { + using var conn = Create(); + Skip.IfBelow(conn, RedisFeatures.v6_2_0); + + var db = conn.GetDatabase(); + var me = Me(); + + var setKey = $"{me}:ZScoreSetMultiple"; + var member1 = $"{me}:ZScoreSetMultiple_Member1"; + var member2 = $"{me}:ZScoreSetMultiple_Member2"; + var member3 = $"{me}:ZScoreSetMultiple_Member3"; + + db.SortedSetAdd(setKey, member1, 1.5); + db.SortedSetAdd(setKey, member2, 1.75); + db.SortedSetAdd(setKey, member3, 2); + + var scores = db.SortedSetScore(setKey, new RedisValue[] { member1, member2, member3 }); + + Assert.NotNull(scores); + Assert.Equal(3, scores.Length); + Assert.Equal((double)1.5, scores[0]); + Assert.Equal((double)1.75, scores[1]); + Assert.Equal((double)2, scores[2]); + } + + [Fact] + public void SortedSetScoreMultiple_ReturnsNullItems() + { + using var conn = Create(); + Skip.IfBelow(conn, RedisFeatures.v6_2_0); + + var db = conn.GetDatabase(); + var me = Me(); + + var setKey = $"{me}:ZScoreSetMultiple"; + var member1 = $"{me}:ZScoreSetMultiple_Member1"; + var member2 = $"{me}:ZScoreSetMultiple_Member2"; + var member3 = $"{me}:ZScoreSetMultiple_Member3"; + var bogusMember = $"{me}:ZScoreSetMultiple_BogusMember"; + + db.SortedSetAdd(setKey, member1, 1.5); + db.SortedSetAdd(setKey, member2, 1.75); + db.SortedSetAdd(setKey, member3, 2); + + var scores = db.SortedSetScore(setKey, new RedisValue[] { member1, bogusMember, member2, member3 }); + + Assert.NotNull(scores); + Assert.Equal(4, scores.Length); + Assert.Null(scores[1]); + Assert.Equal((double)1.5, scores[0]); + Assert.Equal((double)1.75, scores[2]); + Assert.Equal(2, scores[3]); + } } } diff --git a/tests/StackExchange.Redis.Tests/WrapperBaseTests.cs b/tests/StackExchange.Redis.Tests/WrapperBaseTests.cs index fac9fce28..95d6c0ab9 100644 --- a/tests/StackExchange.Redis.Tests/WrapperBaseTests.cs +++ b/tests/StackExchange.Redis.Tests/WrapperBaseTests.cs @@ -815,6 +815,13 @@ public void SortedSetScoreAsync() mock.Verify(_ => _.SortedSetScoreAsync("prefix:key", "member", CommandFlags.None)); } + [Fact] + public void SortedSetScoreAsync_Multiple() + { + wrapper.SortedSetScoreAsync("key", new RedisValue[] { "member1", "member2" }, CommandFlags.None); + mock.Verify(_ => _.SortedSetScoreAsync("prefix:key", new RedisValue[] { "member1", "member2" }, CommandFlags.None)); + } + [Fact] public void StreamAcknowledgeAsync_1() { From aed021b77d27850a6a146a22ae1f06f49be58a10 Mon Sep 17 00:00:00 2001 From: Todd Tingen Date: Tue, 12 Apr 2022 08:45:13 -0400 Subject: [PATCH 2/6] Simplify double array result processing and updates to tests. --- src/StackExchange.Redis/ResultProcessor.cs | 12 +- tests/StackExchange.Redis.Tests/SortedSets.cs | 220 ++++++++++++++++-- 2 files changed, 211 insertions(+), 21 deletions(-) diff --git a/src/StackExchange.Redis/ResultProcessor.cs b/src/StackExchange.Redis/ResultProcessor.cs index 657fc2992..8d3a08b26 100644 --- a/src/StackExchange.Redis/ResultProcessor.cs +++ b/src/StackExchange.Redis/ResultProcessor.cs @@ -1091,15 +1091,11 @@ private sealed class NullableDoubleArrayProcessor : ResultProcessor { protected override bool SetResultCore(PhysicalConnection connection, Message message, in RawResult result) { - switch (result.Type) + if (result.Type == ResultType.MultiBulk && !result.IsNull) { - case ResultType.Integer: - case ResultType.SimpleString: - case ResultType.BulkString: - case ResultType.MultiBulk: - var values = result.GetItemsAsDoubles()!; - SetResult(message, values); - return true; + var arr = result.GetItemsAsDoubles()!; + SetResult(message, arr); + return true; } return false; } diff --git a/tests/StackExchange.Redis.Tests/SortedSets.cs b/tests/StackExchange.Redis.Tests/SortedSets.cs index f51a06490..210a00e41 100644 --- a/tests/StackExchange.Redis.Tests/SortedSets.cs +++ b/tests/StackExchange.Redis.Tests/SortedSets.cs @@ -649,10 +649,12 @@ public void SortedSetScoreSingle() var db = conn.GetDatabase(); var me = Me(); - var setKey = $"{me}:ZScoreSet"; - var memberName = $"{me}:ZScoreMember"; + var setKey = $"{me}:ZScoreSetSingle"; + var memberName = "member"; + db.KeyDelete(setKey); db.SortedSetAdd(setKey, memberName, 1.5); + var score = db.SortedSetScore(setKey, memberName); Assert.NotNull(score); @@ -660,7 +662,66 @@ public void SortedSetScoreSingle() } [Fact] - public void SortedSetScoreSingle_ReturnsNull() + public async Task SortedSetScoreSingleAsync() + { + using var conn = Create(); + Skip.IfBelow(conn, RedisFeatures.v2_1_0); + + var db = conn.GetDatabase(); + var me = Me(); + + var setKey = $"{me}:ZScoreSetSingleAsync"; + var memberName = "member"; + + await db.KeyDeleteAsync(setKey); + await db.SortedSetAddAsync(setKey, memberName, 1.5); + + var score = await db.SortedSetScoreAsync(setKey, memberName); + + Assert.NotNull(score); + Assert.Equal((double)1.5, score.Value); + } + + [Fact] + public void SortedSetScoreSingle_MissingSetStillReturnsNull() + { + using var conn = Create(); + Skip.IfBelow(conn, RedisFeatures.v2_1_0); + + var db = conn.GetDatabase(); + var me = Me(); + + var setKey = $"{me}:ZScoreMissingSetSingle"; + + db.KeyDelete(setKey); + + // Attempt to retrieve score for a missing set, should still return null. + var score = db.SortedSetScore(setKey, "bogusMemberName"); + + Assert.Null(score); + } + + [Fact] + public async Task SortedSetScoreSingle_MissingSetStillReturnsNullAsync() + { + using var conn = Create(); + Skip.IfBelow(conn, RedisFeatures.v2_1_0); + + var db = conn.GetDatabase(); + var me = Me(); + + var setKey = $"{me}:ZScoreMissingSetSingleAsync"; + + await db.KeyDeleteAsync(setKey); + + // Attempt to retrieve score for a missing set, should still return null. + var score = await db.SortedSetScoreAsync(setKey, "bogusMemberName"); + + Assert.Null(score); + } + + [Fact] + public void SortedSetScoreSingle_ReturnsNullForMissingMember() { using var conn = Create(); Skip.IfBelow(conn, RedisFeatures.v2_1_0); @@ -669,11 +730,36 @@ public void SortedSetScoreSingle_ReturnsNull() var me = Me(); var setKey = $"{me}:ZScoreSetNullValue"; + + db.KeyDelete(setKey); + db.SortedSetAdd(setKey, "member1", 1.5); + + // Attempt to retrieve score for a missing member, should return null. var score = db.SortedSetScore(setKey, "bogusMemberName"); Assert.Null(score); } + [Fact] + public async Task SortedSetScoreSingle_ReturnsNullForMissingMemberAsync() + { + using var conn = Create(); + Skip.IfBelow(conn, RedisFeatures.v2_1_0); + + var db = conn.GetDatabase(); + var me = Me(); + + var setKey = $"{me}:ZScoreSetNullValueAsync"; + + await db.KeyDeleteAsync(setKey); + await db.SortedSetAddAsync(setKey, "member1", 1.5); + + // Attempt to retrieve score for a missing member, should return null. + var score = await db.SortedSetScoreAsync(setKey, "bogusMemberName"); + + Assert.Null(score); + } + [Fact] public void SortedSetScoreMultiple() { @@ -684,10 +770,11 @@ public void SortedSetScoreMultiple() var me = Me(); var setKey = $"{me}:ZScoreSetMultiple"; - var member1 = $"{me}:ZScoreSetMultiple_Member1"; - var member2 = $"{me}:ZScoreSetMultiple_Member2"; - var member3 = $"{me}:ZScoreSetMultiple_Member3"; + var member1 = "member1"; + var member2 = "member2"; + var member3 = "member3"; + db.KeyDelete(setKey); db.SortedSetAdd(setKey, member1, 1.5); db.SortedSetAdd(setKey, member2, 1.75); db.SortedSetAdd(setKey, member3, 2); @@ -698,11 +785,11 @@ public void SortedSetScoreMultiple() Assert.Equal(3, scores.Length); Assert.Equal((double)1.5, scores[0]); Assert.Equal((double)1.75, scores[1]); - Assert.Equal((double)2, scores[2]); + Assert.Equal(2, scores[2]); } [Fact] - public void SortedSetScoreMultiple_ReturnsNullItems() + public async Task SortedSetScoreMultipleAsync() { using var conn = Create(); Skip.IfBelow(conn, RedisFeatures.v6_2_0); @@ -710,11 +797,87 @@ public void SortedSetScoreMultiple_ReturnsNullItems() var db = conn.GetDatabase(); var me = Me(); - var setKey = $"{me}:ZScoreSetMultiple"; - var member1 = $"{me}:ZScoreSetMultiple_Member1"; - var member2 = $"{me}:ZScoreSetMultiple_Member2"; - var member3 = $"{me}:ZScoreSetMultiple_Member3"; - var bogusMember = $"{me}:ZScoreSetMultiple_BogusMember"; + var setKey = $"{me}:ZScoreSetMultipleAsync"; + var member1 = "member1"; + var member2 = "member2"; + var member3 = "member3"; + + await db.KeyDeleteAsync(setKey); + await db.SortedSetAddAsync(setKey, member1, 1.5); + await db.SortedSetAddAsync(setKey, member2, 1.75); + await db.SortedSetAddAsync(setKey, member3, 2); + + var scores = await db.SortedSetScoreAsync(setKey, new RedisValue[] { member1, member2, member3 }); + + Assert.NotNull(scores); + Assert.Equal(3, scores.Length); + Assert.Equal((double)1.5, scores[0]); + Assert.Equal((double)1.75, scores[1]); + Assert.Equal(2, scores[2]); + } + + [Fact] + public void SortedSetScoreMultiple_ReturnsNullItemsForMissingSet() + { + using var conn = Create(); + Skip.IfBelow(conn, RedisFeatures.v6_2_0); + + var db = conn.GetDatabase(); + var me = Me(); + + var setKey = $"{me}:ZScoreSetMultipleMissingSet"; + + db.KeyDelete(setKey); + + // Missing set but should still return an array of nulls. + var scores = db.SortedSetScore(setKey, new RedisValue[] { "bogus1", "bogus2", "bogus3" }); + + Assert.NotNull(scores); + Assert.Equal(3, scores.Length); + Assert.Null(scores[0]); + Assert.Null(scores[1]); + Assert.Null(scores[2]); + } + + [Fact] + public async Task SortedSetScoreMultiple_ReturnsNullItemsForMissingSetAsync() + { + using var conn = Create(); + Skip.IfBelow(conn, RedisFeatures.v6_2_0); + + var db = conn.GetDatabase(); + var me = Me(); + + var setKey = $"{me}:ZScoreSetMultipleMissingSetAsync"; + + await db.KeyDeleteAsync(setKey); + + // Missing set but should still return an array of nulls. + var scores = await db.SortedSetScoreAsync(setKey, new RedisValue[] { "bogus1", "bogus2", "bogus3" }); + + Assert.NotNull(scores); + Assert.Equal(3, scores.Length); + Assert.Null(scores[0]); + Assert.Null(scores[1]); + Assert.Null(scores[2]); + } + + [Fact] + public void SortedSetScoreMultiple_ReturnsScoresAndNullItems() + { + using var conn = Create(); + Skip.IfBelow(conn, RedisFeatures.v6_2_0); + + var db = conn.GetDatabase(); + var me = Me(); + + var setKey = $"{me}:ZScoreSetMultipleScoresAndNull"; + var member1 = "member1"; + var member2 = "member2"; + var member3 = "member3"; + var bogusMember = "bogusMember"; + + db.KeyDelete(setKey); db.SortedSetAdd(setKey, member1, 1.5); db.SortedSetAdd(setKey, member2, 1.75); @@ -729,5 +892,36 @@ public void SortedSetScoreMultiple_ReturnsNullItems() Assert.Equal((double)1.75, scores[2]); Assert.Equal(2, scores[3]); } + + [Fact] + public async Task SortedSetScoreMultiple_ReturnsScoresAndNullItemsAsync() + { + using var conn = Create(); + Skip.IfBelow(conn, RedisFeatures.v6_2_0); + + var db = conn.GetDatabase(); + var me = Me(); + + var setKey = $"{me}:ZScoreSetMultipleScoresAndNullAsync"; + var member1 = "member1"; + var member2 = "member2"; + var member3 = "member3"; + var bogusMember = "bogusMember"; + + await db.KeyDeleteAsync(setKey); + + await db.SortedSetAddAsync(setKey, member1, 1.5); + await db.SortedSetAddAsync(setKey, member2, 1.75); + await db.SortedSetAddAsync(setKey, member3, 2); + + var scores = await db.SortedSetScoreAsync(setKey, new RedisValue[] { member1, bogusMember, member2, member3 }); + + Assert.NotNull(scores); + Assert.Equal(4, scores.Length); + Assert.Null(scores[1]); + Assert.Equal((double)1.5, scores[0]); + Assert.Equal((double)1.75, scores[2]); + Assert.Equal(2, scores[3]); + } } } From eabd1ad12893d0a5ee1f5c6850ea79a5f4c21bfa Mon Sep 17 00:00:00 2001 From: Todd Tingen Date: Tue, 12 Apr 2022 08:48:40 -0400 Subject: [PATCH 3/6] Doc tweaks. --- src/StackExchange.Redis/Interfaces/IDatabase.cs | 8 ++++---- src/StackExchange.Redis/Interfaces/IDatabaseAsync.cs | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/StackExchange.Redis/Interfaces/IDatabase.cs b/src/StackExchange.Redis/Interfaces/IDatabase.cs index b68edd1e7..9f305022a 100644 --- a/src/StackExchange.Redis/Interfaces/IDatabase.cs +++ b/src/StackExchange.Redis/Interfaces/IDatabase.cs @@ -1698,15 +1698,15 @@ IEnumerable SortedSetScan(RedisKey key, double? SortedSetScore(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None); /// - /// Returns the scores of members in the sorted set at key. - /// If a member does not exist in the sorted set, or key does not exist, nil is returned. + /// Returns the scores of members in the sorted set at . + /// If a member does not exist in the sorted set, or key does not exist, is returned. /// /// The key of the sorted set. /// The members to get a score for. /// The flags to use for this operation. /// - /// The scores of the members in the same order as the array. If a member does - /// not exist in the set, nil is returned. + /// The scores of the members in the same order as the array. + /// If a member does not exist in the set, is returned. /// /// https://redis.io/commands/zmscore double?[] SortedSetScore(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None); diff --git a/src/StackExchange.Redis/Interfaces/IDatabaseAsync.cs b/src/StackExchange.Redis/Interfaces/IDatabaseAsync.cs index 2991cb621..d92cca392 100644 --- a/src/StackExchange.Redis/Interfaces/IDatabaseAsync.cs +++ b/src/StackExchange.Redis/Interfaces/IDatabaseAsync.cs @@ -1651,15 +1651,15 @@ IAsyncEnumerable SortedSetScanAsync(RedisKey key, Task SortedSetScoreAsync(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None); /// - /// Returns the scores of members in the sorted set at key. - /// If a member does not exist in the sorted set, or key does not exist, nil is returned. + /// Returns the scores of members in the sorted set at . + /// If a member does not exist in the sorted set, or key does not exist, is returned. /// /// The key of the sorted set. /// The members to get a score for. /// The flags to use for this operation. /// - /// The scores of the members in the same order as the array. If a member does - /// not exist in the set, nil is returned. + /// The scores of the members in the same order as the array. + /// If a member does not exist in the set, is returned. /// /// https://redis.io/commands/zmscore Task SortedSetScoreAsync(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None); From 142a1ca80e7541c053a06f5d6786753e195a37f4 Mon Sep 17 00:00:00 2001 From: Nick Craver Date: Tue, 12 Apr 2022 09:27:28 -0400 Subject: [PATCH 4/6] Tests: normalize naming --- tests/StackExchange.Redis.Tests/SortedSets.cs | 128 +++++++----------- 1 file changed, 52 insertions(+), 76 deletions(-) diff --git a/tests/StackExchange.Redis.Tests/SortedSets.cs b/tests/StackExchange.Redis.Tests/SortedSets.cs index 210a00e41..835435ad1 100644 --- a/tests/StackExchange.Redis.Tests/SortedSets.cs +++ b/tests/StackExchange.Redis.Tests/SortedSets.cs @@ -647,15 +647,13 @@ public void SortedSetScoreSingle() Skip.IfBelow(conn, RedisFeatures.v2_1_0); var db = conn.GetDatabase(); - var me = Me(); - - var setKey = $"{me}:ZScoreSetSingle"; + var key = Me(); var memberName = "member"; - db.KeyDelete(setKey); - db.SortedSetAdd(setKey, memberName, 1.5); + db.KeyDelete(key); + db.SortedSetAdd(key, memberName, 1.5); - var score = db.SortedSetScore(setKey, memberName); + var score = db.SortedSetScore(key, memberName); Assert.NotNull(score); Assert.Equal((double)1.5, score.Value); @@ -668,15 +666,13 @@ public async Task SortedSetScoreSingleAsync() Skip.IfBelow(conn, RedisFeatures.v2_1_0); var db = conn.GetDatabase(); - var me = Me(); - - var setKey = $"{me}:ZScoreSetSingleAsync"; + var key = Me(); var memberName = "member"; - await db.KeyDeleteAsync(setKey); - await db.SortedSetAddAsync(setKey, memberName, 1.5); + await db.KeyDeleteAsync(key); + await db.SortedSetAddAsync(key, memberName, 1.5); - var score = await db.SortedSetScoreAsync(setKey, memberName); + var score = await db.SortedSetScoreAsync(key, memberName); Assert.NotNull(score); Assert.Equal((double)1.5, score.Value); @@ -689,14 +685,12 @@ public void SortedSetScoreSingle_MissingSetStillReturnsNull() Skip.IfBelow(conn, RedisFeatures.v2_1_0); var db = conn.GetDatabase(); - var me = Me(); - - var setKey = $"{me}:ZScoreMissingSetSingle"; + var key = Me(); - db.KeyDelete(setKey); + db.KeyDelete(key); // Attempt to retrieve score for a missing set, should still return null. - var score = db.SortedSetScore(setKey, "bogusMemberName"); + var score = db.SortedSetScore(key, "bogusMemberName"); Assert.Null(score); } @@ -708,14 +702,12 @@ public async Task SortedSetScoreSingle_MissingSetStillReturnsNullAsync() Skip.IfBelow(conn, RedisFeatures.v2_1_0); var db = conn.GetDatabase(); - var me = Me(); - - var setKey = $"{me}:ZScoreMissingSetSingleAsync"; + var key = Me(); - await db.KeyDeleteAsync(setKey); + await db.KeyDeleteAsync(key); // Attempt to retrieve score for a missing set, should still return null. - var score = await db.SortedSetScoreAsync(setKey, "bogusMemberName"); + var score = await db.SortedSetScoreAsync(key, "bogusMemberName"); Assert.Null(score); } @@ -727,15 +719,13 @@ public void SortedSetScoreSingle_ReturnsNullForMissingMember() Skip.IfBelow(conn, RedisFeatures.v2_1_0); var db = conn.GetDatabase(); - var me = Me(); + var key = Me(); - var setKey = $"{me}:ZScoreSetNullValue"; - - db.KeyDelete(setKey); - db.SortedSetAdd(setKey, "member1", 1.5); + db.KeyDelete(key); + db.SortedSetAdd(key, "member1", 1.5); // Attempt to retrieve score for a missing member, should return null. - var score = db.SortedSetScore(setKey, "bogusMemberName"); + var score = db.SortedSetScore(key, "bogusMemberName"); Assert.Null(score); } @@ -747,15 +737,13 @@ public async Task SortedSetScoreSingle_ReturnsNullForMissingMemberAsync() Skip.IfBelow(conn, RedisFeatures.v2_1_0); var db = conn.GetDatabase(); - var me = Me(); - - var setKey = $"{me}:ZScoreSetNullValueAsync"; + var key = Me(); - await db.KeyDeleteAsync(setKey); - await db.SortedSetAddAsync(setKey, "member1", 1.5); + await db.KeyDeleteAsync(key); + await db.SortedSetAddAsync(key, "member1", 1.5); // Attempt to retrieve score for a missing member, should return null. - var score = await db.SortedSetScoreAsync(setKey, "bogusMemberName"); + var score = await db.SortedSetScoreAsync(key, "bogusMemberName"); Assert.Null(score); } @@ -767,19 +755,17 @@ public void SortedSetScoreMultiple() Skip.IfBelow(conn, RedisFeatures.v6_2_0); var db = conn.GetDatabase(); - var me = Me(); - - var setKey = $"{me}:ZScoreSetMultiple"; + var key = Me(); var member1 = "member1"; var member2 = "member2"; var member3 = "member3"; - db.KeyDelete(setKey); - db.SortedSetAdd(setKey, member1, 1.5); - db.SortedSetAdd(setKey, member2, 1.75); - db.SortedSetAdd(setKey, member3, 2); + db.KeyDelete(key); + db.SortedSetAdd(key, member1, 1.5); + db.SortedSetAdd(key, member2, 1.75); + db.SortedSetAdd(key, member3, 2); - var scores = db.SortedSetScore(setKey, new RedisValue[] { member1, member2, member3 }); + var scores = db.SortedSetScore(key, new RedisValue[] { member1, member2, member3 }); Assert.NotNull(scores); Assert.Equal(3, scores.Length); @@ -795,19 +781,17 @@ public async Task SortedSetScoreMultipleAsync() Skip.IfBelow(conn, RedisFeatures.v6_2_0); var db = conn.GetDatabase(); - var me = Me(); - - var setKey = $"{me}:ZScoreSetMultipleAsync"; + var key = Me(); var member1 = "member1"; var member2 = "member2"; var member3 = "member3"; - await db.KeyDeleteAsync(setKey); - await db.SortedSetAddAsync(setKey, member1, 1.5); - await db.SortedSetAddAsync(setKey, member2, 1.75); - await db.SortedSetAddAsync(setKey, member3, 2); + await db.KeyDeleteAsync(key); + await db.SortedSetAddAsync(key, member1, 1.5); + await db.SortedSetAddAsync(key, member2, 1.75); + await db.SortedSetAddAsync(key, member3, 2); - var scores = await db.SortedSetScoreAsync(setKey, new RedisValue[] { member1, member2, member3 }); + var scores = await db.SortedSetScoreAsync(key, new RedisValue[] { member1, member2, member3 }); Assert.NotNull(scores); Assert.Equal(3, scores.Length); @@ -823,14 +807,12 @@ public void SortedSetScoreMultiple_ReturnsNullItemsForMissingSet() Skip.IfBelow(conn, RedisFeatures.v6_2_0); var db = conn.GetDatabase(); - var me = Me(); - - var setKey = $"{me}:ZScoreSetMultipleMissingSet"; + var key = Me(); - db.KeyDelete(setKey); + db.KeyDelete(key); // Missing set but should still return an array of nulls. - var scores = db.SortedSetScore(setKey, new RedisValue[] { "bogus1", "bogus2", "bogus3" }); + var scores = db.SortedSetScore(key, new RedisValue[] { "bogus1", "bogus2", "bogus3" }); Assert.NotNull(scores); Assert.Equal(3, scores.Length); @@ -846,14 +828,12 @@ public async Task SortedSetScoreMultiple_ReturnsNullItemsForMissingSetAsync() Skip.IfBelow(conn, RedisFeatures.v6_2_0); var db = conn.GetDatabase(); - var me = Me(); - - var setKey = $"{me}:ZScoreSetMultipleMissingSetAsync"; + var key = Me(); - await db.KeyDeleteAsync(setKey); + await db.KeyDeleteAsync(key); // Missing set but should still return an array of nulls. - var scores = await db.SortedSetScoreAsync(setKey, new RedisValue[] { "bogus1", "bogus2", "bogus3" }); + var scores = await db.SortedSetScoreAsync(key, new RedisValue[] { "bogus1", "bogus2", "bogus3" }); Assert.NotNull(scores); Assert.Equal(3, scores.Length); @@ -869,21 +849,19 @@ public void SortedSetScoreMultiple_ReturnsScoresAndNullItems() Skip.IfBelow(conn, RedisFeatures.v6_2_0); var db = conn.GetDatabase(); - var me = Me(); - - var setKey = $"{me}:ZScoreSetMultipleScoresAndNull"; + var key = Me(); var member1 = "member1"; var member2 = "member2"; var member3 = "member3"; var bogusMember = "bogusMember"; - db.KeyDelete(setKey); + db.KeyDelete(key); - db.SortedSetAdd(setKey, member1, 1.5); - db.SortedSetAdd(setKey, member2, 1.75); - db.SortedSetAdd(setKey, member3, 2); + db.SortedSetAdd(key, member1, 1.5); + db.SortedSetAdd(key, member2, 1.75); + db.SortedSetAdd(key, member3, 2); - var scores = db.SortedSetScore(setKey, new RedisValue[] { member1, bogusMember, member2, member3 }); + var scores = db.SortedSetScore(key, new RedisValue[] { member1, bogusMember, member2, member3 }); Assert.NotNull(scores); Assert.Equal(4, scores.Length); @@ -900,21 +878,19 @@ public async Task SortedSetScoreMultiple_ReturnsScoresAndNullItemsAsync() Skip.IfBelow(conn, RedisFeatures.v6_2_0); var db = conn.GetDatabase(); - var me = Me(); - - var setKey = $"{me}:ZScoreSetMultipleScoresAndNullAsync"; + var key = Me(); var member1 = "member1"; var member2 = "member2"; var member3 = "member3"; var bogusMember = "bogusMember"; - await db.KeyDeleteAsync(setKey); + await db.KeyDeleteAsync(key); - await db.SortedSetAddAsync(setKey, member1, 1.5); - await db.SortedSetAddAsync(setKey, member2, 1.75); - await db.SortedSetAddAsync(setKey, member3, 2); + await db.SortedSetAddAsync(key, member1, 1.5); + await db.SortedSetAddAsync(key, member2, 1.75); + await db.SortedSetAddAsync(key, member3, 2); - var scores = await db.SortedSetScoreAsync(setKey, new RedisValue[] { member1, bogusMember, member2, member3 }); + var scores = await db.SortedSetScoreAsync(key, new RedisValue[] { member1, bogusMember, member2, member3 }); Assert.NotNull(scores); Assert.Equal(4, scores.Length); From 86532a553091128ddcb20a78b125ed23366a7c92 Mon Sep 17 00:00:00 2001 From: Nick Craver Date: Tue, 12 Apr 2022 09:32:13 -0400 Subject: [PATCH 5/6] Rename to plural form --- .../Interfaces/IDatabase.cs | 2 +- .../Interfaces/IDatabaseAsync.cs | 2 +- .../KeyspaceIsolation/DatabaseWrapper.cs | 4 +-- .../KeyspaceIsolation/WrapperBase.cs | 4 +-- src/StackExchange.Redis/PublicAPI.Shipped.txt | 4 +-- src/StackExchange.Redis/RedisDatabase.cs | 4 +-- .../DatabaseWrapperTests.cs | 4 +-- tests/StackExchange.Redis.Tests/SortedSets.cs | 36 +++++++++---------- .../WrapperBaseTests.cs | 4 +-- 9 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/StackExchange.Redis/Interfaces/IDatabase.cs b/src/StackExchange.Redis/Interfaces/IDatabase.cs index 9f305022a..45acbe96a 100644 --- a/src/StackExchange.Redis/Interfaces/IDatabase.cs +++ b/src/StackExchange.Redis/Interfaces/IDatabase.cs @@ -1709,7 +1709,7 @@ IEnumerable SortedSetScan(RedisKey key, /// If a member does not exist in the set, is returned. /// /// https://redis.io/commands/zmscore - double?[] SortedSetScore(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None); + double?[] SortedSetScores(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None); /// /// Removes and returns the first element from the sorted set stored at key, by default with the scores ordered from low to high. diff --git a/src/StackExchange.Redis/Interfaces/IDatabaseAsync.cs b/src/StackExchange.Redis/Interfaces/IDatabaseAsync.cs index d92cca392..ba21a3d6c 100644 --- a/src/StackExchange.Redis/Interfaces/IDatabaseAsync.cs +++ b/src/StackExchange.Redis/Interfaces/IDatabaseAsync.cs @@ -1662,7 +1662,7 @@ IAsyncEnumerable SortedSetScanAsync(RedisKey key, /// If a member does not exist in the set, is returned. /// /// https://redis.io/commands/zmscore - Task SortedSetScoreAsync(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None); + Task SortedSetScoresAsync(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None); /// /// Removes and returns the first element from the sorted set stored at key, by default with the scores ordered from low to high. diff --git a/src/StackExchange.Redis/KeyspaceIsolation/DatabaseWrapper.cs b/src/StackExchange.Redis/KeyspaceIsolation/DatabaseWrapper.cs index eac91be5b..d491ac004 100644 --- a/src/StackExchange.Redis/KeyspaceIsolation/DatabaseWrapper.cs +++ b/src/StackExchange.Redis/KeyspaceIsolation/DatabaseWrapper.cs @@ -412,8 +412,8 @@ public long SortedSetRemoveRangeByValue(RedisKey key, RedisValue min, RedisValue public double? SortedSetScore(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) => Inner.SortedSetScore(ToInner(key), member, flags); - public double?[] SortedSetScore(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None) => - Inner.SortedSetScore(ToInner(key), members, flags); + public double?[] SortedSetScores(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None) => + Inner.SortedSetScores(ToInner(key), members, flags); public SortedSetEntry? SortedSetPop(RedisKey key, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None) => Inner.SortedSetPop(ToInner(key), order, flags); diff --git a/src/StackExchange.Redis/KeyspaceIsolation/WrapperBase.cs b/src/StackExchange.Redis/KeyspaceIsolation/WrapperBase.cs index 483429331..f60b2a933 100644 --- a/src/StackExchange.Redis/KeyspaceIsolation/WrapperBase.cs +++ b/src/StackExchange.Redis/KeyspaceIsolation/WrapperBase.cs @@ -425,8 +425,8 @@ public Task SortedSetRemoveRangeByValueAsync(RedisKey key, RedisValue min, public Task SortedSetScoreAsync(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) => Inner.SortedSetScoreAsync(ToInner(key), member, flags); - public Task SortedSetScoreAsync(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None) => - Inner.SortedSetScoreAsync(ToInner(key), members, flags); + public Task SortedSetScoresAsync(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None) => + Inner.SortedSetScoresAsync(ToInner(key), members, flags); public IAsyncEnumerable SortedSetScanAsync(RedisKey key, RedisValue pattern, int pageSize, long cursor, int pageOffset, CommandFlags flags) => Inner.SortedSetScanAsync(ToInner(key), pattern, pageSize, cursor, pageOffset, flags); diff --git a/src/StackExchange.Redis/PublicAPI.Shipped.txt b/src/StackExchange.Redis/PublicAPI.Shipped.txt index 5074802f7..db93a847c 100644 --- a/src/StackExchange.Redis/PublicAPI.Shipped.txt +++ b/src/StackExchange.Redis/PublicAPI.Shipped.txt @@ -615,7 +615,7 @@ StackExchange.Redis.IDatabase.SortedSetRemoveRangeByValue(StackExchange.Redis.Re StackExchange.Redis.IDatabase.SortedSetScan(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue pattern = default(StackExchange.Redis.RedisValue), int pageSize = 250, long cursor = 0, int pageOffset = 0, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Collections.Generic.IEnumerable! StackExchange.Redis.IDatabase.SortedSetScan(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue pattern, int pageSize, StackExchange.Redis.CommandFlags flags) -> System.Collections.Generic.IEnumerable! StackExchange.Redis.IDatabase.SortedSetScore(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue member, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> double? -StackExchange.Redis.IDatabase.SortedSetScore(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! members, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> double?[]! +StackExchange.Redis.IDatabase.SortedSetScores(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! members, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> double?[]! StackExchange.Redis.IDatabase.StreamAcknowledge(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue groupName, StackExchange.Redis.RedisValue messageId, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> long StackExchange.Redis.IDatabase.StreamAcknowledge(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue groupName, StackExchange.Redis.RedisValue[]! messageIds, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> long StackExchange.Redis.IDatabase.StreamAdd(StackExchange.Redis.RedisKey key, StackExchange.Redis.NameValueEntry[]! streamPairs, StackExchange.Redis.RedisValue? messageId = null, int? maxLength = null, bool useApproximateMaxLength = false, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> StackExchange.Redis.RedisValue @@ -805,7 +805,7 @@ StackExchange.Redis.IDatabaseAsync.SortedSetRemoveRangeByScoreAsync(StackExchang StackExchange.Redis.IDatabaseAsync.SortedSetRemoveRangeByValueAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue min, StackExchange.Redis.RedisValue max, StackExchange.Redis.Exclude exclude = StackExchange.Redis.Exclude.None, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task! StackExchange.Redis.IDatabaseAsync.SortedSetScanAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue pattern = default(StackExchange.Redis.RedisValue), int pageSize = 250, long cursor = 0, int pageOffset = 0, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Collections.Generic.IAsyncEnumerable! StackExchange.Redis.IDatabaseAsync.SortedSetScoreAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue member, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task! -StackExchange.Redis.IDatabaseAsync.SortedSetScoreAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! members, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task! +StackExchange.Redis.IDatabaseAsync.SortedSetScoresAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! members, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task! StackExchange.Redis.IDatabaseAsync.StreamAcknowledgeAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue groupName, StackExchange.Redis.RedisValue messageId, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task! StackExchange.Redis.IDatabaseAsync.StreamAcknowledgeAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue groupName, StackExchange.Redis.RedisValue[]! messageIds, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task! StackExchange.Redis.IDatabaseAsync.StreamAddAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.NameValueEntry[]! streamPairs, StackExchange.Redis.RedisValue? messageId = null, int? maxLength = null, bool useApproximateMaxLength = false, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task! diff --git a/src/StackExchange.Redis/RedisDatabase.cs b/src/StackExchange.Redis/RedisDatabase.cs index 8907e97f1..00d9bd049 100644 --- a/src/StackExchange.Redis/RedisDatabase.cs +++ b/src/StackExchange.Redis/RedisDatabase.cs @@ -1827,7 +1827,7 @@ private CursorEnumerable SortedSetScanAsync(RedisKey key, RedisV return ExecuteSync(msg, ResultProcessor.NullableDouble); } - public double?[] SortedSetScore(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None) + public double?[] SortedSetScores(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None) { var msg = Message.Create(Database, flags, RedisCommand.ZMSCORE, key, members); return ExecuteSync(msg, ResultProcessor.NullableDoubleArray, defaultValue: Array.Empty()); @@ -1839,7 +1839,7 @@ private CursorEnumerable SortedSetScanAsync(RedisKey key, RedisV return ExecuteAsync(msg, ResultProcessor.NullableDouble); } - public Task SortedSetScoreAsync(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None) + public Task SortedSetScoresAsync(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None) { var msg = Message.Create(Database, flags, RedisCommand.ZMSCORE, key, members); return ExecuteAsync(msg, ResultProcessor.NullableDoubleArray, defaultValue: Array.Empty()); diff --git a/tests/StackExchange.Redis.Tests/DatabaseWrapperTests.cs b/tests/StackExchange.Redis.Tests/DatabaseWrapperTests.cs index 210e6c80d..dc694bc90 100644 --- a/tests/StackExchange.Redis.Tests/DatabaseWrapperTests.cs +++ b/tests/StackExchange.Redis.Tests/DatabaseWrapperTests.cs @@ -886,8 +886,8 @@ public void SortedSetScore() [Fact] public void SortedSetScore_Multiple() { - wrapper.SortedSetScore("key", new RedisValue[] { "member1", "member2" }, CommandFlags.None); - mock.Verify(_ => _.SortedSetScore("prefix:key", new RedisValue[] { "member1", "member2" }, CommandFlags.None)); + wrapper.SortedSetScores("key", new RedisValue[] { "member1", "member2" }, CommandFlags.None); + mock.Verify(_ => _.SortedSetScores("prefix:key", new RedisValue[] { "member1", "member2" }, CommandFlags.None)); } [Fact] diff --git a/tests/StackExchange.Redis.Tests/SortedSets.cs b/tests/StackExchange.Redis.Tests/SortedSets.cs index 835435ad1..087c271bb 100644 --- a/tests/StackExchange.Redis.Tests/SortedSets.cs +++ b/tests/StackExchange.Redis.Tests/SortedSets.cs @@ -641,7 +641,7 @@ public void SortedSetRangeStoreFailExclude() } [Fact] - public void SortedSetScoreSingle() + public void SortedSetScoresSingle() { using var conn = Create(); Skip.IfBelow(conn, RedisFeatures.v2_1_0); @@ -660,7 +660,7 @@ public void SortedSetScoreSingle() } [Fact] - public async Task SortedSetScoreSingleAsync() + public async Task SortedSetScoresSingleAsync() { using var conn = Create(); Skip.IfBelow(conn, RedisFeatures.v2_1_0); @@ -679,7 +679,7 @@ public async Task SortedSetScoreSingleAsync() } [Fact] - public void SortedSetScoreSingle_MissingSetStillReturnsNull() + public void SortedSetScoresSingle_MissingSetStillReturnsNull() { using var conn = Create(); Skip.IfBelow(conn, RedisFeatures.v2_1_0); @@ -696,7 +696,7 @@ public void SortedSetScoreSingle_MissingSetStillReturnsNull() } [Fact] - public async Task SortedSetScoreSingle_MissingSetStillReturnsNullAsync() + public async Task SortedSetScoresSingle_MissingSetStillReturnsNullAsync() { using var conn = Create(); Skip.IfBelow(conn, RedisFeatures.v2_1_0); @@ -713,7 +713,7 @@ public async Task SortedSetScoreSingle_MissingSetStillReturnsNullAsync() } [Fact] - public void SortedSetScoreSingle_ReturnsNullForMissingMember() + public void SortedSetScoresSingle_ReturnsNullForMissingMember() { using var conn = Create(); Skip.IfBelow(conn, RedisFeatures.v2_1_0); @@ -731,7 +731,7 @@ public void SortedSetScoreSingle_ReturnsNullForMissingMember() } [Fact] - public async Task SortedSetScoreSingle_ReturnsNullForMissingMemberAsync() + public async Task SortedSetScoresSingle_ReturnsNullForMissingMemberAsync() { using var conn = Create(); Skip.IfBelow(conn, RedisFeatures.v2_1_0); @@ -749,7 +749,7 @@ public async Task SortedSetScoreSingle_ReturnsNullForMissingMemberAsync() } [Fact] - public void SortedSetScoreMultiple() + public void SortedSetScoresMultiple() { using var conn = Create(); Skip.IfBelow(conn, RedisFeatures.v6_2_0); @@ -765,7 +765,7 @@ public void SortedSetScoreMultiple() db.SortedSetAdd(key, member2, 1.75); db.SortedSetAdd(key, member3, 2); - var scores = db.SortedSetScore(key, new RedisValue[] { member1, member2, member3 }); + var scores = db.SortedSetScores(key, new RedisValue[] { member1, member2, member3 }); Assert.NotNull(scores); Assert.Equal(3, scores.Length); @@ -775,7 +775,7 @@ public void SortedSetScoreMultiple() } [Fact] - public async Task SortedSetScoreMultipleAsync() + public async Task SortedSetScoresMultipleAsync() { using var conn = Create(); Skip.IfBelow(conn, RedisFeatures.v6_2_0); @@ -791,7 +791,7 @@ public async Task SortedSetScoreMultipleAsync() await db.SortedSetAddAsync(key, member2, 1.75); await db.SortedSetAddAsync(key, member3, 2); - var scores = await db.SortedSetScoreAsync(key, new RedisValue[] { member1, member2, member3 }); + var scores = await db.SortedSetScoresAsync(key, new RedisValue[] { member1, member2, member3 }); Assert.NotNull(scores); Assert.Equal(3, scores.Length); @@ -801,7 +801,7 @@ public async Task SortedSetScoreMultipleAsync() } [Fact] - public void SortedSetScoreMultiple_ReturnsNullItemsForMissingSet() + public void SortedSetScoresMultiple_ReturnsNullItemsForMissingSet() { using var conn = Create(); Skip.IfBelow(conn, RedisFeatures.v6_2_0); @@ -812,7 +812,7 @@ public void SortedSetScoreMultiple_ReturnsNullItemsForMissingSet() db.KeyDelete(key); // Missing set but should still return an array of nulls. - var scores = db.SortedSetScore(key, new RedisValue[] { "bogus1", "bogus2", "bogus3" }); + var scores = db.SortedSetScores(key, new RedisValue[] { "bogus1", "bogus2", "bogus3" }); Assert.NotNull(scores); Assert.Equal(3, scores.Length); @@ -822,7 +822,7 @@ public void SortedSetScoreMultiple_ReturnsNullItemsForMissingSet() } [Fact] - public async Task SortedSetScoreMultiple_ReturnsNullItemsForMissingSetAsync() + public async Task SortedSetScoresMultiple_ReturnsNullItemsForMissingSetAsync() { using var conn = Create(); Skip.IfBelow(conn, RedisFeatures.v6_2_0); @@ -833,7 +833,7 @@ public async Task SortedSetScoreMultiple_ReturnsNullItemsForMissingSetAsync() await db.KeyDeleteAsync(key); // Missing set but should still return an array of nulls. - var scores = await db.SortedSetScoreAsync(key, new RedisValue[] { "bogus1", "bogus2", "bogus3" }); + var scores = await db.SortedSetScoresAsync(key, new RedisValue[] { "bogus1", "bogus2", "bogus3" }); Assert.NotNull(scores); Assert.Equal(3, scores.Length); @@ -843,7 +843,7 @@ public async Task SortedSetScoreMultiple_ReturnsNullItemsForMissingSetAsync() } [Fact] - public void SortedSetScoreMultiple_ReturnsScoresAndNullItems() + public void SortedSetScoresMultiple_ReturnsScoresAndNullItems() { using var conn = Create(); Skip.IfBelow(conn, RedisFeatures.v6_2_0); @@ -861,7 +861,7 @@ public void SortedSetScoreMultiple_ReturnsScoresAndNullItems() db.SortedSetAdd(key, member2, 1.75); db.SortedSetAdd(key, member3, 2); - var scores = db.SortedSetScore(key, new RedisValue[] { member1, bogusMember, member2, member3 }); + var scores = db.SortedSetScores(key, new RedisValue[] { member1, bogusMember, member2, member3 }); Assert.NotNull(scores); Assert.Equal(4, scores.Length); @@ -872,7 +872,7 @@ public void SortedSetScoreMultiple_ReturnsScoresAndNullItems() } [Fact] - public async Task SortedSetScoreMultiple_ReturnsScoresAndNullItemsAsync() + public async Task SortedSetScoresMultiple_ReturnsScoresAndNullItemsAsync() { using var conn = Create(); Skip.IfBelow(conn, RedisFeatures.v6_2_0); @@ -890,7 +890,7 @@ public async Task SortedSetScoreMultiple_ReturnsScoresAndNullItemsAsync() await db.SortedSetAddAsync(key, member2, 1.75); await db.SortedSetAddAsync(key, member3, 2); - var scores = await db.SortedSetScoreAsync(key, new RedisValue[] { member1, bogusMember, member2, member3 }); + var scores = await db.SortedSetScoresAsync(key, new RedisValue[] { member1, bogusMember, member2, member3 }); Assert.NotNull(scores); Assert.Equal(4, scores.Length); diff --git a/tests/StackExchange.Redis.Tests/WrapperBaseTests.cs b/tests/StackExchange.Redis.Tests/WrapperBaseTests.cs index 95d6c0ab9..43652cd22 100644 --- a/tests/StackExchange.Redis.Tests/WrapperBaseTests.cs +++ b/tests/StackExchange.Redis.Tests/WrapperBaseTests.cs @@ -818,8 +818,8 @@ public void SortedSetScoreAsync() [Fact] public void SortedSetScoreAsync_Multiple() { - wrapper.SortedSetScoreAsync("key", new RedisValue[] { "member1", "member2" }, CommandFlags.None); - mock.Verify(_ => _.SortedSetScoreAsync("prefix:key", new RedisValue[] { "member1", "member2" }, CommandFlags.None)); + wrapper.SortedSetScoresAsync("key", new RedisValue[] { "member1", "member2" }, CommandFlags.None); + mock.Verify(_ => _.SortedSetScoresAsync("prefix:key", new RedisValue[] { "member1", "member2" }, CommandFlags.None)); } [Fact] From b58aaa03cfc2d7d610f464c8b3ee4ef2b532407c Mon Sep 17 00:00:00 2001 From: Nick Craver Date: Tue, 12 Apr 2022 09:32:19 -0400 Subject: [PATCH 6/6] Add release notes --- docs/ReleaseNotes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/ReleaseNotes.md b/docs/ReleaseNotes.md index 00ef24fb2..aabd837c9 100644 --- a/docs/ReleaseNotes.md +++ b/docs/ReleaseNotes.md @@ -10,6 +10,7 @@ - Adds: Support for `COPY` with `.KeyCopy()`/`.KeyCopyAsync()` ([#2064 by Avital-Fine](https://github.com/StackExchange/StackExchange.Redis/pull/2064)) - Adds: Support for `LMOVE` with `.ListMove()`/`.ListMoveAsync()` ([#2065 by Avital-Fine](https://github.com/StackExchange/StackExchange.Redis/pull/2065)) - Adds: Support for `SINTERCARD` with `.SetIntersectionLength()`/`.SetIntersectionLengthAsync()` ([#2078 by Avital-Fine](https://github.com/StackExchange/StackExchange.Redis/pull/2078)) +- Adds: Support for `ZMSCORE` with `.SortedSetScores()`/.`SortedSetScoresAsync()` ([#2082 by ttingen](https://github.com/StackExchange/StackExchange.Redis/pull/2082)) ## 2.5.61