From 6a150829fcd660ca5c1f53a524bf4fa097a9ac72 Mon Sep 17 00:00:00 2001 From: Niels Derdaele Date: Wed, 13 Apr 2022 11:17:00 +0200 Subject: [PATCH 1/3] Use a Message type with a RedisKey for XACK, XCLAIM and XPENDING commands => fixes incorrect HashSlot calculation. --- src/StackExchange.Redis/RedisDatabase.cs | 29 +++++++++++------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/src/StackExchange.Redis/RedisDatabase.cs b/src/StackExchange.Redis/RedisDatabase.cs index 03707579a..9c9a08210 100644 --- a/src/StackExchange.Redis/RedisDatabase.cs +++ b/src/StackExchange.Redis/RedisDatabase.cs @@ -3422,13 +3422,12 @@ private Message GetSortedSetRemoveRangeByScoreMessage(RedisKey key, double start private Message GetStreamAcknowledgeMessage(RedisKey key, RedisValue groupName, RedisValue messageId, CommandFlags flags) { var values = new RedisValue[] - { - key.AsRedisValue(), + { groupName, messageId }; - return Message.Create(Database, flags, RedisCommand.XACK, values); + return Message.Create(Database, flags, RedisCommand.XACK, key, values); } private Message GetStreamAcknowledgeMessage(RedisKey key, RedisValue groupName, RedisValue[] messageIds, CommandFlags flags) @@ -3436,11 +3435,10 @@ private Message GetStreamAcknowledgeMessage(RedisKey key, RedisValue groupName, if (messageIds == null) throw new ArgumentNullException(nameof(messageIds)); if (messageIds.Length == 0) throw new ArgumentOutOfRangeException(nameof(messageIds), "messageIds must contain at least one item."); - var values = new RedisValue[messageIds.Length + 2]; + var values = new RedisValue[messageIds.Length + 1]; var offset = 0; - values[offset++] = key.AsRedisValue(); values[offset++] = groupName; for (var i = 0; i < messageIds.Length; i++) @@ -3448,7 +3446,7 @@ private Message GetStreamAcknowledgeMessage(RedisKey key, RedisValue groupName, values[offset++] = messageIds[i]; } - return Message.Create(Database, flags, RedisCommand.XACK, values); + return Message.Create(Database, flags, RedisCommand.XACK, key, values); } private Message GetStreamAddMessage(RedisKey key, RedisValue messageId, int? maxLength, bool useApproximateMaxLength, NameValueEntry streamPair, CommandFlags flags) @@ -3539,11 +3537,10 @@ private Message GetStreamClaimMessage(RedisKey key, RedisValue consumerGroup, Re if (messageIds.Length == 0) throw new ArgumentOutOfRangeException(nameof(messageIds), "messageIds must contain at least one item."); // XCLAIM ... - var values = new RedisValue[4 + messageIds.Length + (returnJustIds ? 1 : 0)]; + var values = new RedisValue[3 + messageIds.Length + (returnJustIds ? 1 : 0)]; var offset = 0; - values[offset++] = key.AsRedisValue(); values[offset++] = consumerGroup; values[offset++] = assignToConsumer; values[offset++] = minIdleTimeInMs; @@ -3558,7 +3555,7 @@ private Message GetStreamClaimMessage(RedisKey key, RedisValue consumerGroup, Re values[offset] = StreamConstants.JustId; } - return Message.Create(Database, flags, RedisCommand.XCLAIM, values); + return Message.Create(Database, flags, RedisCommand.XCLAIM, key, values); } private Message GetStreamCreateConsumerGroupMessage(RedisKey key, RedisValue groupName, RedisValue? position = null, bool createStream = true, CommandFlags flags = CommandFlags.None) @@ -3602,22 +3599,22 @@ private Message GetStreamPendingMessagesMessage(RedisKey key, RedisValue groupNa throw new ArgumentOutOfRangeException(nameof(count), "count must be greater than 0."); } - var values = new RedisValue[consumerName == RedisValue.Null ? 5 : 6]; + var values = new RedisValue[consumerName == RedisValue.Null ? 4 : 5]; - values[0] = key.AsRedisValue(); - values[1] = groupName; - values[2] = minId ?? StreamConstants.ReadMinValue; - values[3] = maxId ?? StreamConstants.ReadMaxValue; - values[4] = count; + values[0] = groupName; + values[1] = minId ?? StreamConstants.ReadMinValue; + values[2] = maxId ?? StreamConstants.ReadMaxValue; + values[3] = count; if (consumerName != RedisValue.Null) { - values[5] = consumerName; + values[4] = consumerName; } return Message.Create(Database, flags, RedisCommand.XPENDING, + key, values); } From 7247837467b157f2ad6a8bd7d6254d01ebaf165c Mon Sep 17 00:00:00 2001 From: Nick Craver Date: Wed, 13 Apr 2022 08:23:05 -0400 Subject: [PATCH 2/3] Add release notes! --- docs/ReleaseNotes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/ReleaseNotes.md b/docs/ReleaseNotes.md index 4c2c40658..dc572d616 100644 --- a/docs/ReleaseNotes.md +++ b/docs/ReleaseNotes.md @@ -14,6 +14,7 @@ - Adds: Support for `ZDIFF`, `ZDIFFSTORE`, `ZINTER`, `ZINTERCARD`, and `ZUNION` with `.SortedSetCombine()`/`.SortedSetCombineAsync()`, `.SortedSetCombineWithScores()`/`.SortedSetCombineWithScoresAsync()`, and `.SortedSetIntersectionLength()`/`.SortedSetIntersectionLengthAsync()` ([#2075 by Avital-Fine](https://github.com/StackExchange/StackExchange.Redis/pull/2075)) - Adds: Support for `SINTERCARD` with `.SetIntersectionLength()`/`.SetIntersectionLengthAsync()` ([#2078 by Avital-Fine](https://github.com/StackExchange/StackExchange.Redis/pull/2078)) - Adds: Support for `LPOS` with `.ListPosition()`/`.ListPositionAsync()` and `.ListPositions()`/`.ListPositionsAsync()` ([#2080 by slorello89](https://github.com/StackExchange/StackExchange.Redis/pull/2080)) +- Fix: For streams, properly hash `XACK`, `XCLAIM`, and `XPENDING` in cluster scenarios to eliminate `MOVED` retries ([#2085 by nielsderdaele](https://github.com/StackExchange/StackExchange.Redis/pull/2085)) ## 2.5.61 From 4e63b783d61b2ce1ea05a240c62cd014bf0de693 Mon Sep 17 00:00:00 2001 From: Nick Craver Date: Wed, 13 Apr 2022 08:23:56 -0400 Subject: [PATCH 3/3] Tidy --- src/StackExchange.Redis/RedisDatabase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/StackExchange.Redis/RedisDatabase.cs b/src/StackExchange.Redis/RedisDatabase.cs index 9c9a08210..89e89a370 100644 --- a/src/StackExchange.Redis/RedisDatabase.cs +++ b/src/StackExchange.Redis/RedisDatabase.cs @@ -3422,7 +3422,7 @@ private Message GetSortedSetRemoveRangeByScoreMessage(RedisKey key, double start private Message GetStreamAcknowledgeMessage(RedisKey key, RedisValue groupName, RedisValue messageId, CommandFlags flags) { var values = new RedisValue[] - { + { groupName, messageId };