From 3b3e0369e36db793097b60a49013228e5ba18a9a Mon Sep 17 00:00:00 2001 From: Marc Gravell Date: Mon, 24 Aug 2026 09:50:12 +0100 Subject: [PATCH 1/2] TS.INFO is not obsolete --- src/NRedisStack/ResponseParser.cs | 1 - .../DataTypes/TimeSeriesInformation.cs | 3 +- .../TimeSeries/TimeSeriesCommands.cs | 1 - .../TimeSeries/TimeSeriesCommandsAsync.cs | 1 - tests/NRedisStack.Tests/PipelineTests.cs | 1 - .../TestAPI/InfoNotObsoleteGuard.cs | 32 +++++++++++++++++++ .../TimeSeries/TestAPI/TestAdd.cs | 7 ---- .../TimeSeries/TestAPI/TestAddAsync.cs | 7 ---- .../TimeSeries/TestAPI/TestCreate.cs | 4 --- .../TimeSeries/TestAPI/TestCreateAsync.cs | 3 -- .../TimeSeries/TestAPI/TestDecrBy.cs | 2 -- .../TimeSeries/TestAPI/TestDecrByAsync.cs | 2 -- .../TimeSeries/TestAPI/TestIncrBy.cs | 2 -- .../TimeSeries/TestAPI/TestIncrByAsync.cs | 2 -- .../TimeSeries/TestAPI/TestMADD.cs | 1 - .../TimeSeries/TestAPI/TestMAddAsync.cs | 1 - .../TimeSeries/TestAPI/TestRead.cs | 1 - .../TimeSeries/TestAPI/TestRules.cs | 1 - .../TimeSeries/TestAPI/TestRulesAsync.cs | 1 - 19 files changed, 34 insertions(+), 39 deletions(-) create mode 100644 tests/NRedisStack.Tests/TimeSeries/TestAPI/InfoNotObsoleteGuard.cs diff --git a/src/NRedisStack/ResponseParser.cs b/src/NRedisStack/ResponseParser.cs index b99c8b37..b212a9cf 100644 --- a/src/NRedisStack/ResponseParser.cs +++ b/src/NRedisStack/ResponseParser.cs @@ -607,7 +607,6 @@ public static TdigestInformation mergedWeight, unmergedWeight, observations, totalCompressions, memoryUsage); } - [Obsolete] public static TimeSeriesInformation ToTimeSeriesInfo(this RedisResult result) { long totalSamples = -1, memoryUsage = -1, retentionTime = -1, chunkSize = -1, chunkCount = -1; diff --git a/src/NRedisStack/TimeSeries/DataTypes/TimeSeriesInformation.cs b/src/NRedisStack/TimeSeries/DataTypes/TimeSeriesInformation.cs index 7f6a8a38..c8d2e655 100644 --- a/src/NRedisStack/TimeSeries/DataTypes/TimeSeriesInformation.cs +++ b/src/NRedisStack/TimeSeries/DataTypes/TimeSeriesInformation.cs @@ -80,7 +80,6 @@ public class TimeSeriesInformation /// public IReadOnlyList? Chunks { get; private set; } - [Obsolete] internal TimeSeriesInformation(long totalSamples, long memoryUsage, TimeStamp? firstTimeStamp, TimeStamp? lastTimeStamp, long retentionTime, long chunkCount, long chunkSize, IReadOnlyList? labels, @@ -97,7 +96,9 @@ internal TimeSeriesInformation(long totalSamples, long memoryUsage, SourceKey = sourceKey; Rules = rules; // backwards compatible with RedisTimeSeries < v1.4 +#pragma warning disable CS0618 // MaxSamplesPerChunk is deprecated, but we still need to populate it MaxSamplesPerChunk = chunkSize / 16; +#pragma warning restore CS0618 ChunkSize = chunkSize; // configure what to do on duplicate sample > v1.4 DuplicatePolicy = policy; diff --git a/src/NRedisStack/TimeSeries/TimeSeriesCommands.cs b/src/NRedisStack/TimeSeries/TimeSeriesCommands.cs index d0b0127c..27429f53 100644 --- a/src/NRedisStack/TimeSeries/TimeSeriesCommands.cs +++ b/src/NRedisStack/TimeSeries/TimeSeriesCommands.cs @@ -460,7 +460,6 @@ public IReadOnlyList RevRange(string key, #region General /// - [Obsolete] public TimeSeriesInformation Info(string key, bool debug = false) { return _db.Execute(TimeSeriesCommandsBuilder.Info(key, debug)).ToTimeSeriesInfo(); diff --git a/src/NRedisStack/TimeSeries/TimeSeriesCommandsAsync.cs b/src/NRedisStack/TimeSeries/TimeSeriesCommandsAsync.cs index 505788ed..727881ce 100644 --- a/src/NRedisStack/TimeSeries/TimeSeriesCommandsAsync.cs +++ b/src/NRedisStack/TimeSeries/TimeSeriesCommandsAsync.cs @@ -466,7 +466,6 @@ public async Task> RevRangeAsync(string key, #region General /// - [Obsolete] public async Task InfoAsync(string key, bool debug = false) { return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.Info(key, debug))).ToTimeSeriesInfo(); diff --git a/tests/NRedisStack.Tests/PipelineTests.cs b/tests/NRedisStack.Tests/PipelineTests.cs index b0cfa0f6..50025f4b 100644 --- a/tests/NRedisStack.Tests/PipelineTests.cs +++ b/tests/NRedisStack.Tests/PipelineTests.cs @@ -160,7 +160,6 @@ public void TestJsonPipeline(string endpointId) [Theory] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - [Obsolete] public async Task Issue401_TestPipelineAsInitialCommand(string endpointId) { IDatabase db = GetCleanDatabase(endpointId); diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/InfoNotObsoleteGuard.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/InfoNotObsoleteGuard.cs new file mode 100644 index 00000000..3c6a3442 --- /dev/null +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/InfoNotObsoleteGuard.cs @@ -0,0 +1,32 @@ +using NRedisStack.RedisStackCommands; +using StackExchange.Redis; + +namespace NRedisStack.Tests.TimeSeries.TestAPI; + +// COMPILE-TIME test - deliberately NOT an xUnit [Fact]/[Theory], and never executed (no server, no +// assertions). The check is performed entirely by the compiler, so this file must never be given a +// file-level obsolete-suppression pragma. +// +// Why it exists: TS.INFO is not deprecated, but Info/InfoAsync on the concrete command types carried a +// bare [Obsolete] from #184 (v0.10.0) until #548. Nothing about the command was deprecated; the attribute +// was added to silence CS0618 raised inside TimeSeriesInformation's constructor, which still has to +// populate the genuinely-deprecated MaxSamplesPerChunk, and it then cascaded outwards through +// ToTimeSeriesInfo to the public API. The interfaces were never marked, so the warning only hit callers +// going through db.TS() - which is to say, essentially everyone. +// +// This project compiles CS0612/CS0618 as errors (see NRedisStack.Tests.csproj), so if any of these ever +// becomes obsolete again, this file fails to BUILD. That build failure IS the test. +internal static class InfoNotObsoleteGuard +{ + public static void SyncInterface(ITimeSeriesCommands ts) => _ = ts.Info("k").ChunkSize; + + public static Task AsyncInterface(ITimeSeriesCommandsAsync ts) => ts.InfoAsync("k"); + + public static void Concrete(IDatabase db) + { + // db.TS() returns the concrete TimeSeriesCommands - the dominant real-world call pattern, and the + // one that actually produced the warning reported in #548. + _ = db.TS().Info("k").ChunkSize; + _ = db.TS().InfoAsync("k"); + } +} diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAdd.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAdd.cs index fab1f57b..2eea3f18 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAdd.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAdd.cs @@ -12,7 +12,6 @@ public class TestAdd(EndpointsFixture endpointsFixture) : AbstractNRedisStackTes [Fact] - [Obsolete] public void TestAddNotExistingTimeSeries() { IDatabase db = GetCleanDatabase(); @@ -26,7 +25,6 @@ public void TestAddNotExistingTimeSeries() } [Fact] - [Obsolete] public void TestAddExistingTimeSeries() { IDatabase db = GetCleanDatabase(); @@ -41,7 +39,6 @@ public void TestAddExistingTimeSeries() } [Fact] - [Obsolete] public void TestAddStar() { IDatabase db = GetCleanDatabase(); @@ -54,7 +51,6 @@ public void TestAddStar() } [Fact] - [Obsolete] public void TestAddWithRetentionTime() { IDatabase db = GetCleanDatabase(); @@ -69,7 +65,6 @@ public void TestAddWithRetentionTime() } [Fact] - [Obsolete] public void TestAddWithLabels() { IDatabase db = GetCleanDatabase(); @@ -85,7 +80,6 @@ public void TestAddWithLabels() } [Fact] - [Obsolete] public void TestAddWithUncompressed() { IDatabase db = GetCleanDatabase(); @@ -99,7 +93,6 @@ public void TestAddWithUncompressed() } [Fact] - [Obsolete] public void TestAddWithChunkSize() { IDatabase db = GetCleanDatabase(); diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAddAsync.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAddAsync.cs index 23714ae8..a19af876 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAddAsync.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAddAsync.cs @@ -10,7 +10,6 @@ namespace NRedisStack.Tests.TimeSeries.TestAPI; public class TestAddAsync(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture) { [Fact] - [Obsolete] public async Task TestAddNotExistingTimeSeries() { var key = CreateKeyName(); @@ -25,7 +24,6 @@ public async Task TestAddNotExistingTimeSeries() } [Fact] - [Obsolete] public async Task TestAddExistingTimeSeries() { var key = CreateKeyName(); @@ -41,7 +39,6 @@ public async Task TestAddExistingTimeSeries() } [Fact] - [Obsolete] public async Task TestAddStar() { var key = CreateKeyName(); @@ -54,7 +51,6 @@ public async Task TestAddStar() } [Fact] - [Obsolete] public async Task TestAddWithRetentionTime() { var key = CreateKeyName(); @@ -71,7 +67,6 @@ public async Task TestAddWithRetentionTime() } [Fact] - [Obsolete] public async Task TestAddWithLabels() { var key = CreateKeyName(); @@ -89,7 +84,6 @@ public async Task TestAddWithLabels() } [Fact] - [Obsolete] public async Task TestAddWithChunkSize() { var key = CreateKeyName(); @@ -104,7 +98,6 @@ public async Task TestAddWithChunkSize() } [Fact] - [Obsolete] public async Task TestAddWithUncompressed() { var key = CreateKeyName(); diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestCreate.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestCreate.cs index 187216a5..97dde528 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestCreate.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestCreate.cs @@ -13,7 +13,6 @@ public class TestCreate(EndpointsFixture endpointsFixture) : AbstractNRedisStack [Fact] - [Obsolete] public void TestCreateOK() { IDatabase db = GetCleanDatabase(); @@ -23,7 +22,6 @@ public void TestCreateOK() } [Fact] - [Obsolete] public void TestCreateRetentionTime() { long retentionTime = 5000; @@ -35,7 +33,6 @@ public void TestCreateRetentionTime() } [Fact] - [Obsolete] public void TestCreateLabels() { TimeSeriesLabel label = new("key", "value"); @@ -48,7 +45,6 @@ public void TestCreateLabels() } [Fact] - [Obsolete] public void TestCreateEmptyLabels() { var labels = new List(); diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestCreateAsync.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestCreateAsync.cs index bba4864a..6398b8f8 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestCreateAsync.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestCreateAsync.cs @@ -18,7 +18,6 @@ public async Task TestCreateOK() } [Fact] - [Obsolete] public async Task TestCreateRetentionTime() { var key = CreateKeyName(); @@ -32,7 +31,6 @@ public async Task TestCreateRetentionTime() } [Fact] - [Obsolete] public async Task TestCreateLabels() { var key = CreateKeyName(); @@ -47,7 +45,6 @@ public async Task TestCreateLabels() } [Fact] - [Obsolete] public async Task TestCreateEmptyLabels() { var key = CreateKeyName(); diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestDecrBy.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestDecrBy.cs index 62bc4a1e..9c5c2018 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestDecrBy.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestDecrBy.cs @@ -43,7 +43,6 @@ public void TestDecrByTimeStamp() } [Fact] - [Obsolete] public void TestDefaultDecrByWithRetentionTime() { double value = 5.5; @@ -57,7 +56,6 @@ public void TestDefaultDecrByWithRetentionTime() } [Fact] - [Obsolete] public void TestDefaultDecrByWithLabels() { double value = 5.5; diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestDecrByAsync.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestDecrByAsync.cs index a272c3e9..96b61ecf 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestDecrByAsync.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestDecrByAsync.cs @@ -46,7 +46,6 @@ public async Task TestDecrByTimeStamp() } [Fact] - [Obsolete] public async Task TestDefaultDecrByWithRetentionTime() { var key = CreateKeyName(); @@ -64,7 +63,6 @@ public async Task TestDefaultDecrByWithRetentionTime() } [Fact] - [Obsolete] public async Task TestDefaultDecrByWithLabels() { var key = CreateKeyName(); diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestIncrBy.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestIncrBy.cs index ae557ff2..ed887a14 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestIncrBy.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestIncrBy.cs @@ -42,7 +42,6 @@ public void TestIncrByTimeStamp() } [Fact] - [Obsolete] public void TestDefaultIncrByWithRetentionTime() { double value = 5.5; @@ -56,7 +55,6 @@ public void TestDefaultIncrByWithRetentionTime() } [Fact] - [Obsolete] public void TestDefaultIncrByWithLabels() { double value = 5.5; diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestIncrByAsync.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestIncrByAsync.cs index eee0bb23..93049433 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestIncrByAsync.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestIncrByAsync.cs @@ -46,7 +46,6 @@ public async Task TestIncrByTimeStamp() } [Fact] - [Obsolete] public async Task TestDefaultIncrByWithRetentionTime() { var key = CreateKeyName(); @@ -64,7 +63,6 @@ public async Task TestDefaultIncrByWithRetentionTime() } [Fact] - [Obsolete] public async Task TestDefaultIncrByWithLabels() { var key = CreateKeyName(); diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMADD.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMADD.cs index 6f142271..febbd929 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMADD.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMADD.cs @@ -14,7 +14,6 @@ public class TestMADD(EndpointsFixture endpointsFixture) : AbstractNRedisStackTe [SkipIfRedisTheory(Is.Enterprise)] [MemberData(nameof(EndpointsFixture.Env.AllEnvironments), MemberType = typeof(EndpointsFixture.Env))] - [Obsolete] public void TestStarMADD(string endpointId) { SkipClusterPre8(endpointId); diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMAddAsync.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMAddAsync.cs index 8d65b76e..4a2f72d3 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMAddAsync.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMAddAsync.cs @@ -11,7 +11,6 @@ public class TestMAddAsync(EndpointsFixture endpointsFixture) : AbstractNRedisSt { [SkipIfRedisTheory(Is.Enterprise)] [MemberData(nameof(EndpointsFixture.Env.AllEnvironments), MemberType = typeof(EndpointsFixture.Env))] - [Obsolete] public async Task TestStarMADD(string endpointId) { SkipClusterPre8(endpointId); diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRead.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRead.cs index c26e9203..49bdca47 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRead.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRead.cs @@ -1,4 +1,3 @@ -#pragma warning disable CS0618, CS0612 // allow testing obsolete methods using NRedisStack.DataTypes; using NRedisStack.RedisStackCommands; using Xunit; diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRules.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRules.cs index cbe87cfd..2ed1e52f 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRules.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRules.cs @@ -31,7 +31,6 @@ public class TestRules(EndpointsFixture endpointsFixture) : AbstractNRedisStackT [SkipIfRedisTheory(Is.Enterprise)] [MemberData(nameof(EndpointsFixture.Env.AllEnvironments), MemberType = typeof(EndpointsFixture.Env))] - [Obsolete] public void TestRulesAdditionDeletion(string endpointId) { SkipClusterPre8(endpointId); diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRulesAsync.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRulesAsync.cs index c8a808aa..a1311fdb 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRulesAsync.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRulesAsync.cs @@ -11,7 +11,6 @@ public class TestRulesAsync(EndpointsFixture endpointsFixture) : AbstractNRedisS { [SkipIfRedisTheory(Is.Enterprise)] [MemberData(nameof(EndpointsFixture.Env.AllEnvironments), MemberType = typeof(EndpointsFixture.Env))] - [Obsolete] public async Task TestRulesAdditionDeletion(string endpointId) { SkipClusterPre8(endpointId); From 0be450ea05b01307b09afb7ed4631ce4b7dcc4a2 Mon Sep 17 00:00:00 2001 From: Marc Gravell Date: Mon, 24 Aug 2026 09:52:09 +0100 Subject: [PATCH 2/2] meh, we don't need the guard --- .../TestAPI/InfoNotObsoleteGuard.cs | 32 ------------------- 1 file changed, 32 deletions(-) delete mode 100644 tests/NRedisStack.Tests/TimeSeries/TestAPI/InfoNotObsoleteGuard.cs diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/InfoNotObsoleteGuard.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/InfoNotObsoleteGuard.cs deleted file mode 100644 index 3c6a3442..00000000 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/InfoNotObsoleteGuard.cs +++ /dev/null @@ -1,32 +0,0 @@ -using NRedisStack.RedisStackCommands; -using StackExchange.Redis; - -namespace NRedisStack.Tests.TimeSeries.TestAPI; - -// COMPILE-TIME test - deliberately NOT an xUnit [Fact]/[Theory], and never executed (no server, no -// assertions). The check is performed entirely by the compiler, so this file must never be given a -// file-level obsolete-suppression pragma. -// -// Why it exists: TS.INFO is not deprecated, but Info/InfoAsync on the concrete command types carried a -// bare [Obsolete] from #184 (v0.10.0) until #548. Nothing about the command was deprecated; the attribute -// was added to silence CS0618 raised inside TimeSeriesInformation's constructor, which still has to -// populate the genuinely-deprecated MaxSamplesPerChunk, and it then cascaded outwards through -// ToTimeSeriesInfo to the public API. The interfaces were never marked, so the warning only hit callers -// going through db.TS() - which is to say, essentially everyone. -// -// This project compiles CS0612/CS0618 as errors (see NRedisStack.Tests.csproj), so if any of these ever -// becomes obsolete again, this file fails to BUILD. That build failure IS the test. -internal static class InfoNotObsoleteGuard -{ - public static void SyncInterface(ITimeSeriesCommands ts) => _ = ts.Info("k").ChunkSize; - - public static Task AsyncInterface(ITimeSeriesCommandsAsync ts) => ts.InfoAsync("k"); - - public static void Concrete(IDatabase db) - { - // db.TS() returns the concrete TimeSeriesCommands - the dominant real-world call pattern, and the - // one that actually produced the warning reported in #548. - _ = db.TS().Info("k").ChunkSize; - _ = db.TS().InfoAsync("k"); - } -}