diff --git a/docs/ReleaseNotes.md b/docs/ReleaseNotes.md index 3a50f1ef3..12b4f9ded 100644 --- a/docs/ReleaseNotes.md +++ b/docs/ReleaseNotes.md @@ -13,6 +13,7 @@ Current package versions: - Add `Condition.SortedSet[Not]ContainsStarting` condition for transactions ([#2638 by ArnoKoll](https://github.com/StackExchange/StackExchange.Redis/pull/2638)) - Add support for XPENDING Idle time filter ([#2822 by david-brink-talogy](https://github.com/StackExchange/StackExchange.Redis/pull/2822)) - Improve `double` formatting performance on net8+ ([#2928 by mgravell](https://github.com/StackExchange/StackExchange.Redis/pull/2928)) +- Fix error constructing `StreamAdd` message ([#2941 by mgravell](https://github.com/StackExchange/StackExchange.Redis/pull/2941)) ## 2.8.58 diff --git a/src/StackExchange.Redis/RedisDatabase.cs b/src/StackExchange.Redis/RedisDatabase.cs index bf69f25f3..349864a1b 100644 --- a/src/StackExchange.Redis/RedisDatabase.cs +++ b/src/StackExchange.Redis/RedisDatabase.cs @@ -4598,13 +4598,12 @@ private Message GetStreamAddMessage(RedisKey key, RedisValue entryId, long? maxL throw new ArgumentOutOfRangeException(nameof(maxLength), "maxLength must be greater than 0."); } - var includeMaxLen = maxLength.HasValue ? 2 : 0; - var includeApproxLen = maxLength.HasValue && useApproximateMaxLength ? 1 : 0; - var totalLength = (streamPairs.Length * 2) // Room for the name/value pairs - + 1 // The stream entry ID - + includeMaxLen // 2 or 0 (MAXLEN keyword & the count) - + includeApproxLen; // 1 or 0 + + 1 // The stream entry ID + + (maxLength.HasValue ? 2 : 0) // MAXLEN N + + (maxLength.HasValue && useApproximateMaxLength ? 1 : 0) // ~ + + (mode == StreamTrimMode.KeepReferences ? 0 : 1) // relevant trim-mode keyword + + (limit.HasValue ? 2 : 0); // LIMIT N var values = new RedisValue[totalLength]; diff --git a/tests/RedisConfigs/.docker/Redis/Dockerfile b/tests/RedisConfigs/.docker/Redis/Dockerfile index 4de03f221..424abd1cd 100644 --- a/tests/RedisConfigs/.docker/Redis/Dockerfile +++ b/tests/RedisConfigs/.docker/Redis/Dockerfile @@ -1,4 +1,4 @@ -FROM redis:7.4.2 +FROM redis:8.2.0 COPY --from=configs ./Basic /data/Basic/ COPY --from=configs ./Failover /data/Failover/ diff --git a/tests/StackExchange.Redis.Tests/KeyTests.cs b/tests/StackExchange.Redis.Tests/KeyTests.cs index 31cd87d79..e956af4ff 100644 --- a/tests/StackExchange.Redis.Tests/KeyTests.cs +++ b/tests/StackExchange.Redis.Tests/KeyTests.cs @@ -182,8 +182,8 @@ public async Task KeyEncoding() db.KeyDelete(key, CommandFlags.FireAndForget); db.StringSet(key, "new value", flags: CommandFlags.FireAndForget); - Assert.Equal("embstr", db.KeyEncoding(key)); - Assert.Equal("embstr", await db.KeyEncodingAsync(key)); + Assert.True(db.KeyEncoding(key) is "embstr" or "raw"); // server-version dependent + Assert.True(await db.KeyEncodingAsync(key) is "embstr" or "raw"); db.KeyDelete(key, CommandFlags.FireAndForget); db.ListLeftPush(key, "new value", flags: CommandFlags.FireAndForget); diff --git a/tests/StackExchange.Redis.Tests/StreamTests.cs b/tests/StackExchange.Redis.Tests/StreamTests.cs index 196913f40..58d2bb1fb 100644 --- a/tests/StackExchange.Redis.Tests/StreamTests.cs +++ b/tests/StackExchange.Redis.Tests/StreamTests.cs @@ -2155,6 +2155,28 @@ public async Task AddWithApproxCount(StreamTrimMode mode) db.StreamAdd(key, "field", "value", maxLength: 10, useApproximateMaxLength: true, trimMode: mode, flags: CommandFlags.None); } + [Theory] + [InlineData(StreamTrimMode.KeepReferences, 1)] + [InlineData(StreamTrimMode.DeleteReferences, 1)] + [InlineData(StreamTrimMode.Acknowledged, 1)] + [InlineData(StreamTrimMode.KeepReferences, 2)] + [InlineData(StreamTrimMode.DeleteReferences, 2)] + [InlineData(StreamTrimMode.Acknowledged, 2)] + public async Task AddWithMultipleApproxCount(StreamTrimMode mode, int count) + { + await using var conn = Create(require: ForMode(mode)); + + var db = conn.GetDatabase(); + var key = Me() + ":" + mode; + + var pairs = new NameValueEntry[count]; + for (var i = 0; i < count; i++) + { + pairs[i] = new NameValueEntry($"field{i}", $"value{i}"); + } + db.StreamAdd(key, maxLength: 10, useApproximateMaxLength: true, trimMode: mode, flags: CommandFlags.None, streamPairs: pairs); + } + [Fact] public async Task StreamReadGroupWithNoAckShowsNoPendingMessages() {