diff --git a/NRedisTimeSeries.Example/AddExample.cs b/NRedisTimeSeries.Example/AddExample.cs index 4831494..8d54417 100644 --- a/NRedisTimeSeries.Example/AddExample.cs +++ b/NRedisTimeSeries.Example/AddExample.cs @@ -19,8 +19,7 @@ public static void DefaultAdd() { ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); IDatabase db = redis.GetDatabase(); - TimeStamp timestamp = "*"; - db.TimeSeriesAdd("my_ts", timestamp, 0.0); + db.TimeSeriesAdd("my_ts", 0.0); redis.Close(); } @@ -33,7 +32,7 @@ public static void LongAdd() { ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); IDatabase db = redis.GetDatabase(); - TimeStamp timestamp = 1; + TsTimeStamp timestamp = 1; db.TimeSeriesAdd("my_ts", timestamp, 0.0); redis.Close(); } @@ -47,7 +46,7 @@ public static void DateTimeAdd() { ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); IDatabase db = redis.GetDatabase(); - TimeStamp timestamp = DateTime.UtcNow; + TsTimeStamp timestamp = DateTime.UtcNow; db.TimeSeriesAdd("my_ts", timestamp, 0.0); redis.Close(); } @@ -60,10 +59,9 @@ public static void ParameterizedAdd() { ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); IDatabase db = redis.GetDatabase(); - TimeStamp timestamp = "*"; var label = new TimeSeriesLabel("key", "value"); var labels = new List { label }; - db.TimeSeriesAdd("my_ts", timestamp, 0.0, retentionTime:5000, labels:labels, uncompressed:true); + db.TimeSeriesAdd("my_ts", 0.0, retentionTime: 5000, labels: labels, uncompressed: true); redis.Close(); } } diff --git a/NRedisTimeSeries.Example/AddExampleAsync.cs b/NRedisTimeSeries.Example/AddExampleAsync.cs index 457e049..d72958e 100644 --- a/NRedisTimeSeries.Example/AddExampleAsync.cs +++ b/NRedisTimeSeries.Example/AddExampleAsync.cs @@ -1,8 +1,8 @@ -using System; +using NRedisTimeSeries.DataTypes; +using StackExchange.Redis; +using System; using System.Collections.Generic; using System.Threading.Tasks; -using NRedisTimeSeries.DataTypes; -using StackExchange.Redis; namespace NRedisTimeSeries.Example { @@ -20,8 +20,7 @@ public static async Task DefaultAddAsync() { ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); IDatabase db = redis.GetDatabase(); - TimeStamp timestamp = "*"; - await db.TimeSeriesAddAsync("my_ts", timestamp, 0.0); + await db.TimeSeriesAddAsync("my_ts", 0.0); redis.Close(); } @@ -34,7 +33,7 @@ public static async Task LongAddAsync() { ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); IDatabase db = redis.GetDatabase(); - TimeStamp timestamp = 1; + TsTimeStamp timestamp = 1; await db.TimeSeriesAddAsync("my_ts", timestamp, 0.0); redis.Close(); } @@ -48,7 +47,7 @@ public static async Task DateTimeAddAsync() { ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); IDatabase db = redis.GetDatabase(); - TimeStamp timestamp = DateTime.UtcNow; + TsTimeStamp timestamp = DateTime.UtcNow; await db.TimeSeriesAddAsync("my_ts", timestamp, 0.0); redis.Close(); } @@ -61,10 +60,9 @@ public static async Task ParameterizedAddAsync() { ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); IDatabase db = redis.GetDatabase(); - TimeStamp timestamp = "*"; var label = new TimeSeriesLabel("key", "value"); var labels = new List { label }; - await db.TimeSeriesAddAsync("my_ts", timestamp, 0.0, retentionTime:5000, labels:labels, uncompressed:true); + await db.TimeSeriesAddAsync("my_ts", 0.0, retentionTime: 5000, labels: labels, uncompressed: true); redis.Close(); } } diff --git a/NRedisTimeSeries.Example/DecrByExample.cs b/NRedisTimeSeries.Example/DecrByExample.cs index 5266860..271ecf9 100644 --- a/NRedisTimeSeries.Example/DecrByExample.cs +++ b/NRedisTimeSeries.Example/DecrByExample.cs @@ -1,7 +1,7 @@ -using System; -using System.Collections.Generic; -using NRedisTimeSeries.DataTypes; +using NRedisTimeSeries.DataTypes; using StackExchange.Redis; +using System; +using System.Collections.Generic; namespace NRedisTimeSeries.Example { @@ -11,7 +11,7 @@ namespace NRedisTimeSeries.Example internal class DecrByExample { /// - /// Example for decreasing the value of the last sample by 5. + /// Example for decreasing the value of the last sample by 5 using the system timestamp. /// public static void DefaultIncrByExample() { @@ -21,17 +21,6 @@ public static void DefaultIncrByExample() redis.Close(); } - /// - /// Example for setting the last sample timestamp to system time and its value to -5, with DECRBY. - /// - public static void SystemTimeIncrByExample() - { - ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); - IDatabase db = redis.GetDatabase(); - db.TimeSeriesDecrBy("my_ts", 5, timestamp: "*"); - redis.Close(); - } - /// /// Example for setting the last sample timestamp to DateTime.UtcNow and its value to -5, with DECRBY. /// @@ -50,7 +39,7 @@ public static void LongIncrByExample() { ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); IDatabase db = redis.GetDatabase(); - db.TimeSeriesDecrBy("my_ts", 5, timestamp: long.MaxValue); + db.TimeSeriesDecrBy("my_ts", 5, timestamp: 1000); redis.Close(); } @@ -64,7 +53,7 @@ public static void ParameterizedIncrByExample() IDatabase db = redis.GetDatabase(); var label = new TimeSeriesLabel("key", "value"); var labels = new List { label }; - db.TimeSeriesDecrBy("my_ts", 5, timestamp: "*", retentionTime: 5000, uncompressed: true, labels: labels); + db.TimeSeriesDecrBy("my_ts", 5, retentionTime: 5000, uncompressed: true, labels: labels); redis.Close(); } } diff --git a/NRedisTimeSeries.Example/DecrByExampleAsync.cs b/NRedisTimeSeries.Example/DecrByExampleAsync.cs index 1286fee..6cf6bc3 100644 --- a/NRedisTimeSeries.Example/DecrByExampleAsync.cs +++ b/NRedisTimeSeries.Example/DecrByExampleAsync.cs @@ -22,17 +22,6 @@ public static async Task DefaultDecrByAsyncExample() redis.Close(); } - /// - /// Example for setting the last sample timestamp to system time and its value to -5, with DECRBY. - /// - public static async Task SystemTimeDecrByAsyncExample() - { - ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); - IDatabase db = redis.GetDatabase(); - await db.TimeSeriesDecrByAsync("my_ts", 5, timestamp: "*"); - redis.Close(); - } - /// /// Example for setting the last sample timestamp to DateTime.UtcNow and its value to -5, with DECRBY. /// @@ -51,7 +40,7 @@ public static async Task LongDecrByAsyncExample() { ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); IDatabase db = redis.GetDatabase(); - await db.TimeSeriesDecrByAsync("my_ts", 5, timestamp: long.MaxValue); + await db.TimeSeriesDecrByAsync("my_ts", 5, timestamp: 1000); redis.Close(); } @@ -65,7 +54,7 @@ public static async Task ParameterizedDecrByAsyncExample() IDatabase db = redis.GetDatabase(); var label = new TimeSeriesLabel("key", "value"); var labels = new List { label }; - await db.TimeSeriesDecrByAsync("my_ts", 5, timestamp: "*", retentionTime: 5000, uncompressed: true, labels: labels); + await db.TimeSeriesDecrByAsync("my_ts", 5, retentionTime: 5000, uncompressed: true, labels: labels); redis.Close(); } } diff --git a/NRedisTimeSeries.Example/IncrByExample.cs b/NRedisTimeSeries.Example/IncrByExample.cs index 51042f2..c656eb4 100644 --- a/NRedisTimeSeries.Example/IncrByExample.cs +++ b/NRedisTimeSeries.Example/IncrByExample.cs @@ -21,17 +21,6 @@ public static void DefaultIncrByExample() redis.Close(); } - /// - /// Example for setting the last sample timestamp to system time and its value to 5, with INCRBY. - /// - public static void SystemTimeIncrByExample() - { - ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); - IDatabase db = redis.GetDatabase(); - db.TimeSeriesIncrBy("my_ts", 5, timestamp: "*"); - redis.Close(); - } - /// /// Example for setting the last sample timestamp to DateTime.UtcNow and its value to 5, with INCRBY. /// @@ -50,7 +39,7 @@ public static void LongIncrByExample() { ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); IDatabase db = redis.GetDatabase(); - db.TimeSeriesIncrBy("my_ts", 5, timestamp: long.MaxValue); + db.TimeSeriesIncrBy("my_ts", 5, timestamp: 1000); redis.Close(); } @@ -64,7 +53,7 @@ public static void ParameterizedIncrByExample() IDatabase db = redis.GetDatabase(); var label = new TimeSeriesLabel("key", "value"); var labels = new List { label }; - db.TimeSeriesIncrBy("my_ts", 5, timestamp: "*", retentionTime:5000, uncompressed:true, labels: labels); + db.TimeSeriesIncrBy("my_ts", 5, retentionTime: 5000, uncompressed: true, labels: labels); redis.Close(); } } diff --git a/NRedisTimeSeries.Example/IncrByExampleAsync.cs b/NRedisTimeSeries.Example/IncrByExampleAsync.cs index f623031..1e89134 100644 --- a/NRedisTimeSeries.Example/IncrByExampleAsync.cs +++ b/NRedisTimeSeries.Example/IncrByExampleAsync.cs @@ -22,17 +22,6 @@ public static async Task DefaultIncrByAsyncExample() redis.Close(); } - /// - /// Example for setting the last sample timestamp to system time and its value to 5, with INCRBY. - /// - public static async Task SystemTimeIncrByAsyncExample() - { - ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); - IDatabase db = redis.GetDatabase(); - await db.TimeSeriesIncrByAsync("my_ts", 5, timestamp: "*"); - redis.Close(); - } - /// /// Example for setting the last sample timestamp to DateTime.UtcNow and its value to 5, with INCRBY. /// @@ -51,7 +40,7 @@ public static async Task LongIncrByAsyncExample() { ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); IDatabase db = redis.GetDatabase(); - await db.TimeSeriesIncrByAsync("my_ts", 5, timestamp: long.MaxValue); + await db.TimeSeriesIncrByAsync("my_ts", 5, timestamp: 1000); redis.Close(); } @@ -65,7 +54,7 @@ public static async Task ParameterizedIncrByAsyncExample() IDatabase db = redis.GetDatabase(); var label = new TimeSeriesLabel("key", "value"); var labels = new List { label }; - await db.TimeSeriesIncrByAsync("my_ts", 5, timestamp: "*", retentionTime: 5000, uncompressed: true, labels: labels); + await db.TimeSeriesIncrByAsync("my_ts", 5, retentionTime: 5000, uncompressed: true, labels: labels); redis.Close(); } } diff --git a/NRedisTimeSeries.Example/MAddExample.cs b/NRedisTimeSeries.Example/MAddExample.cs index a3b1116..bc6ef33 100644 --- a/NRedisTimeSeries.Example/MAddExample.cs +++ b/NRedisTimeSeries.Example/MAddExample.cs @@ -11,19 +11,38 @@ namespace NRedisTimeSeries.Example internal class MAddExample { /// - /// Example for mutiple sample addtion. One is using RedisTimeSeris default system time in one time series, - /// the second is using DateTime in the second time series and the third is using long in the third time series. + /// Example for mutiple sample addtion. One is using default TsTimeStamp value in one time series, + /// the second is using current system DateTime in the second time series and the third is using a specified TsTimeStamp in the third time series. /// - public static void MAddFlowExample() + public static void MAddWithTimeStampExample() { - string[] keys = { "system_time_ts", "datetime_ts", "long_ts" }; - var sequence = new List<(string, TimeStamp, double)>(keys.Length); - // Add sample to the system_time_ts - sequence.Add((keys[0], "*", 0.0)); - // Add sample to the datetime_ts - sequence.Add((keys[1], DateTime.UtcNow, 0.0)); - // Add sample to the long_ts - sequence.Add((keys[2], 1, 0.0)); + string[] keys = { "ts_first", "ts_second", "ts_third" }; + var sequence = new List<(string, TsTimeStamp, double)>(keys.Length) + { + (keys[0], default(TsTimeStamp), 1.0), + (keys[1], DateTime.UtcNow, 1.0), + (keys[2], new TsTimeStamp(1), 1.0) + }; + ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); + IDatabase db = redis.GetDatabase(); + db.TimeSeriesMAdd(sequence); + redis.Close(); + } + + /// + /// Example for mutiple sample addtion using the Redis system timestamp. Two samples are added to the first timeseries, + /// and two samples are added to the second timeseries. + /// + public static void MAddWithoutTimeStampExample() + { + string[] keys = { "ts_first", "ts_second" }; + var sequence = new List<(string, double)>(keys.Length) + { + (keys[0], 1.0), + (keys[0], 2.0), + (keys[1], 1.0), + (keys[1], 2.0) + }; ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); IDatabase db = redis.GetDatabase(); db.TimeSeriesMAdd(sequence); diff --git a/NRedisTimeSeries.Example/MAddExampleAsync.cs b/NRedisTimeSeries.Example/MAddExampleAsync.cs index 464c233..356c337 100644 --- a/NRedisTimeSeries.Example/MAddExampleAsync.cs +++ b/NRedisTimeSeries.Example/MAddExampleAsync.cs @@ -12,19 +12,38 @@ namespace NRedisTimeSeries.Example internal class MAddAsyncExample { /// - /// Example for mutiple sample addtion. One is using RedisTimeSeris default system time in one time series, - /// the second is using DateTime in the second time series and the third is using long in the third time series. + /// Example for mutiple sample addtion. One is using default TsTimeStamp value in one time series, + /// the second is using current system DateTime in the second time series and the third is using a specified TsTimeStamp in the third time series. /// - public static async Task MAddFlowAsyncExample() + public static async Task MAddWithTimeStampExample() { - string[] keys = { "system_time_ts", "datetime_ts", "long_ts" }; - var sequence = new List<(string, TimeStamp, double)>(keys.Length); - // Add sample to the system_time_ts - sequence.Add((keys[0], "*", 0.0)); - // Add sample to the datetime_ts - sequence.Add((keys[1], DateTime.UtcNow, 0.0)); - // Add sample to the long_ts - sequence.Add((keys[2], 1, 0.0)); + string[] keys = { "ts_first", "ts_second", "ts_third" }; + var sequence = new List<(string, TsTimeStamp, double)>(keys.Length) + { + (keys[0], default(TsTimeStamp), 1.0), + (keys[1], DateTime.UtcNow, 1.0), + (keys[2], new TsTimeStamp(1), 1.0) + }; + ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); + IDatabase db = redis.GetDatabase(); + await db.TimeSeriesMAddAsync(sequence); + redis.Close(); + } + + /// + /// Example for mutiple sample addtion using the Redis system timestamp. Two samples are added to the first timeseries, + /// and two samples are added to the second timeseries. + /// + public static async Task MAddWithoutTimeStampExample() + { + string[] keys = { "ts_first", "ts_second" }; + var sequence = new List<(string, double)>(keys.Length) + { + (keys[0], 1.0), + (keys[0], 2.0), + (keys[1], 1.0), + (keys[1], 2.0) + }; ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); IDatabase db = redis.GetDatabase(); await db.TimeSeriesMAddAsync(sequence); diff --git a/NRedisTimeSeries.Example/MRangeExample.cs b/NRedisTimeSeries.Example/MRangeExample.cs index e415a7f..d3d589d 100644 --- a/NRedisTimeSeries.Example/MRangeExample.cs +++ b/NRedisTimeSeries.Example/MRangeExample.cs @@ -12,7 +12,7 @@ namespace NRedisTimeSeries.Example internal class MRangeExample { /// - /// Example for basic usage of RedisTimeSeries RANGE command with "-" and "+" as range boundreis and a filter. + /// Example for basic usage of RedisTimeSeries RANGE command with TsTimeStamp.MinValue and TsTimeStamp.MaxValue as range boundreis and a filter. /// NRedisTimeSeris MRange is expecting two TimeStamps objects as the range boundries. /// In this case, the strings are implicitly casted into TimeStamp objects. /// The TimeSeriesMRange command returns an IReadOnlyList<(string key, IReadOnlyList labels, IReadOnlyList values)>collection. @@ -22,7 +22,7 @@ public static void BasicMRangeExample() ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); IDatabase db = redis.GetDatabase(); var filter = new List { "MRANGEkey=MRANGEvalue" }; - var results = db.TimeSeriesMRange("-", "+", filter); + var results = db.TimeSeriesMRange(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, filter); // Values extraction example. No lables in this case. foreach (var result in results) { @@ -33,7 +33,7 @@ public static void BasicMRangeExample() } /// - /// Example for basic usage of RedisTimeSeries RANGE command with "-" and "+" as range boundreis, a filter and the COUNT parameter. + /// Example for basic usage of RedisTimeSeries RANGE command with TsTimeStamp.MinValue and TsTimeStamp.MaxValue as range boundreis, a filter and the COUNT parameter. /// NRedisTimeSeris MRange is expecting two TimeStamps objects as the range boundries. /// In this case, the strings are implicitly casted into TimeStamp objects. /// The TimeSeriesMRange command returns an IReadOnlyList<(string key, IReadOnlyList labels, IReadOnlyList values)>collection. @@ -43,7 +43,7 @@ public static void CountMRangeExample() ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); IDatabase db = redis.GetDatabase(); var filter = new List { "MRANGEkey=MRANGEvalue" }; - var results = db.TimeSeriesMRange("-", "+", filter, count:50); + var results = db.TimeSeriesMRange(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, filter, count:50); // Values extraction example. No lables in this case. foreach (var result in results) { @@ -54,7 +54,7 @@ public static void CountMRangeExample() } /// - /// Example for basic usage of RedisTimeSeries RANGE command with "-" and "+" as range boundreis, a filter and MIN aggregation. + /// Example for basic usage of RedisTimeSeries RANGE command with TsTimeStamp.MinValue and TsTimeStamp.MaxValue as range boundreis, a filter and MIN aggregation. /// NRedisTimeSeris MRange is expecting two TimeStamps objects as the range boundries. /// In this case, the strings are implicitly casted into TimeStamp objects. /// The TimeSeriesMRange command returns an IReadOnlyList<(string key, IReadOnlyList labels, IReadOnlyList values)>collection. @@ -64,7 +64,7 @@ public static void MRangeAggregationExample() ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); IDatabase db = redis.GetDatabase(); var filter = new List { "MRANGEkey=MRANGEvalue" }; - var results = db.TimeSeriesMRange("-", "+", filter, aggregation:Aggregation.MIN, timeBucket:50); + var results = db.TimeSeriesMRange(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, filter, aggregation:Aggregation.MIN, timeBucket: new TsTimeBucket(50)); // Values extraction example. No lables in this case. foreach (var result in results) { @@ -75,7 +75,7 @@ public static void MRangeAggregationExample() } /// - /// Example for basic usage of RedisTimeSeries RANGE command with "-" and "+" as range boundreis, a filter and WITHLABELS flag. + /// Example for basic usage of RedisTimeSeries RANGE command with TsTimeStamp.MinValue and TsTimeStamp.MaxValue as range boundreis, a filter and WITHLABELS flag. /// NRedisTimeSeris MRange is expecting two TimeStamps objects as the range boundries. /// In this case, the strings are implicitly casted into TimeStamp objects. /// The TimeSeriesMRange command returns an IReadOnlyList<(string key, IReadOnlyList labels, IReadOnlyList values)>collection. @@ -85,7 +85,7 @@ public static void MRangeWithLabelsExample() ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); IDatabase db = redis.GetDatabase(); var filter = new List { "MRANGEkey=MRANGEvalue" }; - var results = db.TimeSeriesMRange("-", "+", filter,withLabels:true); + var results = db.TimeSeriesMRange(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, filter,withLabels:true); // Values extraction example. foreach (var result in results) { diff --git a/NRedisTimeSeries.Example/MRangeExampleAsync.cs b/NRedisTimeSeries.Example/MRangeExampleAsync.cs index 1ce96f5..44a672a 100644 --- a/NRedisTimeSeries.Example/MRangeExampleAsync.cs +++ b/NRedisTimeSeries.Example/MRangeExampleAsync.cs @@ -12,7 +12,7 @@ namespace NRedisTimeSeries.Example internal class MRangeAsyncExample { /// - /// Example for basic usage of RedisTimeSeries RANGE command with "-" and "+" as range boundreis and a filter. + /// Example for basic usage of RedisTimeSeries RANGE command with TsTimeStamp.MinValue and TsTimeStamp.MaxValue as range boundreis and a filter. /// NRedisTimeSeris MRange is expecting two TimeStamps objects as the range boundries. /// In this case, the strings are implicitly casted into TimeStamp objects. /// The TimeSeriesMRange command returns an IReadOnlyList<(string key, IReadOnlyList labels, IReadOnlyList values)>collection. @@ -22,7 +22,7 @@ public static async Task BasicMRangeAsyncExample() ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); IDatabase db = redis.GetDatabase(); var filter = new List { "MRANGEkey=MRANGEvalue" }; - var results = await db.TimeSeriesMRangeAsync("-", "+", filter); + var results = await db.TimeSeriesMRangeAsync(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, filter); // Values extraction example. No lables in this case. foreach (var result in results) { @@ -33,7 +33,7 @@ public static async Task BasicMRangeAsyncExample() } /// - /// Example for basic usage of RedisTimeSeries RANGE command with "-" and "+" as range boundreis, a filter and the COUNT parameter. + /// Example for basic usage of RedisTimeSeries RANGE command with TsTimeStamp.MinValue and TsTimeStamp.MaxValue as range boundreis, a filter and the COUNT parameter. /// NRedisTimeSeris MRange is expecting two TimeStamps objects as the range boundries. /// In this case, the strings are implicitly casted into TimeStamp objects. /// The TimeSeriesMRange command returns an IReadOnlyList<(string key, IReadOnlyList labels, IReadOnlyList values)>collection. @@ -43,7 +43,7 @@ public static async Task CountMRangeAsyncExample() ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); IDatabase db = redis.GetDatabase(); var filter = new List { "MRANGEkey=MRANGEvalue" }; - var results = await db.TimeSeriesMRangeAsync("-", "+", filter, count: 50); + var results = await db.TimeSeriesMRangeAsync(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, filter, count: 50); // Values extraction example. No lables in this case. foreach (var result in results) { @@ -54,7 +54,7 @@ public static async Task CountMRangeAsyncExample() } /// - /// Example for basic usage of RedisTimeSeries RANGE command with "-" and "+" as range boundreis, a filter and MIN aggregation. + /// Example for basic usage of RedisTimeSeries RANGE command with TsTimeStamp.MinValue and TsTimeStamp.MaxValue as range boundreis, a filter and MIN aggregation. /// NRedisTimeSeris MRange is expecting two TimeStamps objects as the range boundries. /// In this case, the strings are implicitly casted into TimeStamp objects. /// The TimeSeriesMRange command returns an IReadOnlyList<(string key, IReadOnlyList labels, IReadOnlyList values)>collection. @@ -64,7 +64,7 @@ public static async Task MRangeAggregationAsyncExample() ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); IDatabase db = redis.GetDatabase(); var filter = new List { "MRANGEkey=MRANGEvalue" }; - var results = await db.TimeSeriesMRangeAsync("-", "+", filter, aggregation: Aggregation.MIN, timeBucket: 50); + var results = await db.TimeSeriesMRangeAsync(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, filter, aggregation: Aggregation.MIN, timeBucket: new TsTimeBucket(50)); // Values extraction example. No lables in this case. foreach (var result in results) { @@ -75,7 +75,7 @@ public static async Task MRangeAggregationAsyncExample() } /// - /// Example for basic usage of RedisTimeSeries RANGE command with "-" and "+" as range boundreis, a filter and WITHLABELS flag. + /// Example for basic usage of RedisTimeSeries RANGE command with TsTimeStamp.MinValue and TsTimeStamp.MaxValue as range boundreis, a filter and WITHLABELS flag. /// NRedisTimeSeris MRange is expecting two TimeStamps objects as the range boundries. /// In this case, the strings are implicitly casted into TimeStamp objects. /// The TimeSeriesMRange command returns an IReadOnlyList<(string key, IReadOnlyList labels, IReadOnlyList values)>collection. @@ -85,7 +85,7 @@ public static async Task MRangeWithLabelsAsyncExample() ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); IDatabase db = redis.GetDatabase(); var filter = new List { "MRANGEkey=MRANGEvalue" }; - var results = await db.TimeSeriesMRangeAsync("-", "+", filter, withLabels: true); + var results = await db.TimeSeriesMRangeAsync(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, filter, withLabels: true); // Values extraction example. foreach (var result in results) { diff --git a/NRedisTimeSeries.Example/RangeExample.cs b/NRedisTimeSeries.Example/RangeExample.cs index 380c21a..cdcd842 100644 --- a/NRedisTimeSeries.Example/RangeExample.cs +++ b/NRedisTimeSeries.Example/RangeExample.cs @@ -12,7 +12,7 @@ namespace NRedisTimeSeries.Example public class RangeExample { /// - /// Example for basic usage of RedisTimeSeries RANGE command with "-" and "+" as range boundreis. + /// Example for basic usage of RedisTimeSeries RANGE command with TsTimeStamp.MinValue and TsTimeStamp.MaxValue as range boundreis. /// NRedisTimeSeris Range is expecting two TimeStamps objects as the range boundries. /// In this case, the strings are implicitly casted into TimeStamp objects. /// The TimeSeriesRange command returns an IReadOnlyList collection. @@ -21,12 +21,12 @@ public static void DefaultRangeExample() { ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); IDatabase db = redis.GetDatabase(); - IReadOnlyList results = db.TimeSeriesRange("my_ts", "-", "+"); + IReadOnlyList results = db.TimeSeriesRange("my_ts", TsTimeStamp.MinValue, TsTimeStamp.MaxValue); redis.Close(); } /// - /// Example for basic usage of RedisTimeSeries RANGE command with "-" and "+" as range boundreis, and the COUNT parameter. + /// Example for basic usage of RedisTimeSeries RANGE command with TsTimeStamp.MinValue and TsTimeStamp.MaxValue as range boundreis, and the COUNT parameter. /// NRedisTimeSeris Range is expecting two TimeStamps objects as the range boundries. /// In this case, the strings are implicitly casted into TimeStamp objects. /// The TimeSeriesRange command returns an IReadOnlyList collection. @@ -35,12 +35,12 @@ public static void CountRangeExample() { ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); IDatabase db = redis.GetDatabase(); - IReadOnlyList results = db.TimeSeriesRange("my_ts", "-", "+", count:50); + IReadOnlyList results = db.TimeSeriesRange("my_ts", TsTimeStamp.MinValue, TsTimeStamp.MaxValue, count:50); redis.Close(); } /// - /// Example for basic usage of RedisTimeSeries RANGE command with "-" and "+" as range boundreis, and MIN aggregation. + /// Example for basic usage of RedisTimeSeries RANGE command with TsTimeStamp.MinValue and TsTimeStamp.MaxValue as range boundreis, and MIN aggregation. /// NRedisTimeSeris Range is expecting two TimeStamps objects as the range boundries. /// In this case, the strings are implicitly casted into TimeStamp objects. /// The TimeSeriesRange command returns an IReadOnlyList collection. @@ -49,7 +49,7 @@ public static void RangeAggregationExample() { ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); IDatabase db = redis.GetDatabase(); - db.TimeSeriesRange("my_ts", "-", "+", aggregation: Aggregation.MIN, timeBucket: 50); + db.TimeSeriesRange("my_ts", TsTimeStamp.MinValue, TsTimeStamp.MaxValue, aggregation: Aggregation.MIN, timeBucket: new TsTimeBucket(50)); redis.Close(); } } diff --git a/NRedisTimeSeries.Example/RangeExampleAsync.cs b/NRedisTimeSeries.Example/RangeExampleAsync.cs index 22db1f2..b25797a 100644 --- a/NRedisTimeSeries.Example/RangeExampleAsync.cs +++ b/NRedisTimeSeries.Example/RangeExampleAsync.cs @@ -12,7 +12,7 @@ namespace NRedisTimeSeries.Example public class RangeAsyncExample { /// - /// Example for basic usage of RedisTimeSeries RANGE command with "-" and "+" as range boundreis. + /// Example for basic usage of RedisTimeSeries RANGE command with TsTimeStamp.MinValue and TsTimeStamp.MaxValue as range boundreis. /// NRedisTimeSeris Range is expecting two TimeStamps objects as the range boundries. /// In this case, the strings are implicitly casted into TimeStamp objects. /// The TimeSeriesRange command returns an IReadOnlyList collection. @@ -21,12 +21,12 @@ public static async Task DefaultRangeAsyncExample() { ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); IDatabase db = redis.GetDatabase(); - IReadOnlyList results = await db.TimeSeriesRangeAsync("my_ts", "-", "+"); + IReadOnlyList results = await db.TimeSeriesRangeAsync("my_ts", TsTimeStamp.MinValue, TsTimeStamp.MaxValue); redis.Close(); } /// - /// Example for basic usage of RedisTimeSeries RANGE command with "-" and "+" as range boundreis, and the COUNT parameter. + /// Example for basic usage of RedisTimeSeries RANGE command with TsTimeStamp.MinValue and TsTimeStamp.MaxValue as range boundreis, and the COUNT parameter. /// NRedisTimeSeris Range is expecting two TimeStamps objects as the range boundries. /// In this case, the strings are implicitly casted into TimeStamp objects. /// The TimeSeriesRange command returns an IReadOnlyList collection. @@ -35,12 +35,12 @@ public static async Task CountRangeAsyncExample() { ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); IDatabase db = redis.GetDatabase(); - IReadOnlyList results = await db.TimeSeriesRangeAsync("my_ts", "-", "+", count:50); + IReadOnlyList results = await db.TimeSeriesRangeAsync("my_ts", TsTimeStamp.MinValue, TsTimeStamp.MaxValue, count:50); redis.Close(); } /// - /// Example for basic usage of RedisTimeSeries RANGE command with "-" and "+" as range boundreis, and MIN aggregation. + /// Example for basic usage of RedisTimeSeries RANGE command with TsTimeStamp.MinValue and TsTimeStamp.MaxValue as range boundreis, and MIN aggregation. /// NRedisTimeSeris Range is expecting two TimeStamps objects as the range boundries. /// In this case, the strings are implicitly casted into TimeStamp objects. /// The TimeSeriesRange command returns an IReadOnlyList collection. @@ -49,7 +49,7 @@ public static async Task RangeAggregationAsyncExample() { ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); IDatabase db = redis.GetDatabase(); - await db.TimeSeriesRangeAsync("my_ts", "-", "+", aggregation: Aggregation.MIN, timeBucket: 50); + await db.TimeSeriesRangeAsync("my_ts", TsTimeStamp.MinValue, TsTimeStamp.MaxValue, aggregation: Aggregation.MIN, timeBucket: new TsTimeBucket(50)); redis.Close(); } } diff --git a/NRedisTimeSeries.Example/RulesExample.cs b/NRedisTimeSeries.Example/RulesExample.cs index e953b20..e9d7cd9 100644 --- a/NRedisTimeSeries.Example/RulesExample.cs +++ b/NRedisTimeSeries.Example/RulesExample.cs @@ -18,7 +18,7 @@ public static void RulesCreateDeleteExample() ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); IDatabase db = redis.GetDatabase(); // Create you rule with destination key, time bucket and aggregation type. - TimeSeriesRule rule = new TimeSeriesRule("dest_ts", 50, Aggregation.AVG); + TimeSeriesRule rule = new TimeSeriesRule("dest_ts", new TsTimeBucket(50), Aggregation.AVG); db.TimeSeriesCreateRule("my_ts", rule); db.TimeSeriesDeleteRule("my_ts", "dest"); redis.Close(); diff --git a/NRedisTimeSeries.Example/RulesExampleAsync.cs b/NRedisTimeSeries.Example/RulesExampleAsync.cs index a1def16..c907d2e 100644 --- a/NRedisTimeSeries.Example/RulesExampleAsync.cs +++ b/NRedisTimeSeries.Example/RulesExampleAsync.cs @@ -18,7 +18,7 @@ public static async Task RulesCreateDeleteAsyncExample() ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost"); IDatabase db = redis.GetDatabase(); // Create your rule with destination key, time bucket and aggregation type. - TimeSeriesRule rule = new TimeSeriesRule("dest_ts", 50, Aggregation.AVG); + TimeSeriesRule rule = new TimeSeriesRule("dest_ts", new TsTimeBucket(50), Aggregation.AVG); await db.TimeSeriesCreateRuleAsync("my_ts", rule); await db.TimeSeriesDeleteRuleAsync("my_ts", "dest"); redis.Close(); diff --git a/NRedisTimeSeries.Test/TestAPI/AbstractTimeSeriesTest.cs b/NRedisTimeSeries.Test/TestAPI/AbstractTimeSeriesTest.cs index 0d15b8c..e1b9431 100644 --- a/NRedisTimeSeries.Test/TestAPI/AbstractTimeSeriesTest.cs +++ b/NRedisTimeSeries.Test/TestAPI/AbstractTimeSeriesTest.cs @@ -15,7 +15,7 @@ public abstract class AbstractTimeSeriesTest : IClassFixture, IAsy protected internal AbstractTimeSeriesTest(RedisFixture redisFixture) => this.redisFixture = redisFixture; - private List keyNames = new List(); + private List _keyNames = new List(); protected internal string CreateKeyName([CallerMemberName] string memberName = "") => CreateKeyNames(1, memberName)[0]; @@ -29,7 +29,7 @@ protected internal string[] CreateKeyNames(int count, [CallerMemberName] string newKeys[i] = $"{GetType().Name}:{memberName}:{i}"; } - keyNames.AddRange(newKeys); + _keyNames.AddRange(newKeys); return newKeys; } @@ -50,7 +50,7 @@ protected internal static List ReverseData(List (RedisKey)i).ToArray()); + await redis.KeyDeleteAsync(_keyNames.Select(i => (RedisKey)i).ToArray()); } } } diff --git a/NRedisTimeSeries.Test/TestAPI/TestAdd.cs b/NRedisTimeSeries.Test/TestAPI/TestAdd.cs index d75a0ca..55d8c95 100644 --- a/NRedisTimeSeries.Test/TestAPI/TestAdd.cs +++ b/NRedisTimeSeries.Test/TestAPI/TestAdd.cs @@ -9,22 +9,22 @@ namespace NRedisTimeSeries.Test.TestAPI { public class TestAdd : AbstractTimeSeriesTest, IDisposable { - private readonly string key = "ADD_TESTS"; + private readonly string _key = "ADD_TESTS"; public TestAdd(RedisFixture redisFixture) : base(redisFixture) { } public void Dispose() { - redisFixture.Redis.GetDatabase().KeyDelete(key); + redisFixture.Redis.GetDatabase().KeyDelete(_key); } [Fact] public void TestAddNotExistingTimeSeries() { IDatabase db = redisFixture.Redis.GetDatabase(); - TimeStamp now = DateTime.UtcNow; - Assert.Equal(now, db.TimeSeriesAdd(key, now, 1.1)); - TimeSeriesInformation info = db.TimeSeriesInfo(key); + TsTimeStamp now = DateTime.UtcNow; + Assert.Equal(now, db.TimeSeriesAdd(_key, now, 1.1)); + TimeSeriesInformation info = db.TimeSeriesInfo(_key); Assert.Equal(now, info.FirstTimeStamp); Assert.Equal(now, info.LastTimeStamp); } @@ -33,10 +33,10 @@ public void TestAddNotExistingTimeSeries() public void TestAddExistingTimeSeries() { IDatabase db = redisFixture.Redis.GetDatabase(); - db.TimeSeriesCreate(key); - TimeStamp now = DateTime.UtcNow; - Assert.Equal(now, db.TimeSeriesAdd(key, now, 1.1)); - TimeSeriesInformation info = db.TimeSeriesInfo(key); + db.TimeSeriesCreate(_key); + TsTimeStamp now = DateTime.UtcNow; + Assert.Equal(now, db.TimeSeriesAdd(_key, now, 1.1)); + TimeSeriesInformation info = db.TimeSeriesInfo(_key); Assert.Equal(now, info.FirstTimeStamp); Assert.Equal(now, info.LastTimeStamp); } @@ -45,9 +45,9 @@ public void TestAddExistingTimeSeries() public void TestAddStar() { IDatabase db = redisFixture.Redis.GetDatabase(); - db.TimeSeriesAdd(key, "*", 1.1); - TimeSeriesInformation info = db.TimeSeriesInfo(key); - Assert.True(info.FirstTimeStamp > 0); + db.TimeSeriesAdd(_key, 1.1); + TimeSeriesInformation info = db.TimeSeriesInfo(_key); + Assert.True(info.FirstTimeStamp.UnixMilliseconds > 0); Assert.Equal(info.FirstTimeStamp, info.LastTimeStamp); } @@ -55,10 +55,10 @@ public void TestAddStar() public void TestAddWithRetentionTime() { IDatabase db = redisFixture.Redis.GetDatabase(); - TimeStamp now = DateTime.UtcNow; + TsTimeStamp now = DateTime.UtcNow; long retentionTime = 5000; - Assert.Equal(now, db.TimeSeriesAdd(key, now, 1.1, retentionTime: retentionTime)); - TimeSeriesInformation info = db.TimeSeriesInfo(key); + Assert.Equal(now, db.TimeSeriesAdd(_key, now, 1.1, retentionTime: retentionTime)); + TimeSeriesInformation info = db.TimeSeriesInfo(_key); Assert.Equal(now, info.FirstTimeStamp); Assert.Equal(now, info.LastTimeStamp); Assert.Equal(retentionTime, info.RetentionTime); @@ -68,11 +68,11 @@ public void TestAddWithRetentionTime() public void TestAddWithLabels() { IDatabase db = redisFixture.Redis.GetDatabase(); - TimeStamp now = DateTime.UtcNow; + TsTimeStamp now = DateTime.UtcNow; TimeSeriesLabel label = new TimeSeriesLabel("key", "value"); var labels = new List { label }; - Assert.Equal(now, db.TimeSeriesAdd(key, now, 1.1, labels: labels)); - TimeSeriesInformation info = db.TimeSeriesInfo(key); + Assert.Equal(now, db.TimeSeriesAdd(_key, now, 1.1, labels: labels)); + TimeSeriesInformation info = db.TimeSeriesInfo(_key); Assert.Equal(now, info.FirstTimeStamp); Assert.Equal(now, info.LastTimeStamp); Assert.Equal(labels, info.Labels); @@ -82,49 +82,37 @@ public void TestAddWithLabels() public void TestAddWithUncompressed() { IDatabase db = redisFixture.Redis.GetDatabase(); - db.TimeSeriesCreate(key); - TimeStamp now = DateTime.UtcNow; - Assert.Equal(now, db.TimeSeriesAdd(key, now, 1.1, uncompressed: true)); - TimeSeriesInformation info = db.TimeSeriesInfo(key); + db.TimeSeriesCreate(_key); + TsTimeStamp now = DateTime.UtcNow; + Assert.Equal(now, db.TimeSeriesAdd(_key, now, 1.1, uncompressed: true)); + TimeSeriesInformation info = db.TimeSeriesInfo(_key); Assert.Equal(now, info.FirstTimeStamp); Assert.Equal(now, info.LastTimeStamp); } - + [Fact] public void TestAddWithChunkSize() { IDatabase db = redisFixture.Redis.GetDatabase(); - TimeStamp now = DateTime.UtcNow; - Assert.Equal(now, db.TimeSeriesAdd(key, now, 1.1, chunkSizeBytes: 128)); - TimeSeriesInformation info = db.TimeSeriesInfo(key); + TsTimeStamp now = DateTime.UtcNow; + Assert.Equal(now, db.TimeSeriesAdd(_key, now, 1.1, chunkSizeBytes: 128)); + TimeSeriesInformation info = db.TimeSeriesInfo(_key); Assert.Equal(now, info.FirstTimeStamp); Assert.Equal(now, info.LastTimeStamp); Assert.Equal(128, info.ChunkSize); } - [Fact] public void TestOldAdd() { - TimeStamp old_dt = DateTime.UtcNow; + TsTimeStamp old_dt = DateTime.UtcNow; Thread.Sleep(1000); - TimeStamp new_dt = DateTime.UtcNow; + TsTimeStamp new_dt = DateTime.UtcNow; IDatabase db = redisFixture.Redis.GetDatabase(); - db.TimeSeriesCreate(key); - db.TimeSeriesAdd(key, new_dt, 1.1); + db.TimeSeriesCreate(_key); + db.TimeSeriesAdd(_key, new_dt, 1.1); // Adding old event - Assert.Equal( old_dt, db.TimeSeriesAdd(key, old_dt, 1.1)); - } - - [Fact] - public void TestWrongParameters() - { - double value = 1.1; - IDatabase db = redisFixture.Redis.GetDatabase(); - var ex = Assert.Throws(() => db.TimeSeriesAdd(key, "+", value)); - Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); - ex = Assert.Throws(() => db.TimeSeriesAdd(key, "-", value)); - Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); + Assert.Equal(old_dt, db.TimeSeriesAdd(_key, old_dt, 1.1)); } } } diff --git a/NRedisTimeSeries.Test/TestAPI/TestAddAsync.cs b/NRedisTimeSeries.Test/TestAPI/TestAddAsync.cs index d149fd1..cfdee6f 100644 --- a/NRedisTimeSeries.Test/TestAPI/TestAddAsync.cs +++ b/NRedisTimeSeries.Test/TestAPI/TestAddAsync.cs @@ -16,7 +16,7 @@ public async Task TestAddNotExistingTimeSeries() { var key = CreateKeyName(); var db = redisFixture.Redis.GetDatabase(); - TimeStamp timeStamp = DateTime.UtcNow; + TsTimeStamp timeStamp = DateTime.UtcNow; Assert.Equal(timeStamp, await db.TimeSeriesAddAsync(key, timeStamp, 1.1)); var info = await db.TimeSeriesInfoAsync(key); @@ -30,7 +30,7 @@ public async Task TestAddExistingTimeSeries() var key = CreateKeyName(); var db = redisFixture.Redis.GetDatabase(); await db.TimeSeriesCreateAsync(key); - TimeStamp timeStamp = DateTime.UtcNow; + TsTimeStamp timeStamp = DateTime.UtcNow; Assert.Equal(timeStamp, await db.TimeSeriesAddAsync(key, timeStamp, 1.1)); var info = await db.TimeSeriesInfoAsync(key); @@ -43,9 +43,9 @@ public async Task TestAddStar() { var key = CreateKeyName(); var db = redisFixture.Redis.GetDatabase(); - await db.TimeSeriesAddAsync(key, "*", 1.1); + await db.TimeSeriesAddAsync(key, 1.1); var info = await db.TimeSeriesInfoAsync(key); - Assert.True(info.FirstTimeStamp > 0); + Assert.True(info.FirstTimeStamp.UnixMilliseconds > 0); Assert.Equal(info.FirstTimeStamp, info.LastTimeStamp); } @@ -54,7 +54,7 @@ public async Task TestAddWithRetentionTime() { var key = CreateKeyName(); var db = redisFixture.Redis.GetDatabase(); - TimeStamp timeStamp = DateTime.UtcNow; + TsTimeStamp timeStamp = DateTime.UtcNow; long retentionTime = 5000; Assert.Equal(timeStamp, await db.TimeSeriesAddAsync(key, timeStamp, 1.1, retentionTime: retentionTime)); @@ -69,7 +69,7 @@ public async Task TestAddWithLabels() { var key = CreateKeyName(); var db = redisFixture.Redis.GetDatabase(); - TimeStamp timeStamp = DateTime.UtcNow; + TsTimeStamp timeStamp = DateTime.UtcNow; var label = new TimeSeriesLabel("key", "value"); var labels = new List { label }; Assert.Equal(timeStamp, await db.TimeSeriesAddAsync(key, timeStamp, 1.1, labels: labels)); @@ -79,13 +79,13 @@ public async Task TestAddWithLabels() Assert.Equal(timeStamp, info.LastTimeStamp); Assert.Equal(labels, info.Labels); } - + [Fact] public async Task TestAddWithChunkSize() { var key = CreateKeyName(); var db = redisFixture.Redis.GetDatabase(); - TimeStamp timeStamp = DateTime.UtcNow; + TsTimeStamp timeStamp = DateTime.UtcNow; Assert.Equal(timeStamp, await db.TimeSeriesAddAsync(key, timeStamp, 1.1, chunkSizeBytes: 128)); var info = await db.TimeSeriesInfoAsync(key); Assert.Equal(timeStamp, info.FirstTimeStamp); @@ -99,7 +99,7 @@ public async Task TestAddWithUncompressed() var key = CreateKeyName(); var db = redisFixture.Redis.GetDatabase(); await db.TimeSeriesCreateAsync(key); - TimeStamp timeStamp = DateTime.UtcNow; + TsTimeStamp timeStamp = DateTime.UtcNow; Assert.Equal(timeStamp, await db.TimeSeriesAddAsync(key, timeStamp, 1.1, uncompressed: true)); var info = await db.TimeSeriesInfoAsync(key); @@ -114,25 +114,12 @@ public async Task TestOldAdd() var key = CreateKeyName(); var db = redisFixture.Redis.GetDatabase(); var dateTime = DateTime.UtcNow; - TimeStamp oldTimeStamp = dateTime.AddSeconds(-1); - TimeStamp newTimeStamp = dateTime; + TsTimeStamp oldTimeStamp = dateTime.AddSeconds(-1); + TsTimeStamp newTimeStamp = dateTime; await db.TimeSeriesCreateAsync(key); await db.TimeSeriesAddAsync(key, newTimeStamp, 1.1); // Adding old event - Assert.Equal( oldTimeStamp, await db.TimeSeriesAddAsync(key, oldTimeStamp, 1.1)); - } - - [Fact] - public async Task TestWrongParameters() - { - var key = CreateKeyName(); - var value = 1.1; - var db = redisFixture.Redis.GetDatabase(); - var ex = await Assert.ThrowsAsync(async () => await db.TimeSeriesAddAsync(key, "+", value)); - Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); - - ex = await Assert.ThrowsAsync(async () => await db.TimeSeriesAddAsync(key, "-", value)); - Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); + Assert.Equal(oldTimeStamp, await db.TimeSeriesAddAsync(key, oldTimeStamp, 1.1)); } } } diff --git a/NRedisTimeSeries.Test/TestAPI/TestAlter.cs b/NRedisTimeSeries.Test/TestAPI/TestAlter.cs index 2110109..60d5af9 100644 --- a/NRedisTimeSeries.Test/TestAPI/TestAlter.cs +++ b/NRedisTimeSeries.Test/TestAPI/TestAlter.cs @@ -8,13 +8,13 @@ namespace NRedisTimeSeries.Test.TestAPI { public class TestAlter : AbstractTimeSeriesTest, IDisposable { - private readonly string key = "ALTER_TESTS"; + private readonly string _key = "ALTER_TESTS"; public TestAlter(RedisFixture redisFixture): base(redisFixture) { } public void Dispose() { - redisFixture.Redis.GetDatabase().KeyDelete(key); + redisFixture.Redis.GetDatabase().KeyDelete(_key); } [Fact] @@ -22,9 +22,9 @@ public void TestAlterRetentionTime() { long retentionTime = 5000; IDatabase db = redisFixture.Redis.GetDatabase(); - db.TimeSeriesCreate(key); - Assert.True(db.TimeSeriesAlter(key, retentionTime: retentionTime)); - TimeSeriesInformation info = db.TimeSeriesInfo(key); + db.TimeSeriesCreate(_key); + Assert.True(db.TimeSeriesAlter(_key, retentionTime: retentionTime)); + TimeSeriesInformation info = db.TimeSeriesInfo(_key); Assert.Equal(retentionTime, info.RetentionTime); } @@ -34,13 +34,13 @@ public void TestAlterLabels() TimeSeriesLabel label = new TimeSeriesLabel("key", "value"); var labels = new List { label }; IDatabase db = redisFixture.Redis.GetDatabase(); - db.TimeSeriesCreate(key); - Assert.True(db.TimeSeriesAlter(key, labels: labels)); - TimeSeriesInformation info = db.TimeSeriesInfo(key); + db.TimeSeriesCreate(_key); + Assert.True(db.TimeSeriesAlter(_key, labels: labels)); + TimeSeriesInformation info = db.TimeSeriesInfo(_key); Assert.Equal(labels, info.Labels); labels.Clear(); - Assert.True(db.TimeSeriesAlter(key, labels: labels)); - info = db.TimeSeriesInfo(key); + Assert.True(db.TimeSeriesAlter(_key, labels: labels)); + info = db.TimeSeriesInfo(_key); Assert.Equal(labels, info.Labels); } diff --git a/NRedisTimeSeries.Test/TestAPI/TestCreate.cs b/NRedisTimeSeries.Test/TestAPI/TestCreate.cs index 276018e..25db0a6 100644 --- a/NRedisTimeSeries.Test/TestAPI/TestCreate.cs +++ b/NRedisTimeSeries.Test/TestAPI/TestCreate.cs @@ -9,21 +9,21 @@ namespace NRedisTimeSeries.Test.TestAPI { public class TestCreate : AbstractTimeSeriesTest, IDisposable { - private readonly string key = "CREATE_TESTS"; + private readonly string _key = "CREATE_TESTS"; public TestCreate(RedisFixture redisFixture) : base(redisFixture) { } public void Dispose() { - redisFixture.Redis.GetDatabase().KeyDelete(key); + redisFixture.Redis.GetDatabase().KeyDelete(_key); } [Fact] public void TestCreateOK() { IDatabase db = redisFixture.Redis.GetDatabase(); - Assert.True(db.TimeSeriesCreate(key)); - TimeSeriesInformation info = db.TimeSeriesInfo(key); + Assert.True(db.TimeSeriesCreate(_key)); + TimeSeriesInformation info = db.TimeSeriesInfo(_key); } [Fact] @@ -31,8 +31,8 @@ public void TestCreateRetentionTime() { long retentionTime = 5000; IDatabase db = redisFixture.Redis.GetDatabase(); - Assert.True(db.TimeSeriesCreate(key, retentionTime: retentionTime)); - TimeSeriesInformation info = db.TimeSeriesInfo(key); + Assert.True(db.TimeSeriesCreate(_key, retentionTime: retentionTime)); + TimeSeriesInformation info = db.TimeSeriesInfo(_key); Assert.Equal(retentionTime, info.RetentionTime); } @@ -42,8 +42,8 @@ public void TestCreateLabels() TimeSeriesLabel label = new TimeSeriesLabel("key", "value"); var labels = new List { label }; IDatabase db = redisFixture.Redis.GetDatabase(); - Assert.True(db.TimeSeriesCreate(key, labels: labels)); - TimeSeriesInformation info = db.TimeSeriesInfo(key); + Assert.True(db.TimeSeriesCreate(_key, labels: labels)); + TimeSeriesInformation info = db.TimeSeriesInfo(_key); Assert.Equal(labels, info.Labels); } @@ -52,8 +52,8 @@ public void TestCreateEmptyLabels() { var labels = new List(); IDatabase db = redisFixture.Redis.GetDatabase(); - Assert.True(db.TimeSeriesCreate(key, labels: labels)); - TimeSeriesInformation info = db.TimeSeriesInfo(key); + Assert.True(db.TimeSeriesCreate(_key, labels: labels)); + TimeSeriesInformation info = db.TimeSeriesInfo(_key); Assert.Equal(labels, info.Labels); } @@ -61,7 +61,7 @@ public void TestCreateEmptyLabels() public void TestCreateUncompressed() { IDatabase db = redisFixture.Redis.GetDatabase(); - Assert.True(db.TimeSeriesCreate(key, uncompressed: true)); + Assert.True(db.TimeSeriesCreate(_key, uncompressed: true)); } } } diff --git a/NRedisTimeSeries.Test/TestAPI/TestDecrBy.cs b/NRedisTimeSeries.Test/TestAPI/TestDecrBy.cs index add5f4f..faa0270 100644 --- a/NRedisTimeSeries.Test/TestAPI/TestDecrBy.cs +++ b/NRedisTimeSeries.Test/TestAPI/TestDecrBy.cs @@ -8,13 +8,13 @@ namespace NRedisTimeSeries.Test.TestAPI { public class TestDecrBy : AbstractTimeSeriesTest, IDisposable { - private readonly string key = "DECRBY_TESTS"; + private readonly string _key = "DECRBY_TESTS"; - public TestDecrBy(RedisFixture redisFixture) : base(redisFixture) {} + public TestDecrBy(RedisFixture redisFixture) : base(redisFixture) { } public void Dispose() { - redisFixture.Redis.GetDatabase().KeyDelete(key); + redisFixture.Redis.GetDatabase().KeyDelete(_key); } [Fact] @@ -22,17 +22,9 @@ public void TestDefaultDecrBy() { double value = 5.5; IDatabase db = redisFixture.Redis.GetDatabase(); - Assert.True(db.TimeSeriesDecrBy(key, -value) > 0); - Assert.Equal(value, db.TimeSeriesGet(key).Val); - } - - [Fact] - public void TestStarDecrBy() - { - double value = 5.5; - IDatabase db = redisFixture.Redis.GetDatabase(); - Assert.True(db.TimeSeriesDecrBy(key, -value, timestamp: "*") > 0); - Assert.Equal(value, db.TimeSeriesGet(key).Val); + var timeStamp = db.TimeSeriesDecrBy(_key, -value); + Assert.True(timeStamp.UnixMilliseconds > 0); + Assert.Equal(value, db.TimeSeriesGet(_key).Val); } [Fact] @@ -40,9 +32,10 @@ public void TestDecrByTimeStamp() { double value = 5.5; IDatabase db = redisFixture.Redis.GetDatabase(); - TimeStamp timeStamp = DateTime.UtcNow; - Assert.Equal(timeStamp, db.TimeSeriesDecrBy(key, -value, timestamp: timeStamp)); - Assert.Equal(new TimeSeriesTuple(timeStamp, value), db.TimeSeriesGet(key)); + TsTimeStamp timeStamp = DateTime.UtcNow; + var result = db.TimeSeriesDecrBy(_key, -value, timeStamp); + Assert.Equal(timeStamp, result); + Assert.Equal(new TimeSeriesTuple(timeStamp, value), db.TimeSeriesGet(_key)); } [Fact] @@ -51,9 +44,10 @@ public void TestDefaultDecrByWithRetentionTime() double value = 5.5; long retentionTime = 5000; IDatabase db = redisFixture.Redis.GetDatabase(); - Assert.True(db.TimeSeriesDecrBy(key, -value, retentionTime: retentionTime) > 0); - Assert.Equal(value, db.TimeSeriesGet(key).Val); - TimeSeriesInformation info = db.TimeSeriesInfo(key); + var timeStamp = db.TimeSeriesDecrBy(_key, -value, retentionTime: retentionTime); + Assert.True(timeStamp.UnixMilliseconds > 0); + Assert.Equal(value, db.TimeSeriesGet(_key).Val); + TimeSeriesInformation info = db.TimeSeriesInfo(_key); Assert.Equal(retentionTime, info.RetentionTime); } @@ -64,9 +58,10 @@ public void TestDefaultDecrByWithLabels() TimeSeriesLabel label = new TimeSeriesLabel("key", "value"); IDatabase db = redisFixture.Redis.GetDatabase(); var labels = new List { label }; - Assert.True(db.TimeSeriesDecrBy(key, -value, labels: labels) > 0); - Assert.Equal(value, db.TimeSeriesGet(key).Val); - TimeSeriesInformation info = db.TimeSeriesInfo(key); + var timeStamp = db.TimeSeriesDecrBy(_key, -value, labels: labels); + Assert.True(timeStamp.UnixMilliseconds > 0); + Assert.Equal(value, db.TimeSeriesGet(_key).Val); + TimeSeriesInformation info = db.TimeSeriesInfo(_key); Assert.Equal(labels, info.Labels); } @@ -75,19 +70,9 @@ public void TestDefaultDecrByWithUncompressed() { double value = 5.5; IDatabase db = redisFixture.Redis.GetDatabase(); - Assert.True(db.TimeSeriesDecrBy(key, -value, uncompressed: true) > 0); - Assert.Equal(value, db.TimeSeriesGet(key).Val); - } - - [Fact] - public void TestWrongParameters() - { - double value = 5.5; - IDatabase db = redisFixture.Redis.GetDatabase(); - var ex = Assert.Throws(() => db.TimeSeriesDecrBy(key, value, timestamp: "+")); - Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); - ex = Assert.Throws(() => db.TimeSeriesDecrBy(key, value, timestamp: "-")); - Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); + var timeStamp = db.TimeSeriesDecrBy(_key, -value, uncompressed: true); + Assert.True(timeStamp.UnixMilliseconds > 0); + Assert.Equal(value, db.TimeSeriesGet(_key).Val); } } } diff --git a/NRedisTimeSeries.Test/TestAPI/TestDecrByAsync.cs b/NRedisTimeSeries.Test/TestAPI/TestDecrByAsync.cs index dbee547..9546cc7 100644 --- a/NRedisTimeSeries.Test/TestAPI/TestDecrByAsync.cs +++ b/NRedisTimeSeries.Test/TestAPI/TestDecrByAsync.cs @@ -1,5 +1,4 @@ using NRedisTimeSeries.DataTypes; -using StackExchange.Redis; using System; using System.Collections.Generic; using System.Threading.Tasks; @@ -17,19 +16,8 @@ public async Task TestDefaultDecrBy() var key = CreateKeyName(); var value = 5.5; var db = redisFixture.Redis.GetDatabase(); - Assert.True(await db.TimeSeriesDecrByAsync(key, -value) > 0); - - var result = await db.TimeSeriesGetAsync(key); - Assert.Equal(value, result.Val); - } - - [Fact] - public async Task TestStarDecrBy() - { - var key = CreateKeyName(); - var value = 5.5; - var db = redisFixture.Redis.GetDatabase(); - Assert.True(await db.TimeSeriesDecrByAsync(key, -value, timestamp: "*") > 0); + var timeStamp = await db.TimeSeriesDecrByAsync(key, -value); + Assert.True(timeStamp.UnixMilliseconds > 0); var result = await db.TimeSeriesGetAsync(key); Assert.Equal(value, result.Val); @@ -41,8 +29,8 @@ public async Task TestDecrByTimeStamp() var key = CreateKeyName(); var value = 5.5; var db = redisFixture.Redis.GetDatabase(); - TimeStamp timeStamp = DateTime.UtcNow; - Assert.Equal(timeStamp, await db.TimeSeriesDecrByAsync(key, -value, timestamp: timeStamp)); + TsTimeStamp timeStamp = DateTime.UtcNow; + Assert.Equal(timeStamp, await db.TimeSeriesDecrByAsync(key, -value, timeStamp)); Assert.Equal(new TimeSeriesTuple(timeStamp, value), await db.TimeSeriesGetAsync(key)); } @@ -53,7 +41,8 @@ public async Task TestDefaultDecrByWithRetentionTime() var value = 5.5; long retentionTime = 5000; var db = redisFixture.Redis.GetDatabase(); - Assert.True(await db.TimeSeriesDecrByAsync(key, -value, retentionTime: retentionTime) > 0); + var timeStamp = await db.TimeSeriesDecrByAsync(key, -value, retentionTime: retentionTime); + Assert.True(timeStamp.UnixMilliseconds > 0); var result = await db.TimeSeriesGetAsync(key); Assert.Equal(value, result.Val); @@ -70,7 +59,8 @@ public async Task TestDefaultDecrByWithLabels() var label = new TimeSeriesLabel("key", "value"); var db = redisFixture.Redis.GetDatabase(); var labels = new List { label }; - Assert.True(await db.TimeSeriesDecrByAsync(key, -value, labels: labels) > 0); + var timeStamp = await db.TimeSeriesDecrByAsync(key, -value, labels: labels); + Assert.True(timeStamp.UnixMilliseconds > 0); var result = await db.TimeSeriesGetAsync(key); Assert.Equal(value, result.Val); @@ -85,23 +75,11 @@ public async Task TestDefaultDecrByWithUncompressed() var key = CreateKeyName(); var value = 5.5; var db = redisFixture.Redis.GetDatabase(); - Assert.True(await db.TimeSeriesDecrByAsync(key, -value, uncompressed: true) > 0); + var timeStamp = await db.TimeSeriesDecrByAsync(key, -value, uncompressed: true); + Assert.True(timeStamp.UnixMilliseconds > 0); var result = await db.TimeSeriesGetAsync(key); Assert.Equal(value, result.Val); } - - [Fact] - public async Task TestWrongParameters() - { - var key = CreateKeyName(); - var value = 5.5; - var db = redisFixture.Redis.GetDatabase(); - var ex = await Assert.ThrowsAsync(async () => await db.TimeSeriesDecrByAsync(key, value, timestamp: "+")); - Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); - - ex = await Assert.ThrowsAsync(async () => await db.TimeSeriesDecrByAsync(key, value, timestamp: "-")); - Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); - } } } diff --git a/NRedisTimeSeries.Test/TestAPI/TestGet.cs b/NRedisTimeSeries.Test/TestAPI/TestGet.cs index 3baacfd..8efdf40 100644 --- a/NRedisTimeSeries.Test/TestAPI/TestGet.cs +++ b/NRedisTimeSeries.Test/TestAPI/TestGet.cs @@ -7,21 +7,20 @@ namespace NRedisTimeSeries.Test.TestAPI { public class TestGet : AbstractTimeSeriesTest, IDisposable { - - private readonly string key = "GET_TESTS"; + private readonly string _key = "GET_TESTS"; public TestGet(RedisFixture redisFixture) : base(redisFixture) { } public void Dispose() { - redisFixture.Redis.GetDatabase().KeyDelete(key); + redisFixture.Redis.GetDatabase().KeyDelete(_key); } [Fact] public void TestGetNotExists() { IDatabase db = redisFixture.Redis.GetDatabase(); - var ex = Assert.Throws(()=>db.TimeSeriesGet(key)); + var ex = Assert.Throws(()=>db.TimeSeriesGet(_key)); Assert.Equal("ERR TSDB: the key does not exist", ex.Message); } @@ -29,8 +28,8 @@ public void TestGetNotExists() public void TestEmptyGet() { IDatabase db = redisFixture.Redis.GetDatabase(); - db.TimeSeriesCreate(key); - Assert.Null(db.TimeSeriesGet(key)); + db.TimeSeriesCreate(_key); + Assert.Null(db.TimeSeriesGet(_key)); } [Fact] @@ -39,9 +38,9 @@ public void TestAddAndGet() DateTime now = DateTime.UtcNow; TimeSeriesTuple expected = new TimeSeriesTuple(now, 1.1); IDatabase db = redisFixture.Redis.GetDatabase(); - db.TimeSeriesCreate(key); - db.TimeSeriesAdd(key, now, 1.1); - TimeSeriesTuple actual = db.TimeSeriesGet(key); + db.TimeSeriesCreate(_key); + db.TimeSeriesAdd(_key, now, 1.1); + TimeSeriesTuple actual = db.TimeSeriesGet(_key); Assert.Equal(expected, actual); } } diff --git a/NRedisTimeSeries.Test/TestAPI/TestIncrBy.cs b/NRedisTimeSeries.Test/TestAPI/TestIncrBy.cs index 62c3db0..3994f93 100644 --- a/NRedisTimeSeries.Test/TestAPI/TestIncrBy.cs +++ b/NRedisTimeSeries.Test/TestAPI/TestIncrBy.cs @@ -8,13 +8,13 @@ namespace NRedisTimeSeries.Test.TestAPI { public class TestIncrBy : AbstractTimeSeriesTest, IDisposable { - private readonly string key = "INCRBY_TESTS"; + private readonly string _key = "INCRBY_TESTS"; public TestIncrBy(RedisFixture redisFixture) : base(redisFixture) { } public void Dispose() { - redisFixture.Redis.GetDatabase().KeyDelete(key); + redisFixture.Redis.GetDatabase().KeyDelete(_key); } [Fact] @@ -22,17 +22,9 @@ public void TestDefaultIncrBy() { double value = 5.5; IDatabase db = redisFixture.Redis.GetDatabase(); - Assert.True(db.TimeSeriesIncrBy(key, value) > 0); - Assert.Equal(value, db.TimeSeriesGet(key).Val); - } - - [Fact] - public void TestStarIncrBy() - { - double value = 5.5; - IDatabase db = redisFixture.Redis.GetDatabase(); - Assert.True(db.TimeSeriesIncrBy(key, value, timestamp: "*") > 0); - Assert.Equal(value, db.TimeSeriesGet(key).Val); + var timeStamp = db.TimeSeriesIncrBy(_key, value); + Assert.True(timeStamp.UnixMilliseconds > 0); + Assert.Equal(value, db.TimeSeriesGet(_key).Val); } [Fact] @@ -40,9 +32,9 @@ public void TestIncrByTimeStamp() { double value = 5.5; IDatabase db = redisFixture.Redis.GetDatabase(); - TimeStamp timeStamp = DateTime.UtcNow; - Assert.Equal(timeStamp, db.TimeSeriesIncrBy(key, value, timestamp: timeStamp)); - Assert.Equal(new TimeSeriesTuple(timeStamp, value), db.TimeSeriesGet(key)); + TsTimeStamp timeStamp = DateTime.UtcNow; + Assert.Equal(timeStamp, db.TimeSeriesIncrBy(_key, value, timeStamp)); + Assert.Equal(new TimeSeriesTuple(timeStamp, value), db.TimeSeriesGet(_key)); } [Fact] @@ -51,9 +43,10 @@ public void TestDefaultIncrByWithRetentionTime() double value = 5.5; long retentionTime = 5000; IDatabase db = redisFixture.Redis.GetDatabase(); - Assert.True(db.TimeSeriesIncrBy(key, value, retentionTime: retentionTime) > 0); - Assert.Equal(value, db.TimeSeriesGet(key).Val); - TimeSeriesInformation info = db.TimeSeriesInfo(key); + var timeStamp = db.TimeSeriesIncrBy(_key, value, retentionTime: retentionTime); + Assert.True(timeStamp.UnixMilliseconds > 0); + Assert.Equal(value, db.TimeSeriesGet(_key).Val); + TimeSeriesInformation info = db.TimeSeriesInfo(_key); Assert.Equal(retentionTime, info.RetentionTime); } @@ -64,9 +57,10 @@ public void TestDefaultIncrByWithLabels() TimeSeriesLabel label = new TimeSeriesLabel("key", "value"); IDatabase db = redisFixture.Redis.GetDatabase(); var labels = new List { label }; - Assert.True(db.TimeSeriesIncrBy(key, value, labels: labels) > 0); - Assert.Equal(value, db.TimeSeriesGet(key).Val); - TimeSeriesInformation info = db.TimeSeriesInfo(key); + var timeStamp = db.TimeSeriesIncrBy(_key, value, labels: labels); + Assert.True(timeStamp.UnixMilliseconds > 0); + Assert.Equal(value, db.TimeSeriesGet(_key).Val); + TimeSeriesInformation info = db.TimeSeriesInfo(_key); Assert.Equal(labels, info.Labels); } @@ -75,19 +69,9 @@ public void TestDefaultIncrByWithUncompressed() { double value = 5.5; IDatabase db = redisFixture.Redis.GetDatabase(); - Assert.True(db.TimeSeriesIncrBy(key, value, uncompressed:true) > 0); - Assert.Equal(value, db.TimeSeriesGet(key).Val); - } - - [Fact] - public void TestWrongParameters() - { - double value = 5.5; - IDatabase db = redisFixture.Redis.GetDatabase(); - var ex = Assert.Throws(() => db.TimeSeriesIncrBy(key, value, timestamp: "+")); - Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); - ex = Assert.Throws(() => db.TimeSeriesIncrBy(key, value, timestamp: "-")); - Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); + var timeStamp = db.TimeSeriesIncrBy(_key, value, uncompressed: true); + Assert.True(timeStamp.UnixMilliseconds > 0); + Assert.Equal(value, db.TimeSeriesGet(_key).Val); } } } diff --git a/NRedisTimeSeries.Test/TestAPI/TestIncrByAsync.cs b/NRedisTimeSeries.Test/TestAPI/TestIncrByAsync.cs index f90ad0a..3d4710b 100644 --- a/NRedisTimeSeries.Test/TestAPI/TestIncrByAsync.cs +++ b/NRedisTimeSeries.Test/TestAPI/TestIncrByAsync.cs @@ -17,19 +17,8 @@ public async Task TestDefaultIncrBy() var key = CreateKeyName(); var value = 5.5; var db = redisFixture.Redis.GetDatabase(); - Assert.True(await db.TimeSeriesIncrByAsync(key, value) > 0); - - var result = await db.TimeSeriesGetAsync(key); - Assert.Equal(value, result.Val); - } - - [Fact] - public async Task TestStarIncrBy() - { - var key = CreateKeyName(); - var value = 5.5; - var db = redisFixture.Redis.GetDatabase(); - Assert.True(await db.TimeSeriesIncrByAsync(key, value, timestamp: "*") > 0); + var timeStamp = await db.TimeSeriesIncrByAsync(key, value); + Assert.True(timeStamp.UnixMilliseconds > 0); var result = await db.TimeSeriesGetAsync(key); Assert.Equal(value, result.Val); @@ -41,8 +30,8 @@ public async Task TestIncrByTimeStamp() var key = CreateKeyName(); var value = 5.5; var db = redisFixture.Redis.GetDatabase(); - TimeStamp timeStamp = DateTime.UtcNow; - Assert.Equal(timeStamp, await db.TimeSeriesIncrByAsync(key, value, timestamp: timeStamp)); + TsTimeStamp timeStamp = DateTime.UtcNow; + Assert.Equal(timeStamp, await db.TimeSeriesIncrByAsync(key, value, timeStamp)); Assert.Equal(new TimeSeriesTuple(timeStamp, value), await db.TimeSeriesGetAsync(key)); } @@ -53,7 +42,8 @@ public async Task TestDefaultIncrByWithRetentionTime() var value = 5.5; long retentionTime = 5000; var db = redisFixture.Redis.GetDatabase(); - Assert.True(await db.TimeSeriesIncrByAsync(key, value, retentionTime: retentionTime) > 0); + var timeStamp = await db.TimeSeriesIncrByAsync(key, value, retentionTime: retentionTime); + Assert.True(timeStamp.UnixMilliseconds > 0); var result = await db.TimeSeriesGetAsync(key); Assert.Equal(value, result.Val); @@ -70,7 +60,8 @@ public async Task TestDefaultIncrByWithLabels() var label = new TimeSeriesLabel("key", "value"); var db = redisFixture.Redis.GetDatabase(); var labels = new List { label }; - Assert.True(await db.TimeSeriesIncrByAsync(key, value, labels: labels) > 0); + var timeStamp = await db.TimeSeriesIncrByAsync(key, value, labels: labels); + Assert.True(timeStamp.UnixMilliseconds > 0); var result = await db.TimeSeriesGetAsync(key); Assert.Equal(value, result.Val); @@ -85,23 +76,11 @@ public async Task TestDefaultIncrByWithUncompressed() var key = CreateKeyName(); var value = 5.5; var db = redisFixture.Redis.GetDatabase(); - Assert.True(await db.TimeSeriesIncrByAsync(key, value, uncompressed: true) > 0); + var timeStamp = await db.TimeSeriesIncrByAsync(key, value, uncompressed: true); + Assert.True(timeStamp.UnixMilliseconds > 0); var result = await db.TimeSeriesGetAsync(key); Assert.Equal(value, result.Val); } - - [Fact] - public async Task TestWrongParameters() - { - var key = CreateKeyName(); - var value = 5.5; - var db = redisFixture.Redis.GetDatabase(); - var ex = await Assert.ThrowsAsync(async () => await db.TimeSeriesIncrByAsync(key, value, timestamp: "+")); - Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); - - ex = await Assert.ThrowsAsync(async () => await db.TimeSeriesIncrByAsync(key, value, timestamp: "-")); - Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); - } } } diff --git a/NRedisTimeSeries.Test/TestAPI/TestMADD.cs b/NRedisTimeSeries.Test/TestAPI/TestMADD.cs index f7eb1b5..a616809 100644 --- a/NRedisTimeSeries.Test/TestAPI/TestMADD.cs +++ b/NRedisTimeSeries.Test/TestAPI/TestMADD.cs @@ -9,13 +9,13 @@ namespace NRedisTimeSeries.Test.TestAPI public class TestMADD : AbstractTimeSeriesTest, IDisposable { - private readonly string[] keys = { "MADD_TESTS_1", "MADD_TESTS_2" }; + private readonly string[] _keys = { "MADD_TESTS_1", "MADD_TESTS_2" }; public TestMADD(RedisFixture redisFixture) : base(redisFixture) { } public void Dispose() { - foreach(string key in keys) + foreach (string key in _keys) { redisFixture.Redis.GetDatabase().KeyDelete(key); } @@ -27,23 +27,23 @@ public void TestStarMADD() IDatabase db = redisFixture.Redis.GetDatabase(); - foreach (string key in keys) + foreach (string key in _keys) { db.TimeSeriesCreate(key); } - List<(string, TimeStamp, double)> sequence = new List<(string, TimeStamp, double)>(keys.Length); - foreach (var keyname in keys) + List<(string, double)> sequence = new List<(string, double)>(_keys.Length); + foreach (var keyname in _keys) { - sequence.Add((keyname, "*", 1.1)); + sequence.Add((keyname, 1.1)); } var response = db.TimeSeriesMAdd(sequence); - Assert.Equal(keys.Length, response.Count); + Assert.Equal(_keys.Length, response.Count); - foreach (var key in keys) + foreach (var key in _keys) { TimeSeriesInformation info = db.TimeSeriesInfo(key); - Assert.True(info.FirstTimeStamp > 0); + Assert.True(info.FirstTimeStamp.UnixMilliseconds > 0); Assert.Equal(info.FirstTimeStamp, info.LastTimeStamp); } } @@ -54,25 +54,25 @@ public void TestSuccessfulMADD() IDatabase db = redisFixture.Redis.GetDatabase(); - foreach (string key in keys) + foreach (string key in _keys) { db.TimeSeriesCreate(key); } - List<(string, TimeStamp, double)> sequence = new List<(string, TimeStamp, double)>(keys.Length); - List timestamps = new List(keys.Length); - foreach (var keyname in keys) + List<(string, TsTimeStamp, double)> sequence = new List<(string, TsTimeStamp, double)>(_keys.Length); + List timestamps = new List(_keys.Length); + foreach (var keyname in _keys) { - DateTime now = DateTime.UtcNow; + TsTimeStamp now = DateTime.UtcNow; timestamps.Add(now); sequence.Add((keyname, now, 1.1)); } var response = db.TimeSeriesMAdd(sequence); Assert.Equal(timestamps.Count, response.Count); - for(int i = 0; i < response.Count; i++) + for (int i = 0; i < response.Count; i++) { - Assert.Equal(timestamps[i], response[i]); + Assert.Equal(timestamps[i], response[i]); } } @@ -81,19 +81,19 @@ public void TestOverrideMADD() { IDatabase db = redisFixture.Redis.GetDatabase(); - foreach (string key in keys) + foreach (string key in _keys) { db.TimeSeriesCreate(key); } - List oldTimeStamps = new List(); - foreach (var keyname in keys) + List oldTimeStamps = new List(); + foreach (var keyname in _keys) { oldTimeStamps.Add(DateTime.UtcNow); } - List<(string, TimeStamp, double)> sequence = new List<(string, TimeStamp, double)>(keys.Length); - foreach (var keyname in keys) + List<(string, TsTimeStamp, double)> sequence = new List<(string, TsTimeStamp, double)>(_keys.Length); + foreach (var keyname in _keys) { sequence.Add((keyname, DateTime.UtcNow, 1.1)); } @@ -102,16 +102,16 @@ public void TestOverrideMADD() sequence.Clear(); // Override the same events should not throw an error - for (int i =0; i < keys.Length; i++) + for (int i = 0; i < _keys.Length; i++) { - sequence.Add((keys[i], oldTimeStamps[i], 1.1)); + sequence.Add((_keys[i], oldTimeStamps[i], 1.1)); } var response = db.TimeSeriesMAdd(sequence); Assert.Equal(oldTimeStamps.Count, response.Count); - for(int i = 0; i < response.Count; i++) + for (int i = 0; i < response.Count; i++) { - Assert.Equal(oldTimeStamps[i], response[i]); + Assert.Equal(oldTimeStamps[i], response[i]); } } } diff --git a/NRedisTimeSeries.Test/TestAPI/TestMAddAsync.cs b/NRedisTimeSeries.Test/TestAPI/TestMAddAsync.cs index c8b938d..1815f3a 100644 --- a/NRedisTimeSeries.Test/TestAPI/TestMAddAsync.cs +++ b/NRedisTimeSeries.Test/TestAPI/TestMAddAsync.cs @@ -11,7 +11,6 @@ public class TestMAddAsync : AbstractTimeSeriesTest { public TestMAddAsync(RedisFixture redisFixture) : base(redisFixture) { } - [Fact] public async Task TestStarMADD() { @@ -24,10 +23,10 @@ public async Task TestStarMADD() await db.TimeSeriesCreateAsync(key); } - List<(string, TimeStamp, double)> sequence = new List<(string, TimeStamp, double)>(keys.Length); + List<(string, double)> sequence = new List<(string, double)>(keys.Length); foreach (var keyname in keys) { - sequence.Add((keyname, "*", 1.1)); + sequence.Add((keyname, 1.1)); } var response = await db.TimeSeriesMAddAsync(sequence); @@ -36,12 +35,11 @@ public async Task TestStarMADD() foreach (var key in keys) { TimeSeriesInformation info = await db.TimeSeriesInfoAsync(key); - Assert.True(info.FirstTimeStamp > 0); + Assert.True(info.FirstTimeStamp.UnixMilliseconds > 0); Assert.Equal(info.FirstTimeStamp, info.LastTimeStamp); } } - [Fact] public async Task TestSuccessfulMAdd() { @@ -53,8 +51,8 @@ public async Task TestSuccessfulMAdd() await db.TimeSeriesCreateAsync(key); } - var sequence = new List<(string, TimeStamp, double)>(keys.Length); - var timestamps = new List(keys.Length); + var sequence = new List<(string, TsTimeStamp, double)>(keys.Length); + var timestamps = new List(keys.Length); foreach (var keyname in keys) { var now = DateTime.UtcNow; @@ -66,7 +64,7 @@ public async Task TestSuccessfulMAdd() Assert.Equal(timestamps.Count, response.Count); for (var i = 0; i < response.Count; i++) { - Assert.Equal(timestamps[i], response[i]); + Assert.Equal(timestamps[i], response[i]); } } @@ -81,13 +79,13 @@ public async Task TestOverrideMAdd() await db.TimeSeriesCreateAsync(key); } - var oldTimeStamps = new List(); + var oldTimeStamps = new List(); foreach (var keyname in keys) { oldTimeStamps.Add(DateTime.UtcNow); } - var sequence = new List<(string, TimeStamp, double)>(keys.Length); + var sequence = new List<(string, TsTimeStamp, double)>(keys.Length); foreach (var keyname in keys) { sequence.Add((keyname, DateTime.UtcNow, 1.1)); @@ -101,13 +99,13 @@ public async Task TestOverrideMAdd() { sequence.Add((keys[i], oldTimeStamps[i], 1.1)); } - + var response = await db.TimeSeriesMAddAsync(sequence); Assert.Equal(oldTimeStamps.Count, response.Count); - for(int i = 0; i < response.Count; i++) + for (int i = 0; i < response.Count; i++) { - Assert.Equal(oldTimeStamps[i], response[i]); + Assert.Equal(oldTimeStamps[i], response[i]); } } } diff --git a/NRedisTimeSeries.Test/TestAPI/TestMGet.cs b/NRedisTimeSeries.Test/TestAPI/TestMGet.cs index e92400e..14d9776 100644 --- a/NRedisTimeSeries.Test/TestAPI/TestMGet.cs +++ b/NRedisTimeSeries.Test/TestAPI/TestMGet.cs @@ -9,13 +9,13 @@ namespace NRedisTimeSeries.Test.TestAPI public class TestMGet : AbstractTimeSeriesTest, IDisposable { - private readonly string[] keys = { "MGET_TESTS_1", "MGET_TESTS_2" }; + private readonly string[] _keys = { "MGET_TESTS_1", "MGET_TESTS_2" }; public TestMGet(RedisFixture redisFixture) : base(redisFixture) { } public void Dispose() { - foreach (string key in keys) + foreach (string key in _keys) { redisFixture.Redis.GetDatabase().KeyDelete(key); } @@ -31,17 +31,17 @@ public void TestMGetQuery() var labels1 = new List { label1, label2 }; var labels2 = new List { label1 }; - TimeStamp ts1 = db.TimeSeriesAdd(keys[0], "*", 1.1, labels: labels1); + TsTimeStamp ts1 = db.TimeSeriesAdd(_keys[0], 1.1, labels: labels1); TimeSeriesTuple tuple1 = new TimeSeriesTuple(ts1, 1.1); - TimeStamp ts2 = db.TimeSeriesAdd(keys[1], "*", 2.2, labels: labels2); + TsTimeStamp ts2 = db.TimeSeriesAdd(_keys[1], 2.2, labels: labels2); TimeSeriesTuple tuple2 = new TimeSeriesTuple(ts2, 2.2); var results = db.TimeSeriesMGet(new List { "MGET_TESTS_1=value" }); Assert.Equal(2, results.Count); - Assert.Equal(keys[0], results[0].key); - Assert.Equal( tuple1 , results[0].value); + Assert.Equal(_keys[0], results[0].key); + Assert.Equal(tuple1, results[0].value); Assert.Equal(new List(), results[0].labels); - Assert.Equal(keys[1], results[1].key); - Assert.Equal(tuple2 , results[1].value); + Assert.Equal(_keys[1], results[1].key); + Assert.Equal(tuple2, results[1].value); Assert.Equal(new List(), results[1].labels); } @@ -56,18 +56,18 @@ public void TestMGetQueryWithLabels() var labels1 = new List { label1, label2 }; var labels2 = new List { label1 }; - TimeStamp ts1 = db.TimeSeriesAdd(keys[0], "*", 1.1, labels: labels1); + TsTimeStamp ts1 = db.TimeSeriesAdd(_keys[0], 1.1, labels: labels1); TimeSeriesTuple tuple1 = new TimeSeriesTuple(ts1, 1.1); - TimeStamp ts2 = db.TimeSeriesAdd(keys[1], "*", 2.2, labels: labels2); + TsTimeStamp ts2 = db.TimeSeriesAdd(_keys[1], 2.2, labels: labels2); TimeSeriesTuple tuple2 = new TimeSeriesTuple(ts2, 2.2); var results = db.TimeSeriesMGet(new List { "MGET_TESTS_1=value" }, withLabels: true); Assert.Equal(2, results.Count); - Assert.Equal(keys[0], results[0].key); + Assert.Equal(_keys[0], results[0].key); Assert.Equal(tuple1, results[0].value); Assert.Equal(labels1, results[0].labels); - Assert.Equal(keys[1], results[1].key); - Assert.Equal(tuple2 , results[1].value); + Assert.Equal(_keys[1], results[1].key); + Assert.Equal(tuple2, results[1].value); Assert.Equal(labels2, results[1].labels); } } diff --git a/NRedisTimeSeries.Test/TestAPI/TestMGetAsync.cs b/NRedisTimeSeries.Test/TestAPI/TestMGetAsync.cs index bc15265..118ab5f 100644 --- a/NRedisTimeSeries.Test/TestAPI/TestMGetAsync.cs +++ b/NRedisTimeSeries.Test/TestAPI/TestMGetAsync.cs @@ -20,9 +20,9 @@ public async Task TestMGetQuery() var labels1 = new List { label1, label2 }; var labels2 = new List { label1 }; - var ts1 = await db.TimeSeriesAddAsync(keys[0], "*", 1.1, labels: labels1); + var ts1 = await db.TimeSeriesAddAsync(keys[0], 1.1, labels: labels1); var tuple1 = new TimeSeriesTuple(ts1, 1.1); - var ts2 = await db.TimeSeriesAddAsync(keys[1], "*", 2.2, labels: labels2); + var ts2 = await db.TimeSeriesAddAsync(keys[1], 2.2, labels: labels2); var tuple2 = new TimeSeriesTuple(ts2, 2.2); var results = await db.TimeSeriesMGetAsync(new List { $"{keys[0]}=value" }); @@ -46,9 +46,9 @@ public async Task TestMGetQueryWithLabels() var labels1 = new List { label1, label2 }; var labels2 = new List { label1 }; - var ts1 = await db.TimeSeriesAddAsync(keys[0], "*", 1.1, labels: labels1); + var ts1 = await db.TimeSeriesAddAsync(keys[0], 1.1, labels: labels1); var tuple1 = new TimeSeriesTuple(ts1, 1.1); - var ts2 = await db.TimeSeriesAddAsync(keys[1], "*", 2.2, labels: labels2); + var ts2 = await db.TimeSeriesAddAsync(keys[1], 2.2, labels: labels2); var tuple2 = new TimeSeriesTuple(ts2, 2.2); var results = await db.TimeSeriesMGetAsync(new List { $"{keys[0]}=value" }, withLabels: true); diff --git a/NRedisTimeSeries.Test/TestAPI/TestMRange.cs b/NRedisTimeSeries.Test/TestAPI/TestMRange.cs index c55cbd6..e9f7b6a 100644 --- a/NRedisTimeSeries.Test/TestAPI/TestMRange.cs +++ b/NRedisTimeSeries.Test/TestAPI/TestMRange.cs @@ -10,13 +10,13 @@ namespace NRedisTimeSeries.Test.TestAPI { public class TestMRange : AbstractTimeSeriesTest, IDisposable { - private readonly string[] keys = { "MRANGE_TESTS_1", "MRANGE_TESTS_2" }; + private readonly string[] _keys = { "MRANGE_TESTS_1", "MRANGE_TESTS_2" }; public TestMRange(RedisFixture redisFixture) : base(redisFixture) { } public void Dispose() { - foreach (string key in keys) + foreach (string key in _keys) { redisFixture.Redis.GetDatabase().KeyDelete(key); } @@ -28,8 +28,8 @@ private List CreateData(IDatabase db, int timeBucket) for (int i = 0; i < 10; i++) { - TimeStamp ts = new TimeStamp(i*timeBucket); - foreach (var key in keys) + TsTimeStamp ts = new TsTimeStamp(i * timeBucket); + foreach (var key in _keys) { db.TimeSeriesAdd(key, ts, i); @@ -45,17 +45,17 @@ public void TestSimpleMRange() IDatabase db = redisFixture.Redis.GetDatabase(); TimeSeriesLabel label = new TimeSeriesLabel("MRANGEkey", "MRANGEvalue"); var labels = new List { label }; - foreach (string key in keys) + foreach (string key in _keys) { db.TimeSeriesCreate(key, labels: labels); } var tuples = CreateData(db, 50); - var results = db.TimeSeriesMRange("-", "+", new List{ "MRANGEkey=MRANGEvalue" }); - Assert.Equal(keys.Length, results.Count); - for(int i =0; i < results.Count; i++) + var results = db.TimeSeriesMRange(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, new List { "MRANGEkey=MRANGEvalue" }); + Assert.Equal(_keys.Length, results.Count); + for (int i = 0; i < results.Count; i++) { - Assert.Equal(keys[i], results[i].key); + Assert.Equal(_keys[i], results[i].key); Assert.Equal(0, results[i].labels.Count); Assert.Equal(tuples, results[i].values); } @@ -67,17 +67,17 @@ public void TestMRangeWithLabels() IDatabase db = redisFixture.Redis.GetDatabase(); TimeSeriesLabel label = new TimeSeriesLabel("key", "MRangeWithLabels"); var labels = new List { label }; - foreach (string key in keys) + foreach (string key in _keys) { db.TimeSeriesCreate(key, labels: labels); } var tuples = CreateData(db, 50); - var results = db.TimeSeriesMRange("-", "+", new List { "key=MRangeWithLabels" }, withLabels: true); - Assert.Equal(keys.Length, results.Count); + var results = db.TimeSeriesMRange(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, new List { "key=MRangeWithLabels" }, withLabels: true); + Assert.Equal(_keys.Length, results.Count); for (int i = 0; i < results.Count; i++) { - Assert.Equal(keys[i], results[i].key); + Assert.Equal(_keys[i], results[i].key); Assert.Equal(labels, results[i].labels); Assert.Equal(tuples, results[i].values); } @@ -89,11 +89,11 @@ public void TestMRangeFilter() IDatabase db = redisFixture.Redis.GetDatabase(); TimeSeriesLabel label = new TimeSeriesLabel("key", "MRangeFilter"); var labels = new List { label }; - db.TimeSeriesCreate(keys[0], labels: labels); + db.TimeSeriesCreate(_keys[0], labels: labels); var tuples = CreateData(db, 50); - var results = db.TimeSeriesMRange("-", "+", new List { "key=MRangeFilter" }); + var results = db.TimeSeriesMRange(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, new List { "key=MRangeFilter" }); Assert.Equal(1, results.Count); - Assert.Equal(keys[0], results[0].key); + Assert.Equal(_keys[0], results[0].key); Assert.Equal(0, results[0].labels.Count); Assert.Equal(tuples, results[0].values); } @@ -104,20 +104,20 @@ public void TestMRangeCount() IDatabase db = redisFixture.Redis.GetDatabase(); TimeSeriesLabel label = new TimeSeriesLabel("key", "MRangeCount"); var labels = new List { label }; - foreach (string key in keys) + foreach (string key in _keys) { db.TimeSeriesCreate(key, labels: labels); } var tuples = CreateData(db, 50); long count = 5; - var results = db.TimeSeriesMRange("-", "+", new List { "key=MRangeCount" }, count:count); - Assert.Equal(keys.Length, results.Count); + var results = db.TimeSeriesMRange(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, new List { "key=MRangeCount" }, count: count); + Assert.Equal(_keys.Length, results.Count); for (int i = 0; i < results.Count; i++) { - Assert.Equal(keys[i], results[i].key); + Assert.Equal(_keys[i], results[i].key); Assert.Equal(0, results[i].labels.Count); - Assert.Equal(tuples.GetRange(0,(int)count), results[i].values); + Assert.Equal(tuples.GetRange(0, (int)count), results[i].values); } } @@ -127,17 +127,17 @@ public void TestMRangeAggregation() IDatabase db = redisFixture.Redis.GetDatabase(); TimeSeriesLabel label = new TimeSeriesLabel("key", "MRangeAggregation"); var labels = new List { label }; - foreach (string key in keys) + foreach (string key in _keys) { db.TimeSeriesCreate(key, labels: labels); } var tuples = CreateData(db, 50); - var results = db.TimeSeriesMRange("-", "+", new List { "key=MRangeAggregation" }, aggregation: Aggregation.MIN, timeBucket: 50); - Assert.Equal(keys.Length, results.Count); + var results = db.TimeSeriesMRange(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, new List { "key=MRangeAggregation" }, aggregation: Aggregation.MIN, timeBucket: new TsTimeBucket(50)); + Assert.Equal(_keys.Length, results.Count); for (int i = 0; i < results.Count; i++) { - Assert.Equal(keys[i], results[i].key); + Assert.Equal(_keys[i], results[i].key); Assert.Equal(0, results[i].labels.Count); Assert.Equal(tuples, results[i].values); } @@ -149,13 +149,13 @@ public void TestMissingFilter() IDatabase db = redisFixture.Redis.GetDatabase(); TimeSeriesLabel label = new TimeSeriesLabel("key", "MissingFilter"); var labels = new List { label }; - foreach (string key in keys) + foreach (string key in _keys) { db.TimeSeriesCreate(key, labels: labels); } var tuples = CreateData(db, 50); - var ex = Assert.Throws(() => db.TimeSeriesMRange("-", "+", new List())); + var ex = Assert.Throws(() => db.TimeSeriesMRange(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, new List())); Assert.Equal("There should be at least one filter on MRANGE/MREVRANGE", ex.Message); } @@ -165,13 +165,13 @@ public void TestMissingTimeBucket() IDatabase db = redisFixture.Redis.GetDatabase(); TimeSeriesLabel label = new TimeSeriesLabel("key", "MissingTimeBucket"); var labels = new List { label }; - foreach (string key in keys) + foreach (string key in _keys) { db.TimeSeriesCreate(key, labels: labels); } var tuples = CreateData(db, 50); - var ex = Assert.Throws(() => db.TimeSeriesMRange("-", "+", new List { "key=MissingTimeBucket" }, aggregation: Aggregation.AVG)); + var ex = Assert.Throws(() => db.TimeSeriesMRange(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, new List { "key=MissingTimeBucket" }, aggregation: Aggregation.AVG)); Assert.Equal("RANGE Aggregation should have timeBucket value", ex.Message); } diff --git a/NRedisTimeSeries.Test/TestAPI/TestMRangeAsync.cs b/NRedisTimeSeries.Test/TestAPI/TestMRangeAsync.cs index bfe560c..38718c9 100644 --- a/NRedisTimeSeries.Test/TestAPI/TestMRangeAsync.cs +++ b/NRedisTimeSeries.Test/TestAPI/TestMRangeAsync.cs @@ -18,7 +18,7 @@ private async Task> CreateData(IDatabase db, string[] keys for (var i = 0; i < 10; i++) { - var ts = new TimeStamp(i * timeBucket); + var ts = new TsTimeStamp(i * timeBucket); foreach (var key in keys) { await db.TimeSeriesAddAsync(key, ts, i); @@ -42,7 +42,7 @@ public async Task TestSimpleMRange() } var tuples = await CreateData(db, keys, 50); - var results = db.TimeSeriesMRange("-", "+", new List { $"{keys[0]}=value" }); + var results = db.TimeSeriesMRange(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, new List { $"{keys[0]}=value" }); Assert.Equal(keys.Length, results.Count); for (var i = 0; i < results.Count; i++) { @@ -65,7 +65,7 @@ public async Task TestMRangeWithLabels() } var tuples = await CreateData(db, keys, 50); - var results = await db.TimeSeriesMRangeAsync("-", "+", new List { $"{keys[0]}=value" }, withLabels: true); + var results = await db.TimeSeriesMRangeAsync(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, new List { $"{keys[0]}=value" }, withLabels: true); Assert.Equal(keys.Length, results.Count); for (var i = 0; i < results.Count; i++) { @@ -84,7 +84,7 @@ public async Task TestMRangeFilter() var labels = new List { label }; await db.TimeSeriesCreateAsync(keys[0], labels: labels); var tuples = await CreateData(db, keys, 50); - var results = await db.TimeSeriesMRangeAsync("-", "+", new List { $"{keys[0]}=value" }); + var results = await db.TimeSeriesMRangeAsync(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, new List { $"{keys[0]}=value" }); Assert.Equal(1, results.Count); Assert.Equal(keys[0], results[0].key); Assert.Equal(0, results[0].labels.Count); @@ -105,7 +105,7 @@ public async Task TestMRangeCount() var tuples = await CreateData(db, keys, 50); var count = 5L; - var results = await db.TimeSeriesMRangeAsync("-", "+", new List { $"{keys[0]}=value" }, count: count); + var results = await db.TimeSeriesMRangeAsync(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, new List { $"{keys[0]}=value" }, count: count); Assert.Equal(keys.Length, results.Count); for (var i = 0; i < results.Count; i++) { @@ -128,7 +128,7 @@ public async Task TestMRangeAggregation() } var tuples = await CreateData(db, keys, 50); - var results = await db.TimeSeriesMRangeAsync("-", "+", new List { $"{keys[0]}=value" }, aggregation: Aggregation.MIN, timeBucket: 50); + var results = await db.TimeSeriesMRangeAsync(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, new List { $"{keys[0]}=value" }, aggregation: Aggregation.MIN, timeBucket: new TsTimeBucket(50)); Assert.Equal(keys.Length, results.Count); for (var i = 0; i < results.Count; i++) { @@ -151,7 +151,7 @@ public async Task TestMissingFilter() } var tuples = await CreateData(db, keys, 50); - var ex = await Assert.ThrowsAsync(async () => await db.TimeSeriesMRangeAsync("-", "+", new List())); + var ex = await Assert.ThrowsAsync(async () => await db.TimeSeriesMRangeAsync(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, new List())); Assert.Equal("There should be at least one filter on MRANGE/MREVRANGE", ex.Message); } @@ -170,7 +170,7 @@ public async Task TestMissingTimeBucket() var tuples = await CreateData(db, keys, 50); var ex = await Assert.ThrowsAsync(async () => { - await db.TimeSeriesMRangeAsync("-", "+", + await db.TimeSeriesMRangeAsync(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, filter: new List() { $"key=value" }, aggregation: Aggregation.AVG); }); diff --git a/NRedisTimeSeries.Test/TestAPI/TestMRevRange.cs b/NRedisTimeSeries.Test/TestAPI/TestMRevRange.cs index aff8844..19d4c6d 100644 --- a/NRedisTimeSeries.Test/TestAPI/TestMRevRange.cs +++ b/NRedisTimeSeries.Test/TestAPI/TestMRevRange.cs @@ -17,7 +17,7 @@ private List CreateData(IDatabase db, string[] keys, int timeBu for (var i = 0; i < 10; i++) { - var ts = new TimeStamp(i*timeBucket); + var ts = new TsTimeStamp(i*timeBucket); foreach (var key in keys) { db.TimeSeriesAdd(key, ts, i); @@ -41,7 +41,7 @@ public void TestSimpleMRevRange() } var tuples = CreateData(db, keys, 50); - var results = db.TimeSeriesMRevRange("-", "+", new List{ $"{keys[0]}=value" }); + var results = db.TimeSeriesMRevRange(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, new List{ $"{keys[0]}=value" }); Assert.Equal(keys.Length, results.Count); for (var i = 0; i < results.Count; i++) { @@ -64,7 +64,7 @@ public void TestMRevRangeWithLabels() } var tuples = CreateData(db, keys, 50); - var results = db.TimeSeriesMRevRange("-", "+", new List { $"{keys[0]}=value" }, withLabels: true); + var results = db.TimeSeriesMRevRange(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, new List { $"{keys[0]}=value" }, withLabels: true); Assert.Equal(keys.Length, results.Count); for (var i = 0; i < results.Count; i++) @@ -82,9 +82,9 @@ public void TestMRevRangeFilter() var db = redisFixture.Redis.GetDatabase(); var label = new TimeSeriesLabel(keys[0], "value"); var labels = new List { label }; - db.TimeSeriesCreateAsync(keys[0], labels: labels); + db.TimeSeriesCreate(keys[0], labels: labels); var tuples = CreateData(db, keys, 50); - var results = db.TimeSeriesMRevRange("-", "+", new List { $"{keys[0]}=value" }); + var results = db.TimeSeriesMRevRange(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, new List { $"{keys[0]}=value" }); Assert.Equal(1, results.Count); Assert.Equal(keys[0], results[0].key); Assert.Equal(0, results[0].labels.Count); @@ -105,7 +105,7 @@ public void TestMRevRangeCount() var tuples = CreateData(db, keys, 50); var count = 5L; - var results = db.TimeSeriesMRevRange("-", "+", new List { $"{keys[0]}=value" }, count: count); + var results = db.TimeSeriesMRevRange(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, new List { $"{keys[0]}=value" }, count: count); Assert.Equal(keys.Length, results.Count); for (var i = 0; i < results.Count; i++) { @@ -124,11 +124,11 @@ public void TestMRevRangeAggregation() var labels = new List { label }; foreach (var key in keys) { - db.TimeSeriesCreateAsync(key, labels: labels); + db.TimeSeriesCreate(key, labels: labels); } var tuples = CreateData(db, keys, 50); - var results = db.TimeSeriesMRevRange("-", "+", new List { $"{keys[0]}=value" }, aggregation: Aggregation.MIN, timeBucket: 50); + var results = db.TimeSeriesMRevRange(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, new List { $"{keys[0]}=value" }, aggregation: Aggregation.MIN, timeBucket: new TsTimeBucket(50)); Assert.Equal(keys.Length, results.Count); for (var i = 0; i < results.Count; i++) { @@ -147,11 +147,11 @@ public void TestMissingFilter() var labels = new List { label }; foreach (var key in keys) { - db.TimeSeriesCreateAsync(key, labels: labels); + db.TimeSeriesCreate(key, labels: labels); } var tuples = CreateData(db, keys, 50); - var ex = Assert.Throws(() => db.TimeSeriesMRevRange("-", "+", new List())); + var ex = Assert.Throws(() => db.TimeSeriesMRevRange(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, new List())); Assert.Equal("There should be at least one filter on MRANGE/MREVRANGE", ex.Message); } @@ -164,11 +164,11 @@ public void TestMissingTimeBucket() var labels = new List { label }; foreach (var key in keys) { - db.TimeSeriesCreateAsync(key, labels: labels); + db.TimeSeriesCreate(key, labels: labels); } var tuples = CreateData(db, keys, 50); - var ex = Assert.Throws(() => db.TimeSeriesMRevRange("-", "+", new List { "key=MissingTimeBucket" }, aggregation: Aggregation.AVG)); + var ex = Assert.Throws(() => db.TimeSeriesMRevRange(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, new List { "key=MissingTimeBucket" }, aggregation: Aggregation.AVG)); Assert.Equal("RANGE Aggregation should have timeBucket value", ex.Message); } diff --git a/NRedisTimeSeries.Test/TestAPI/TestMRevRangeAsync.cs b/NRedisTimeSeries.Test/TestAPI/TestMRevRangeAsync.cs index c34dd05..6032c67 100644 --- a/NRedisTimeSeries.Test/TestAPI/TestMRevRangeAsync.cs +++ b/NRedisTimeSeries.Test/TestAPI/TestMRevRangeAsync.cs @@ -18,7 +18,7 @@ private async Task> CreateData(IDatabase db, string[] keys for (var i = 0; i < 10; i++) { - var ts = new TimeStamp(i * timeBucket); + var ts = new TsTimeStamp(i * timeBucket); foreach (var key in keys) { await db.TimeSeriesAddAsync(key, ts, i); @@ -42,7 +42,7 @@ public async Task TestSimpleMRevRange() } var tuples = await CreateData(db, keys, 50); - var results = await db.TimeSeriesMRevRangeAsync("-", "+", new List { $"{keys[0]}=value" }); + var results = await db.TimeSeriesMRevRangeAsync(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, new List { $"{keys[0]}=value" }); Assert.Equal(keys.Length, results.Count); for (var i = 0; i < results.Count; i++) { @@ -65,7 +65,7 @@ public async Task TestMRevRangeWithLabels() } var tuples = await CreateData(db, keys, 50); - var results = await db.TimeSeriesMRevRangeAsync("-", "+", new List { $"{keys[0]}=value" }, withLabels: true); + var results = await db.TimeSeriesMRevRangeAsync(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, new List { $"{keys[0]}=value" }, withLabels: true); Assert.Equal(keys.Length, results.Count); for (var i = 0; i < results.Count; i++) { @@ -84,7 +84,7 @@ public async Task TestMRevRangeFilter() var labels = new List { label }; await db.TimeSeriesCreateAsync(keys[0], labels: labels); var tuples = await CreateData(db, keys, 50); - var results = await db.TimeSeriesMRevRangeAsync("-", "+", new List { $"{keys[0]}=value" }); + var results = await db.TimeSeriesMRevRangeAsync(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, new List { $"{keys[0]}=value" }); Assert.Equal(1, results.Count); Assert.Equal(keys[0], results[0].key); Assert.Equal(0, results[0].labels.Count); @@ -105,7 +105,7 @@ public async Task TestMRevRangeCount() var tuples = await CreateData(db, keys, 50); var count = 5L; - var results = await db.TimeSeriesMRevRangeAsync("-", "+", new List { $"{keys[0]}=value" }, count: count); + var results = await db.TimeSeriesMRevRangeAsync(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, new List { $"{keys[0]}=value" }, count: count); Assert.Equal(keys.Length, results.Count); for (var i = 0; i < results.Count; i++) { @@ -128,7 +128,7 @@ public async Task TestMRangeAggregation() } var tuples = await CreateData(db, keys, 50); - var results = await db.TimeSeriesMRevRangeAsync("-", "+", new List { $"{keys[0]}=value" }, aggregation: Aggregation.MIN, timeBucket: 50); + var results = await db.TimeSeriesMRevRangeAsync(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, new List { $"{keys[0]}=value" }, aggregation: Aggregation.MIN, timeBucket: new TsTimeBucket(50)); Assert.Equal(keys.Length, results.Count); for (var i = 0; i < results.Count; i++) { @@ -151,7 +151,7 @@ public async Task TestMissingFilter() } var tuples = await CreateData(db, keys, 50); - var ex = await Assert.ThrowsAsync(async () => await db.TimeSeriesMRevRangeAsync("-", "+", new List())); + var ex = await Assert.ThrowsAsync(async () => await db.TimeSeriesMRevRangeAsync(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, new List())); Assert.Equal("There should be at least one filter on MRANGE/MREVRANGE", ex.Message); } @@ -170,7 +170,7 @@ public async Task TestMissingTimeBucket() var tuples = await CreateData(db, keys, 50); var ex = await Assert.ThrowsAsync(async () => { - await db.TimeSeriesMRevRangeAsync("-", "+", + await db.TimeSeriesMRevRangeAsync(TsTimeStamp.MinValue, TsTimeStamp.MaxValue, filter: new List() { $"key=value" }, aggregation: Aggregation.AVG); }); diff --git a/NRedisTimeSeries.Test/TestAPI/TestQueryIndex.cs b/NRedisTimeSeries.Test/TestAPI/TestQueryIndex.cs index 37f494c..219af42 100644 --- a/NRedisTimeSeries.Test/TestAPI/TestQueryIndex.cs +++ b/NRedisTimeSeries.Test/TestAPI/TestQueryIndex.cs @@ -7,13 +7,13 @@ namespace NRedisTimeSeries.Test.TestAPI { public class TestQueryIndex : AbstractTimeSeriesTest, IDisposable { - private readonly string[] keys = { "QUERYINDEX_TESTS_1", "QUERYINDEX_TESTS_2" }; + private readonly string[] _keys = { "QUERYINDEX_TESTS_1", "QUERYINDEX_TESTS_2" }; public TestQueryIndex(RedisFixture redisFixture) : base(redisFixture) { } public void Dispose() { - foreach (var key in keys) + foreach (var key in _keys) { redisFixture.Redis.GetDatabase().KeyDelete(key); } @@ -28,10 +28,10 @@ public void TestTSQueryIndex() var labels1 = new List { label1, label2 }; var labels2 = new List { label1 }; - db.TimeSeriesCreate(keys[0], labels: labels1); - db.TimeSeriesCreate(keys[1], labels: labels2); - Assert.Equal(keys, db.TimeSeriesQueryIndex(new List { "QUERYINDEX_TESTS_1=value" })); - Assert.Equal(new List { keys[0] }, db.TimeSeriesQueryIndex(new List { "QUERYINDEX_TESTS_2=value2" })); + db.TimeSeriesCreate(_keys[0], labels: labels1); + db.TimeSeriesCreate(_keys[1], labels: labels2); + Assert.Equal(_keys, db.TimeSeriesQueryIndex(new List { "QUERYINDEX_TESTS_1=value" })); + Assert.Equal(new List { _keys[0] }, db.TimeSeriesQueryIndex(new List { "QUERYINDEX_TESTS_2=value2" })); } } } diff --git a/NRedisTimeSeries.Test/TestAPI/TestRange.cs b/NRedisTimeSeries.Test/TestAPI/TestRange.cs index fed807a..e8ef45b 100644 --- a/NRedisTimeSeries.Test/TestAPI/TestRange.cs +++ b/NRedisTimeSeries.Test/TestAPI/TestRange.cs @@ -9,13 +9,13 @@ namespace NRedisTimeSeries.Test.TestAPI { public class TestRange : AbstractTimeSeriesTest, IDisposable { - private readonly string key = "RANGE_TESTS"; + private readonly string _key = "RANGE_TESTS"; public TestRange(RedisFixture redisFixture) : base(redisFixture) { } public void Dispose() { - redisFixture.Redis.GetDatabase().KeyDelete(key); + redisFixture.Redis.GetDatabase().KeyDelete(_key); } private List CreateData(IDatabase db, int timeBucket) @@ -23,7 +23,7 @@ private List CreateData(IDatabase db, int timeBucket) var tuples = new List(); for (int i = 0; i < 10; i++) { - TimeStamp ts = db.TimeSeriesAdd(key, i*timeBucket, i); + TsTimeStamp ts = db.TimeSeriesAdd(_key, new TsTimeStamp(i * timeBucket), i); tuples.Add(new TimeSeriesTuple(ts, i)); } return tuples; @@ -34,7 +34,7 @@ public void TestSimpleRange() { IDatabase db = redisFixture.Redis.GetDatabase(); var tuples = CreateData(db, 50); - Assert.Equal(tuples, db.TimeSeriesRange(key, "-", "+")); + Assert.Equal(tuples, db.TimeSeriesRange(_key, TsTimeStamp.MinValue, TsTimeStamp.MaxValue)); } [Fact] @@ -42,7 +42,7 @@ public void TestRangeCount() { IDatabase db = redisFixture.Redis.GetDatabase(); var tuples = CreateData(db, 50); - Assert.Equal(tuples.GetRange(0, 5), db.TimeSeriesRange(key, "-", "+", count: 5)); + Assert.Equal(tuples.GetRange(0, 5), db.TimeSeriesRange(_key, TsTimeStamp.MinValue, TsTimeStamp.MaxValue, count: 5)); } [Fact] @@ -50,7 +50,7 @@ public void TestRangeAggregation() { IDatabase db = redisFixture.Redis.GetDatabase(); var tuples = CreateData(db, 50); - Assert.Equal(tuples, db.TimeSeriesRange(key, "-", "+", aggregation: Aggregation.MIN, timeBucket: 50)); + Assert.Equal(tuples, db.TimeSeriesRange(_key, TsTimeStamp.MinValue, TsTimeStamp.MaxValue, aggregation: Aggregation.MIN, timeBucket: new TsTimeBucket(50))); } [Fact] @@ -58,7 +58,7 @@ public void TestMissingTimeBucket() { IDatabase db = redisFixture.Redis.GetDatabase(); var tuples = CreateData(db, 50); - var ex = Assert.Throws(() => db.TimeSeriesRange(key, "-", "+", aggregation: Aggregation.AVG)); + var ex = Assert.Throws(() => db.TimeSeriesRange(_key, TsTimeStamp.MinValue, TsTimeStamp.MaxValue, aggregation: Aggregation.AVG)); Assert.Equal("RANGE Aggregation should have timeBucket value", ex.Message); } diff --git a/NRedisTimeSeries.Test/TestAPI/TestRangeAsync.cs b/NRedisTimeSeries.Test/TestAPI/TestRangeAsync.cs index ef8a26d..f381c0e 100644 --- a/NRedisTimeSeries.Test/TestAPI/TestRangeAsync.cs +++ b/NRedisTimeSeries.Test/TestAPI/TestRangeAsync.cs @@ -17,7 +17,7 @@ private async Task> CreateData(IDatabase db, string key, i var tuples = new List(); for (var i = 0; i < 10; i++) { - var ts = await db.TimeSeriesAddAsync(key, i * timeBucket, i); + var ts = await db.TimeSeriesAddAsync(key, new TsTimeStamp(i * timeBucket), i); tuples.Add(new TimeSeriesTuple(ts, i)); } return tuples; @@ -29,7 +29,7 @@ public async Task TestSimpleRange() var key = CreateKeyName(); var db = redisFixture.Redis.GetDatabase(); var tuples = await CreateData(db, key, 50); - Assert.Equal(tuples, await db.TimeSeriesRangeAsync(key, "-", "+")); + Assert.Equal(tuples, await db.TimeSeriesRangeAsync(key, TsTimeStamp.MinValue, TsTimeStamp.MaxValue)); } [Fact] @@ -38,7 +38,7 @@ public async Task TestRangeCount() var key = CreateKeyName(); var db = redisFixture.Redis.GetDatabase(); var tuples = await CreateData(db, key, 50); - Assert.Equal(tuples.GetRange(0, 5), await db.TimeSeriesRangeAsync(key, "-", "+", count: 5)); + Assert.Equal(tuples.GetRange(0, 5), await db.TimeSeriesRangeAsync(key, TsTimeStamp.MinValue, TsTimeStamp.MaxValue, count: 5)); } [Fact] @@ -47,7 +47,7 @@ public async Task TestRangeAggregation() var key = CreateKeyName(); var db = redisFixture.Redis.GetDatabase(); var tuples = await CreateData(db, key, 50); - Assert.Equal(tuples, await db.TimeSeriesRangeAsync(key, "-", "+", aggregation: Aggregation.MIN, timeBucket: 50)); + Assert.Equal(tuples, await db.TimeSeriesRangeAsync(key, TsTimeStamp.MinValue, TsTimeStamp.MaxValue, aggregation: Aggregation.MIN, timeBucket: new TsTimeBucket(50))); } [Fact] @@ -56,7 +56,7 @@ public async Task TestMissingTimeBucket() var key = CreateKeyName(); var db = redisFixture.Redis.GetDatabase(); var tuples = await CreateData(db, key, 50); - var ex = await Assert.ThrowsAsync(async () => await db.TimeSeriesRangeAsync(key, "-", "+", aggregation: Aggregation.AVG)); + var ex = await Assert.ThrowsAsync(async () => await db.TimeSeriesRangeAsync(key, TsTimeStamp.MinValue, TsTimeStamp.MaxValue, aggregation: Aggregation.AVG)); Assert.Equal("RANGE Aggregation should have timeBucket value", ex.Message); } } diff --git a/NRedisTimeSeries.Test/TestAPI/TestRevRange.cs b/NRedisTimeSeries.Test/TestAPI/TestRevRange.cs index 2d40d3a..d36e9a4 100644 --- a/NRedisTimeSeries.Test/TestAPI/TestRevRange.cs +++ b/NRedisTimeSeries.Test/TestAPI/TestRevRange.cs @@ -16,7 +16,7 @@ private List CreateData(IDatabase db, string key, int timeBucke var tuples = new List(); for (var i = 0; i < 10; i++) { - var ts = db.TimeSeriesAdd(key, i * timeBucket, i); + var ts = db.TimeSeriesAdd(key, new TsTimeStamp(i * timeBucket), i); tuples.Add(new TimeSeriesTuple(ts, i)); } return tuples; @@ -28,7 +28,7 @@ public void TestSimpleRevRange() var key = CreateKeyName(); var db = redisFixture.Redis.GetDatabase(); var tuples = CreateData(db, key, 50); - Assert.Equal(ReverseData(tuples), db.TimeSeriesRevRange(key, "-", "+")); + Assert.Equal(ReverseData(tuples), db.TimeSeriesRevRange(key, TsTimeStamp.MinValue, TsTimeStamp.MaxValue)); } [Fact] @@ -37,7 +37,7 @@ public void TestRevRangeCount() var key = CreateKeyName(); var db = redisFixture.Redis.GetDatabase(); var tuples = CreateData(db, key, 50); - Assert.Equal(ReverseData(tuples).GetRange(0, 5), db.TimeSeriesRevRange(key, "-", "+", count: 5)); + Assert.Equal(ReverseData(tuples).GetRange(0, 5), db.TimeSeriesRevRange(key, TsTimeStamp.MinValue, TsTimeStamp.MaxValue, count: 5)); } [Fact] @@ -46,7 +46,7 @@ public void TestRevRangeAggregation() var key = CreateKeyName(); var db = redisFixture.Redis.GetDatabase(); var tuples = CreateData(db, key, 50); - Assert.Equal(ReverseData(tuples), db.TimeSeriesRevRange(key, "-", "+", aggregation: Aggregation.MIN, timeBucket: 50)); + Assert.Equal(ReverseData(tuples), db.TimeSeriesRevRange(key, TsTimeStamp.MinValue, TsTimeStamp.MaxValue, aggregation: Aggregation.MIN, timeBucket: new TsTimeBucket(50))); } [Fact] @@ -55,7 +55,7 @@ public void TestMissingTimeBucket() var key = CreateKeyName(); var db = redisFixture.Redis.GetDatabase(); var tuples = CreateData(db, key, 50); - var ex = Assert.Throws(() => db.TimeSeriesRevRange(key, "-", "+", aggregation: Aggregation.AVG)); + var ex = Assert.Throws(() => db.TimeSeriesRevRange(key, TsTimeStamp.MinValue, TsTimeStamp.MaxValue, aggregation: Aggregation.AVG)); Assert.Equal("RANGE Aggregation should have timeBucket value", ex.Message); } diff --git a/NRedisTimeSeries.Test/TestAPI/TestRevRangeAsync.cs b/NRedisTimeSeries.Test/TestAPI/TestRevRangeAsync.cs index 04062a8..4d91ac9 100644 --- a/NRedisTimeSeries.Test/TestAPI/TestRevRangeAsync.cs +++ b/NRedisTimeSeries.Test/TestAPI/TestRevRangeAsync.cs @@ -17,7 +17,7 @@ private async Task> CreateData(IDatabase db, string key, i var tuples = new List(); for (var i = 0; i < 10; i++) { - var ts = await db.TimeSeriesAddAsync(key, i * timeBucket, i); + var ts = await db.TimeSeriesAddAsync(key, new TsTimeStamp(i * timeBucket), i); tuples.Add(new TimeSeriesTuple(ts, i)); } return tuples; @@ -29,7 +29,7 @@ public async Task TestSimpleRevRange() var key = CreateKeyName(); var db = redisFixture.Redis.GetDatabase(); var tuples = await CreateData(db, key, 50); - Assert.Equal(ReverseData(tuples), await db.TimeSeriesRevRangeAsync(key, "-", "+")); + Assert.Equal(ReverseData(tuples), await db.TimeSeriesRevRangeAsync(key, TsTimeStamp.MinValue, TsTimeStamp.MaxValue)); } [Fact] @@ -38,7 +38,7 @@ public async Task TestRevRangeCount() var key = CreateKeyName(); var db = redisFixture.Redis.GetDatabase(); var tuples = await CreateData(db, key, 50); - Assert.Equal(ReverseData(tuples).GetRange(0, 5), await db.TimeSeriesRevRangeAsync(key, "-", "+", count: 5)); + Assert.Equal(ReverseData(tuples).GetRange(0, 5), await db.TimeSeriesRevRangeAsync(key, TsTimeStamp.MinValue, TsTimeStamp.MaxValue, count: 5)); } [Fact] @@ -47,7 +47,7 @@ public async Task TestRevRangeAggregation() var key = CreateKeyName(); var db = redisFixture.Redis.GetDatabase(); var tuples = await CreateData(db, key, 50); - Assert.Equal(ReverseData(tuples), await db.TimeSeriesRevRangeAsync(key, "-", "+", aggregation: Aggregation.MIN, timeBucket: 50)); + Assert.Equal(ReverseData(tuples), await db.TimeSeriesRevRangeAsync(key, TsTimeStamp.MinValue, TsTimeStamp.MaxValue, aggregation: Aggregation.MIN, timeBucket: new TsTimeBucket(50))); } [Fact] @@ -56,7 +56,7 @@ public async Task TestMissingTimeBucket() var key = CreateKeyName(); var db = redisFixture.Redis.GetDatabase(); var tuples = await CreateData(db, key, 50); - var ex = await Assert.ThrowsAsync(async () => await db.TimeSeriesRevRangeAsync(key, "-", "+", aggregation: Aggregation.AVG)); + var ex = await Assert.ThrowsAsync(async () => await db.TimeSeriesRevRangeAsync(key, TsTimeStamp.MinValue, TsTimeStamp.MaxValue, aggregation: Aggregation.AVG)); Assert.Equal("RANGE Aggregation should have timeBucket value", ex.Message); } } diff --git a/NRedisTimeSeries.Test/TestAPI/TestRules.cs b/NRedisTimeSeries.Test/TestAPI/TestRules.cs index 096ada7..ae964e7 100644 --- a/NRedisTimeSeries.Test/TestAPI/TestRules.cs +++ b/NRedisTimeSeries.Test/TestAPI/TestRules.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using NRedisTimeSeries.Commands; using NRedisTimeSeries.DataTypes; using StackExchange.Redis; @@ -9,14 +10,13 @@ namespace NRedisTimeSeries.Test.TestAPI { public class TestRules : AbstractTimeSeriesTest, IDisposable { - private string srcKey = "RULES_TEST_SRC"; + private string _srcKey = "RULES_TEST_SRC"; - private Dictionary destKeys; + private Dictionary _destKeys; public TestRules(RedisFixture redisFixture) : base(redisFixture) { - - destKeys = new Dictionary + _destKeys = new Dictionary { { Aggregation.AVG, "RULES_DEST_" + Aggregation.AVG }, { Aggregation.COUNT, "RULES_DEST_" + Aggregation.COUNT }, @@ -35,40 +35,39 @@ public TestRules(RedisFixture redisFixture) : base(redisFixture) public void Dispose() { - redisFixture.Redis.GetDatabase().KeyDelete(srcKey); - foreach(var key in destKeys.Values) - { - redisFixture.Redis.GetDatabase().KeyDelete(key); - } + var db = redisFixture.Redis.GetDatabase(); + db.KeyDelete(_srcKey); + db.KeyDelete(_destKeys.Values.Select(i => (RedisKey)i).ToArray()); } [Fact] public void TestRulesAdditionDeletion() { IDatabase db = redisFixture.Redis.GetDatabase(); - db.TimeSeriesCreate(srcKey); - foreach(var destKey in destKeys.Values) + db.TimeSeriesCreate(_srcKey); + foreach(var destKey in _destKeys.Values) { db.TimeSeriesCreate(destKey); } - long timeBucket = 50; + var timeBucket = new TsTimeBucket(50); var rules = new List(); var rulesMap = new Dictionary(); - foreach(var aggregation in destKeys.Keys) + foreach (var aggregation in _destKeys.Keys) { - var rule = new TimeSeriesRule(destKeys[aggregation], timeBucket, aggregation); + var rule = new TimeSeriesRule(_destKeys[aggregation], timeBucket, aggregation); rules.Add(rule); rulesMap[aggregation] = rule; - Assert.True(db.TimeSeriesCreateRule(srcKey, rule)); - TimeSeriesInformation info = db.TimeSeriesInfo(srcKey); + var isCreated = db.TimeSeriesCreateRule(_srcKey, rule); + Assert.True(isCreated); + TimeSeriesInformation info = db.TimeSeriesInfo(_srcKey); Assert.Equal(rules, info.Rules); } - foreach(var aggregation in destKeys.Keys) + foreach (var aggregation in _destKeys.Keys) { var rule = rulesMap[aggregation]; rules.Remove(rule); - Assert.True(db.TimeSeriesDeleteRule(srcKey, rule.DestKey)); - TimeSeriesInformation info = db.TimeSeriesInfo(srcKey); + Assert.True(db.TimeSeriesDeleteRule(_srcKey, rule.DestKey)); + TimeSeriesInformation info = db.TimeSeriesInfo(_srcKey); Assert.Equal(rules, info.Rules); } } @@ -79,10 +78,10 @@ public void TestNonExistingSrc() IDatabase db = redisFixture.Redis.GetDatabase(); string destKey = "RULES_DEST_" + Aggregation.AVG; db.TimeSeriesCreate(destKey); - TimeSeriesRule rule = new TimeSeriesRule(destKey, 50, Aggregation.AVG); - var ex = Assert.Throws(() => db.TimeSeriesCreateRule(srcKey, rule)); + TimeSeriesRule rule = new TimeSeriesRule(destKey, new TsTimeBucket(50), Aggregation.AVG); + var ex = Assert.Throws(() => db.TimeSeriesCreateRule(_srcKey, rule)); Assert.Equal("ERR TSDB: the key does not exist", ex.Message); - ex = Assert.Throws(() => db.TimeSeriesDeleteRule(srcKey, destKey)); + ex = Assert.Throws(() => db.TimeSeriesDeleteRule(_srcKey, destKey)); Assert.Equal("ERR TSDB: the key does not exist", ex.Message); } @@ -91,11 +90,11 @@ public void TestNonExisitingDestinaion() { IDatabase db = redisFixture.Redis.GetDatabase(); string destKey = "RULES_DEST_" + Aggregation.AVG; - db.TimeSeriesCreate(srcKey); - TimeSeriesRule rule = new TimeSeriesRule(destKey, 50, Aggregation.AVG); - var ex = Assert.Throws(() => db.TimeSeriesCreateRule(srcKey, rule)); + db.TimeSeriesCreate(_srcKey); + TimeSeriesRule rule = new TimeSeriesRule(destKey, new TsTimeBucket(50), Aggregation.AVG); + var ex = Assert.Throws(() => db.TimeSeriesCreateRule(_srcKey, rule)); Assert.Equal("ERR TSDB: the key does not exist", ex.Message); - ex = Assert.Throws(() => db.TimeSeriesDeleteRule(srcKey, destKey)); + ex = Assert.Throws(() => db.TimeSeriesDeleteRule(_srcKey, destKey)); Assert.Equal("ERR TSDB: compaction rule does not exist", ex.Message); } } diff --git a/NRedisTimeSeries.Test/TestAPI/TestRulesAsync.cs b/NRedisTimeSeries.Test/TestAPI/TestRulesAsync.cs index ba7fa81..de482cb 100644 --- a/NRedisTimeSeries.Test/TestAPI/TestRulesAsync.cs +++ b/NRedisTimeSeries.Test/TestAPI/TestRulesAsync.cs @@ -24,7 +24,7 @@ public async Task TestRulesAdditionDeletion() await db.TimeSeriesCreateAsync($"{key}:{aggregation.Name}"); } - var timeBucket = 50L; + var timeBucket = new TsTimeBucket(50L); var rules = new List(); var rulesMap = new Dictionary(); foreach (var aggregation in Aggregation.GetEnumerator()) @@ -55,10 +55,10 @@ public async Task TestRulesAdditionDeletion() public async Task TestNonExistingSrc() { var key = CreateKeyName(); - var aggKey = $"{key}:{Aggregation.AVG}"; + var aggKey = $"{key}:{Aggregation.AVG.Name}"; var db = redisFixture.Redis.GetDatabase(); await db.TimeSeriesCreateAsync(aggKey); - var rule = new TimeSeriesRule(aggKey, 50, Aggregation.AVG); + var rule = new TimeSeriesRule(aggKey, new TsTimeBucket(50), Aggregation.AVG); var ex = await Assert.ThrowsAsync(async () => await db.TimeSeriesCreateRuleAsync(key, rule)); Assert.Equal("ERR TSDB: the key does not exist", ex.Message); @@ -72,10 +72,10 @@ public async Task TestNonExistingSrc() public async Task TestNonExisitingDestinaion() { var key = CreateKeyName(); - var aggKey = $"{key}:{Aggregation.AVG}"; + var aggKey = $"{key}:{Aggregation.AVG.Name}"; var db = redisFixture.Redis.GetDatabase(); await db.TimeSeriesCreateAsync(key); - var rule = new TimeSeriesRule(aggKey, 50, Aggregation.AVG); + var rule = new TimeSeriesRule(aggKey, new TsTimeBucket(50), Aggregation.AVG); var ex = await Assert.ThrowsAsync(async () => await db.TimeSeriesCreateRuleAsync(key, rule)); Assert.Equal("ERR TSDB: the key does not exist", ex.Message); diff --git a/NRedisTimeSeries.Test/TestDataTypes/TestTimeSeriesLabel.cs b/NRedisTimeSeries.Test/TestDataTypes/TestTimeSeriesLabel.cs index 3338dc0..efe7cba 100644 --- a/NRedisTimeSeries.Test/TestDataTypes/TestTimeSeriesLabel.cs +++ b/NRedisTimeSeries.Test/TestDataTypes/TestTimeSeriesLabel.cs @@ -1,5 +1,4 @@ -using System; -using NRedisTimeSeries.DataTypes; +using NRedisTimeSeries.DataTypes; using Xunit; namespace NRedisTimeSeries.Test.TestDataTypes diff --git a/NRedisTimeSeries.Test/TestDataTypes/TestTimeSeriesRule.cs b/NRedisTimeSeries.Test/TestDataTypes/TestTimeSeriesRule.cs index 981e417..1eb888a 100644 --- a/NRedisTimeSeries.Test/TestDataTypes/TestTimeSeriesRule.cs +++ b/NRedisTimeSeries.Test/TestDataTypes/TestTimeSeriesRule.cs @@ -1,5 +1,4 @@ -using System; -using NRedisTimeSeries.Commands; +using NRedisTimeSeries.Commands; using NRedisTimeSeries.DataTypes; using Xunit; @@ -12,21 +11,22 @@ public TestTimeSeriesRule() { } [Fact] public void TestRuleConstructor() { - TimeSeriesRule rule = new TimeSeriesRule("key", 50, Aggregation.AVG); + TimeSeriesRule rule = new TimeSeriesRule("key", new TsTimeBucket(50), Aggregation.AVG); Assert.Equal("key", rule.DestKey); Assert.Equal(Aggregation.AVG, rule.Aggregation); - Assert.Equal(50, rule.TimeBucket); + Assert.Equal(new TsTimeBucket(50), rule.TimeBucket); } [Fact] public void TestRuleEquals() { - TimeSeriesRule rule = new TimeSeriesRule("key", 50, Aggregation.AVG); + var timeBucket = new TsTimeBucket(50); + TimeSeriesRule rule = new TimeSeriesRule("key", timeBucket, Aggregation.AVG); - TimeSeriesRule rule1 = new TimeSeriesRule("key", 50, Aggregation.AVG); - TimeSeriesRule rule2 = new TimeSeriesRule("key2", 50, Aggregation.AVG); - TimeSeriesRule rule3 = new TimeSeriesRule("key", 51, Aggregation.AVG); - TimeSeriesRule rule4 = new TimeSeriesRule("key", 50, Aggregation.COUNT); + TimeSeriesRule rule1 = new TimeSeriesRule("key", timeBucket, Aggregation.AVG); + TimeSeriesRule rule2 = new TimeSeriesRule("key2", timeBucket, Aggregation.AVG); + TimeSeriesRule rule3 = new TimeSeriesRule("key", new TsTimeBucket(51), Aggregation.AVG); + TimeSeriesRule rule4 = new TimeSeriesRule("key", timeBucket, Aggregation.COUNT); Assert.Equal(rule, rule1); Assert.NotEqual(rule, rule2); @@ -37,12 +37,13 @@ public void TestRuleEquals() [Fact] public void TestRuleHashCode() { - TimeSeriesRule rule = new TimeSeriesRule("key", 50, Aggregation.AVG); + var timeBucket = new TsTimeBucket(50); + TimeSeriesRule rule = new TimeSeriesRule("key", timeBucket, Aggregation.AVG); - TimeSeriesRule rule1 = new TimeSeriesRule("key", 50, Aggregation.AVG); - TimeSeriesRule rule2 = new TimeSeriesRule("key2", 50, Aggregation.AVG); - TimeSeriesRule rule3 = new TimeSeriesRule("key", 51, Aggregation.AVG); - TimeSeriesRule rule4 = new TimeSeriesRule("key", 50, Aggregation.COUNT); + TimeSeriesRule rule1 = new TimeSeriesRule("key", timeBucket, Aggregation.AVG); + TimeSeriesRule rule2 = new TimeSeriesRule("key2", timeBucket, Aggregation.AVG); + TimeSeriesRule rule3 = new TimeSeriesRule("key", new TsTimeBucket(51), Aggregation.AVG); + TimeSeriesRule rule4 = new TimeSeriesRule("key", timeBucket, Aggregation.COUNT); Assert.Equal(rule.GetHashCode(), rule1.GetHashCode()); Assert.NotEqual(rule.GetHashCode(), rule2.GetHashCode()); diff --git a/NRedisTimeSeries.Test/TestDataTypes/TestTimeSeriesTuple.cs b/NRedisTimeSeries.Test/TestDataTypes/TestTimeSeriesTuple.cs index 0ae9891..657272e 100644 --- a/NRedisTimeSeries.Test/TestDataTypes/TestTimeSeriesTuple.cs +++ b/NRedisTimeSeries.Test/TestDataTypes/TestTimeSeriesTuple.cs @@ -1,4 +1,3 @@ -using System; using NRedisTimeSeries.DataTypes; using Xunit; @@ -19,7 +18,7 @@ public void TestTimeSeriesTupleEqual() { TimeSeriesTuple tuple1 = new TimeSeriesTuple(1, 1.1); TimeSeriesTuple tuple1_1 = new TimeSeriesTuple(1, 1.1); - TimeSeriesTuple tuple1_2 = new TimeSeriesTuple(2, 2.2); + TimeSeriesTuple tuple1_2 = new TimeSeriesTuple(1, 2.2); Assert.Equal(tuple1, tuple1_1); Assert.NotEqual(tuple1, tuple1_2); } @@ -29,7 +28,7 @@ public void TestTimeSeriesTupleHashCode() { TimeSeriesTuple tuple1 = new TimeSeriesTuple(1, 1.1); TimeSeriesTuple tuple1_1 = new TimeSeriesTuple(1, 1.1); - TimeSeriesTuple tuple1_2 = new TimeSeriesTuple(2, 2.2); + TimeSeriesTuple tuple1_2 = new TimeSeriesTuple(1, 2.2); Assert.Equal(tuple1.GetHashCode(), tuple1_1.GetHashCode()); Assert.NotEqual(tuple1.GetHashCode(), tuple1_2.GetHashCode()); } diff --git a/NRedisTimeSeries.Test/TestDataTypes/TestTimeStamp.cs b/NRedisTimeSeries.Test/TestDataTypes/TestTimeStamp.cs deleted file mode 100644 index dfcf7de..0000000 --- a/NRedisTimeSeries.Test/TestDataTypes/TestTimeStamp.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using NRedisTimeSeries.DataTypes; -using Xunit; -namespace NRedisTimeSeries.Test -{ - public class TestTimeStamp - { - - [Fact] - public void TestTimeStampImplicitCast() - { - TimeStamp ts = 1; - Assert.Equal(1, ts); - - ts = "+"; - Assert.Equal("+", ts); - - ts = "*"; - Assert.Equal("*", ts); - - ts = "-"; - Assert.Equal("-", ts); - - var ex = Assert.Throws(() => ts = "hi"); - Assert.Equal("The string hi cannot be used", ex.Message); - - DateTime now = DateTime.UtcNow; - ts = now; - Assert.Equal(now, ts); - - } - } -} diff --git a/NRedisTimeSeries.Test/TestDataTypes/TestTsTimeBucket.cs b/NRedisTimeSeries.Test/TestDataTypes/TestTsTimeBucket.cs new file mode 100644 index 0000000..9528139 --- /dev/null +++ b/NRedisTimeSeries.Test/TestDataTypes/TestTsTimeBucket.cs @@ -0,0 +1,61 @@ +using NRedisTimeSeries.DataTypes; +using System; +using Xunit; +namespace NRedisTimeSeries.Test +{ + public class TestTsTimeBucket + { + [Fact] + public void TestConstruction() + { + // Test default and empty constructors + var tsTimeBucketDefault = default(TsTimeBucket); + Assert.Equal(new TsTimeBucket(), tsTimeBucketDefault); + + // Test DateTime constructor + var now = DateTime.UtcNow; + var nowPlus1Day = now.AddDays(1); + var tsTimeBucketDateTime = new TsTimeBucket(now, nowPlus1Day); + Assert.True(tsTimeBucketDateTime.UnixMilliseconds > 0); + + // Test UnixMs long constructor + var tsTimeBucketsUnixMs = new TsTimeBucket(1000); + Assert.Equal(1000, tsTimeBucketsUnixMs.UnixMilliseconds); + } + + [Fact] + public void TestRanges() + { + var tsMin = new TsTimeBucket(DateTime.UnixEpoch.AddMilliseconds(1), DateTime.UnixEpoch.AddMilliseconds(1000)); + Assert.Equal(999, tsMin.UnixMilliseconds); + + var tsMax = new TsTimeBucket(DateTime.UnixEpoch.AddMilliseconds(1), DateTime.MaxValue.ToUniversalTime()); + Assert.Equal(TsTimeBucket.MaxValue, tsMax); + + var tsMinMs = new TsTimeBucket(1); + Assert.Equal(TsTimeBucket.MinValue, tsMinMs); + + var tsMaxMs = new TsTimeBucket(253_402_271_999_998); + Assert.Equal(TsTimeBucket.MaxValue, tsMaxMs); + } + + [Fact] + public void TestExceptions() + { + var ex0 = Assert.Throws(() => new TsTimeBucket(new TsTimeStamp(0), new TsTimeStamp(0))); + Assert.Equal("The time bucket must be 1ms or greater", ex0.Message); + + var ex1 = Assert.Throws(() => new TsTimeBucket(0)); + Assert.Equal("Must be 1ms or greater (Parameter 'unixMilliseconds')", ex1.Message); + + var ex2 = Assert.Throws(() => new TsTimeBucket(-1)); + Assert.Equal($"Must be {1}ms or greater (Parameter 'unixMilliseconds')", ex2.Message); + + var ex3 = Assert.Throws(() => new TsTimeBucket(long.MaxValue)); + Assert.Equal($"Must be {253_402_271_999_998}ms or less (Parameter 'unixMilliseconds')", ex3.Message); + + var ex4 = Assert.Throws(() => new TsTimeBucket(DateTime.MinValue.ToUniversalTime(), DateTime.MaxValue.ToUniversalTime())); + Assert.Equal($"Must be Unix Epoch time or greater (Parameter 'dateTime')", ex4.Message); + } + } +} diff --git a/NRedisTimeSeries.Test/TestDataTypes/TestTsTimeStamp.cs b/NRedisTimeSeries.Test/TestDataTypes/TestTsTimeStamp.cs new file mode 100644 index 0000000..bf8dee2 --- /dev/null +++ b/NRedisTimeSeries.Test/TestDataTypes/TestTsTimeStamp.cs @@ -0,0 +1,78 @@ +using NRedisTimeSeries.DataTypes; +using System; +using Xunit; +namespace NRedisTimeSeries.Test +{ + public class TestTsTimeStamp + { + [Fact] + public void TestConstruction() + { + // Test default and empty constructors + var tsDefault = default(TsTimeStamp); + Assert.Equal(new TsTimeStamp(), tsDefault); + + // Test DateTime constructor + var now = DateTime.UtcNow; + var tsDateTime = new TsTimeStamp(now); + Assert.True(tsDateTime.UnixMilliseconds > 0); + + // Test UnixMs long constructor + var tsUnixMs = new TsTimeStamp(1000); + Assert.Equal(1000, tsUnixMs.UnixMilliseconds); + } + + [Fact] + public void TestRanges() + { + var tsMin = new TsTimeStamp(DateTime.UnixEpoch); + Assert.Equal(TsTimeStamp.MinValue, tsMin); + + var tsMax = new TsTimeStamp(DateTime.MaxValue.ToUniversalTime()); + Assert.Equal(TsTimeStamp.MaxValue, tsMax); + + var tsMinMs = new TsTimeStamp(0); + Assert.Equal(TsTimeStamp.MinValue, tsMinMs); + + var tsMaxMs = new TsTimeStamp(253_402_271_999_999); + Assert.Equal(TsTimeStamp.MaxValue, tsMaxMs); + } + + [Fact] + public void TestEquality() + { + var utcNow = DateTime.UtcNow; + var unixMsNow = new DateTimeOffset(utcNow).ToUnixTimeMilliseconds(); + Assert.Equal(new TsTimeStamp(utcNow), new TsTimeStamp(unixMsNow)); + } + + [Fact] + public void TestImplicitConversion() + { + TsTimeStamp tsMax = DateTime.MaxValue.ToUniversalTime(); + Assert.Equal(TsTimeStamp.MaxValue, tsMax); + + DateTime dtMax = tsMax; + Assert.Equal((DateTime)TsTimeStamp.MaxValue, dtMax); + + TsTimeStamp tsOne = 1; + Assert.Equal(1, tsOne.UnixMilliseconds); + } + + [Fact] + public void TestExceptions() + { + var ex1 = Assert.Throws(() => new TsTimeStamp(DateTime.MaxValue)); + Assert.Equal("DateTime Kind must be UTC (Parameter 'dateTime')", ex1.Message); + + var ex2 = Assert.Throws(() => new TsTimeStamp(-1)); + Assert.Equal($"Must be {0}ms or greater (Parameter 'unixMilliseconds')", ex2.Message); + + var ex3 = Assert.Throws(() => new TsTimeStamp(long.MaxValue)); + Assert.Equal($"Must be {253_402_271_999_999}ms or less (Parameter 'unixMilliseconds')", ex3.Message); + + var ex4 = Assert.Throws(() => new TsTimeStamp(DateTime.MinValue.ToUniversalTime())); + Assert.Equal($"Must be Unix Epoch time or greater (Parameter 'dateTime')", ex4.Message); + } + } +} diff --git a/NRedisTimeSeries/DataTypes/TimeSeriesInformation.cs b/NRedisTimeSeries/DataTypes/TimeSeriesInformation.cs index 7c434fa..4ecdc50 100644 --- a/NRedisTimeSeries/DataTypes/TimeSeriesInformation.cs +++ b/NRedisTimeSeries/DataTypes/TimeSeriesInformation.cs @@ -22,12 +22,12 @@ public class TimeSeriesInformation /// /// First timestamp present in the time-series. /// - public TimeStamp FirstTimeStamp { get; private set; } + public TsTimeStamp FirstTimeStamp { get; private set; } /// /// Last timestamp present in the time-series. /// - public TimeStamp LastTimeStamp { get; private set; } + public TsTimeStamp LastTimeStamp { get; private set; } /// /// Retention time, in milliseconds, for the time-series. @@ -65,7 +65,7 @@ public class TimeSeriesInformation /// public IReadOnlyList Rules { get; private set; } - internal TimeSeriesInformation(long totalSamples, long memoryUsage, TimeStamp firstTimeStamp, TimeStamp lastTimeStamp, long retentionTime, long chunkCount, long chunkSize, IReadOnlyList labels, string sourceKey, IReadOnlyList rules) + internal TimeSeriesInformation(long totalSamples, long memoryUsage, TsTimeStamp firstTimeStamp, TsTimeStamp lastTimeStamp, long retentionTime, long chunkCount, long chunkSize, IReadOnlyList labels, string sourceKey, IReadOnlyList rules) { TotalSamples = totalSamples; MemoryUsage = memoryUsage; diff --git a/NRedisTimeSeries/DataTypes/TimeSeriesRule.cs b/NRedisTimeSeries/DataTypes/TimeSeriesRule.cs index 55e8863..b18e00d 100644 --- a/NRedisTimeSeries/DataTypes/TimeSeriesRule.cs +++ b/NRedisTimeSeries/DataTypes/TimeSeriesRule.cs @@ -16,7 +16,7 @@ public class TimeSeriesRule /// /// Rule's aggregation time bucket. /// - public long TimeBucket { get; private set; } + public TsTimeBucket TimeBucket { get; private set; } /// /// Rule's aggregation type. @@ -29,7 +29,7 @@ public class TimeSeriesRule /// Rule's destination key. /// Rule's aggregation time bucket. /// Rule's aggregation type. - public TimeSeriesRule(string destKey, long timeBucket, Aggregation aggregation) => + public TimeSeriesRule(string destKey, TsTimeBucket timeBucket, Aggregation aggregation) => (DestKey, TimeBucket, Aggregation) = (destKey, timeBucket, aggregation); /// diff --git a/NRedisTimeSeries/DataTypes/TimeSeriesTuple.cs b/NRedisTimeSeries/DataTypes/TimeSeriesTuple.cs index 7aeb76b..0e07fcb 100644 --- a/NRedisTimeSeries/DataTypes/TimeSeriesTuple.cs +++ b/NRedisTimeSeries/DataTypes/TimeSeriesTuple.cs @@ -10,7 +10,7 @@ public class TimeSeriesTuple /// /// Tuple key - timestamp. /// - public TimeStamp Time { get; } + public TsTimeStamp Time { get; } /// /// Tuple value @@ -22,7 +22,7 @@ public class TimeSeriesTuple /// /// Timestamp /// Value - public TimeSeriesTuple(TimeStamp time, double val) => (Time, Val) = (time, val); + public TimeSeriesTuple(TsTimeStamp time, double val) => (Time, Val) = (time, val); /// /// Equality of TimeSeriesTuple objects @@ -31,7 +31,7 @@ public class TimeSeriesTuple /// If two TimeSeriesTuple objects are equal public override bool Equals(object obj) => obj is TimeSeriesTuple tuple && - EqualityComparer.Default.Equals(Time, tuple.Time) && + EqualityComparer.Default.Equals(Time, tuple.Time) && Val == tuple.Val; /// @@ -41,7 +41,7 @@ obj is TimeSeriesTuple tuple && public override int GetHashCode() { var hashCode = 459537088; - hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(Time); + hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(Time); hashCode = (hashCode * -1521134295) + Val.GetHashCode(); return hashCode; } diff --git a/NRedisTimeSeries/DataTypes/TimeStamp.cs b/NRedisTimeSeries/DataTypes/TimeStamp.cs deleted file mode 100644 index e1e281a..0000000 --- a/NRedisTimeSeries/DataTypes/TimeStamp.cs +++ /dev/null @@ -1,99 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace NRedisTimeSeries.DataTypes -{ - /// - /// A class represents timestamp. - /// Value can be either primitive long, DateTime or one of the strings "-", "+", "*". - /// - public class TimeStamp - { - private static readonly string[] constants = { "-", "+", "*" }; - - /// - /// TimeStamp value. - /// - public object Value { get; private set; } - - /// - /// Build a TimeStamp from primitive long. - /// - /// long value - public TimeStamp(long timestamp) => Value = timestamp; - - /// - /// Build a TimeStamp from DateTime. - /// - /// DateTime value - public TimeStamp(DateTime dateTime) => Value = dateTime.Ticks; - - /// - /// Build a TimeStamp from one of the strings "-", "+", "*". - /// If the string is none of the above a NotSupportedException is thrown. - /// - /// String value - public TimeStamp(string timestamp) - { - if (Array.IndexOf(constants, timestamp) == -1) - { - throw new NotSupportedException(string.Format("The string {0} cannot be used", timestamp)); - } - Value = timestamp; - } - - /// - /// Implicit cast from long to TimeStamp. - /// - /// long value. - public static implicit operator TimeStamp(long l) => new TimeStamp(l); - - /// - /// Implicit cast from TimeStamp to long. - /// If the underlying timestamp value is not long or DateTime, an InvalidCastException is thrown. - /// - /// TimeStamp - public static implicit operator long(TimeStamp ts) => - ts.Value is long value ? value : throw new InvalidCastException("Cannot convert string timestamp to long"); - - /// - /// Implicit cast from string to TimeStamp. - /// Calls the string C'tor. - /// - /// String value - public static implicit operator TimeStamp(string s) => new TimeStamp(s); - - /// - /// Implicit cast from TimeStamp to string. - /// - /// TimeStamp - public static implicit operator string(TimeStamp ts) => ts.Value.ToString(); - - /// - /// Implicit cast from DateTime to TimeStamp. - /// - /// DateTime value - public static implicit operator TimeStamp(DateTime dateTime) => new TimeStamp(dateTime); - - /// - /// Implicit cast from TimeStamp to DateTime. - /// - /// TimeStamp - public static implicit operator DateTime(TimeStamp timeStamp) => new DateTime(timeStamp); - - /// - /// Equality of TimeSeriesTuple objects - /// - /// Object to compare - /// If two TimeStamp objects are equal - public override bool Equals(object obj) => - obj is TimeStamp stamp && EqualityComparer.Default.Equals(Value, stamp.Value); - - /// - /// TimeStamp object hash code. - /// - /// TimeStamp object hash code. - public override int GetHashCode() => - -1937169414 + EqualityComparer.Default.GetHashCode(Value); - } -} diff --git a/NRedisTimeSeries/DataTypes/TsTimeBucket.cs b/NRedisTimeSeries/DataTypes/TsTimeBucket.cs new file mode 100644 index 0000000..fe7be04 --- /dev/null +++ b/NRedisTimeSeries/DataTypes/TsTimeBucket.cs @@ -0,0 +1,48 @@ +using System; + +namespace NRedisTimeSeries.DataTypes +{ + public readonly struct TsTimeBucket : IEquatable + { + private const long _minUnixMilliseconds = 1; // 01/01/1970 12:00:00 AM (+1ms) + private const long _maxUnixMilliseconds = 253_402_271_999_998; // 12/31/9999 03:59:59 PM + + public long UnixMilliseconds { get; } + + public static readonly TsTimeBucket MinValue = new TsTimeBucket(_minUnixMilliseconds); + public static readonly TsTimeBucket MaxValue = new TsTimeBucket(_maxUnixMilliseconds); + + public TsTimeBucket(long unixMilliseconds) + { + if (unixMilliseconds < _minUnixMilliseconds) + throw new ArgumentOutOfRangeException(nameof(unixMilliseconds), $"Must be {_minUnixMilliseconds}ms or greater"); + + if (unixMilliseconds > _maxUnixMilliseconds) + throw new ArgumentOutOfRangeException(nameof(unixMilliseconds), $"Must be {_maxUnixMilliseconds}ms or less"); + + UnixMilliseconds = unixMilliseconds; + } + + public TsTimeBucket(TsTimeStamp fromTimeStamp, TsTimeStamp toTimeStamp) + { + var unixMilliseconds = toTimeStamp.UnixMilliseconds - fromTimeStamp.UnixMilliseconds; + + if (unixMilliseconds < 1) + throw new ArgumentException($"The time bucket must be {_minUnixMilliseconds}ms or greater"); + + UnixMilliseconds = unixMilliseconds; + } + + public static bool operator ==(TsTimeBucket left, TsTimeBucket right) => Equals(left, right); + + public static bool operator !=(TsTimeBucket left, TsTimeBucket right) => !Equals(left, right); + + public override bool Equals(object obj) => obj is TsTimeBucket other && Equals(other); + + public bool Equals(TsTimeBucket other) => UnixMilliseconds == other.UnixMilliseconds; + + public override int GetHashCode() => UnixMilliseconds.GetHashCode(); + + public override string ToString() => UnixMilliseconds.ToString(); + } +} diff --git a/NRedisTimeSeries/DataTypes/TsTimeStamp.cs b/NRedisTimeSeries/DataTypes/TsTimeStamp.cs new file mode 100644 index 0000000..d79afd8 --- /dev/null +++ b/NRedisTimeSeries/DataTypes/TsTimeStamp.cs @@ -0,0 +1,62 @@ +using System; + +namespace NRedisTimeSeries.DataTypes +{ + public readonly struct TsTimeStamp : IEquatable + { + private const long _minUnixMilliseconds = 0; // 01/01/1970 12:00:00 AM + private const long _maxUnixMilliseconds = 253_402_271_999_999; // 12/31/9999 03:59:59 PM + private const long _epochTicks = 621_355_968_000_000_000; // 01/01/1970 12:00:00 AM + + public long UnixMilliseconds { get; } + + public DateTime UtcDateTime => DateTimeOffset.FromUnixTimeMilliseconds(UnixMilliseconds).UtcDateTime; + + public static readonly TsTimeStamp MinValue = new TsTimeStamp(_minUnixMilliseconds); + public static readonly TsTimeStamp MaxValue = new TsTimeStamp(_maxUnixMilliseconds); + + public TsTimeStamp(long unixMilliseconds) + { + //TODO: Remove when module allows negative timestamps + if (unixMilliseconds < _minUnixMilliseconds) + throw new ArgumentOutOfRangeException(nameof(unixMilliseconds), $"Must be {_minUnixMilliseconds}ms or greater"); + + if (unixMilliseconds > _maxUnixMilliseconds) + throw new ArgumentOutOfRangeException(nameof(unixMilliseconds), $"Must be {_maxUnixMilliseconds}ms or less"); + + UnixMilliseconds = unixMilliseconds; + } + + public TsTimeStamp(DateTime dateTime) + { + if (dateTime.Kind != DateTimeKind.Utc) + throw new ArgumentException("DateTime Kind must be UTC", nameof(dateTime)); + + //TODO: Remove when module allows negative timestamps + if (dateTime.Ticks < _epochTicks) + throw new ArgumentOutOfRangeException(nameof(dateTime), $"Must be Unix Epoch time or greater"); + + UnixMilliseconds = new DateTimeOffset(dateTime).ToUnixTimeMilliseconds(); + } + + public static implicit operator long(TsTimeStamp timeStamp) => timeStamp.UnixMilliseconds; + + public static implicit operator TsTimeStamp(long unixMilliseconds) => new TsTimeStamp(unixMilliseconds); + + public static implicit operator DateTime(TsTimeStamp timeStamp) => timeStamp.UtcDateTime; + + public static implicit operator TsTimeStamp(DateTime dateTime) => new TsTimeStamp(dateTime); + + public static bool operator ==(TsTimeStamp left, TsTimeStamp right) => Equals(left, right); + + public static bool operator !=(TsTimeStamp left, TsTimeStamp right) => !Equals(left, right); + + public override bool Equals(object obj) => obj is TsTimeStamp other && Equals(other); + + public bool Equals(TsTimeStamp other) => UnixMilliseconds == other.UnixMilliseconds; + + public override int GetHashCode() => UnixMilliseconds.GetHashCode(); + + public override string ToString() => UtcDateTime.ToString(); + } +} diff --git a/NRedisTimeSeries/TimeSeriesClient.cs b/NRedisTimeSeries/TimeSeriesClient.cs index 2e0c6bc..225bb6e 100644 --- a/NRedisTimeSeries/TimeSeriesClient.cs +++ b/NRedisTimeSeries/TimeSeriesClient.cs @@ -60,13 +60,29 @@ public static bool TimeSeriesAlter(this IDatabase db, string key, long? retentio /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. /// You can alter the default TSDB chunk size by passing the chunk_size argument (in Bytes) /// The timestamp value of the new sample - public static TimeStamp TimeSeriesAdd(this IDatabase db, string key, TimeStamp timestamp, double value, long? retentionTime = null, IReadOnlyCollection labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) + public static TsTimeStamp TimeSeriesAdd(this IDatabase db, string key, TsTimeStamp timestamp, double value, long? retentionTime = null, IReadOnlyCollection labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) { - var args = BuildTsAddArgs(key, timestamp, value, retentionTime, labels, uncompressed, chunkSizeBytes); + var args = BuildTsAddArgs(key, value, retentionTime, labels, uncompressed, chunkSizeBytes, timestamp); return ParseTimeStamp(db.Execute(TS.ADD, args)); } - + /// + /// Append (or create and append) a new sample to the series using an automatic timestamp. + /// + /// StackExchange.Redis IDatabase instance + /// Key name for timeseries + /// Numeric data value of the sample. + /// Optional: Maximum age for samples compared to last event time (in milliseconds) + /// Optional: Collaction of label-value pairs that represent metadata labels of the key + /// Optional: Adding this flag will keep data in an uncompressed form + /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. + /// You can alter the default TSDB chunk size by passing the chunk_size argument (in Bytes) + /// The timestamp value of the new sample + public static TsTimeStamp TimeSeriesAdd(this IDatabase db, string key, double value, long? retentionTime = null, IReadOnlyCollection labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) + { + var args = BuildTsAddArgs(key, value, retentionTime, labels, uncompressed, chunkSizeBytes); + return ParseTimeStamp(db.Execute(TS.ADD, args)); + } /// /// Append new samples to multiple series. @@ -74,45 +90,93 @@ public static TimeStamp TimeSeriesAdd(this IDatabase db, string key, TimeStamp t /// StackExchange.Redis IDatabase instance /// An Collection of (key, timestamp, value) tuples /// List of timestamps of the new samples - public static IReadOnlyList TimeSeriesMAdd(this IDatabase db, IReadOnlyCollection<(string key, TimeStamp timestamp, double value)> sequence) + public static IReadOnlyList TimeSeriesMAdd(this IDatabase db, IReadOnlyCollection<(string key, TsTimeStamp timestamp, double value)> sequence) { var args = BuildTsMaddArgs(sequence); return ParseTimeStampArray(db.Execute(TS.MADD, args)); } + /// + /// Append new samples to multiple series using an automatic timestamp. + /// + /// StackExchange.Redis IDatabase instance + /// An Collection of (key, value) tuples + /// List of timestamps of the new samples + public static IReadOnlyList TimeSeriesMAdd(this IDatabase db, IReadOnlyCollection<(string key, double value)> sequence) + { + var args = BuildTsMaddArgs(sequence); + return ParseTimeStampArray(db.Execute(TS.MADD, args)); + } + + /// + /// Creates a new sample that increments the latest sample's value using an automatic timestamp. + /// + /// StackExchange.Redis IDatabase instance + /// Key name for timeseries + /// Delta to add + /// Optional: Maximum age for samples compared to last event time (in milliseconds) + /// Optional: Collaction of label-value pairs that represent metadata labels of the key + /// Optional: Adding this flag will keep data in an uncompressed form + /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. + /// You can alter the default TSDB chunk size by passing the chunk_size argument (in Bytes) + /// The latests sample timestamp (updated sample) + public static TsTimeStamp TimeSeriesIncrBy(this IDatabase db, string key, double value, long? retentionTime = null, IReadOnlyCollection labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) + { + var args = BuildTsIncrDecrByArgs(key, value, null, retentionTime, labels, uncompressed, chunkSizeBytes); + return ParseTimeStamp(db.Execute(TS.INCRBY, args)); + } + /// /// Creates a new sample that increments the latest sample's value. /// /// StackExchange.Redis IDatabase instance /// Key name for timeseries /// Delta to add - /// Optional: TimeStamp to add. UNIX timestamp of the sample. * can be used for automatic timestamp (using the system clock) + /// TimeStamp to add. UNIX timestamp of the sample. * can be used for automatic timestamp (using the system clock) /// Optional: Maximum age for samples compared to last event time (in milliseconds) /// Optional: Collaction of label-value pairs that represent metadata labels of the key /// Optional: Adding this flag will keep data in an uncompressed form /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. /// You can alter the default TSDB chunk size by passing the chunk_size argument (in Bytes) /// The latests sample timestamp (updated sample) - public static TimeStamp TimeSeriesIncrBy(this IDatabase db, string key, double value, TimeStamp timestamp = null, long? retentionTime = null, IReadOnlyCollection labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) + public static TsTimeStamp TimeSeriesIncrBy(this IDatabase db, string key, double value, TsTimeStamp timestamp, long? retentionTime = null, IReadOnlyCollection labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) { var args = BuildTsIncrDecrByArgs(key, value, timestamp, retentionTime, labels, uncompressed, chunkSizeBytes); return ParseTimeStamp(db.Execute(TS.INCRBY, args)); } + /// + /// Creates a new sample that decrements the latest sample's value using an automatic timestamp. + /// + /// StackExchange.Redis IDatabase instance + /// Key name for timeseries + /// Delta to substract + /// Optional: Maximum age for samples compared to last event time (in milliseconds) + /// Optional: Collaction of label-value pairs that represent metadata labels of the key + /// Optional: Adding this flag will keep data in an uncompressed form + /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. + /// You can alter the default TSDB chunk size by passing the chunk_size argument (in Bytes) + /// The latests sample timestamp (updated sample) + public static TsTimeStamp TimeSeriesDecrBy(this IDatabase db, string key, double value, long? retentionTime = null, IReadOnlyCollection labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) + { + var args = BuildTsIncrDecrByArgs(key, value, null, retentionTime, labels, uncompressed, chunkSizeBytes); + return ParseTimeStamp(db.Execute(TS.DECRBY, args)); + } + /// /// Creates a new sample that decrements the latest sample's value. /// /// StackExchange.Redis IDatabase instance /// Key name for timeseries /// Delta to substract - /// Optional: TimeStamp to add. UNIX timestamp of the sample. * can be used for automatic timestamp (using the system clock) + /// TimeStamp to add. /// Optional: Maximum age for samples compared to last event time (in milliseconds) /// Optional: Collaction of label-value pairs that represent metadata labels of the key /// Optional: Adding this flag will keep data in an uncompressed form /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. /// You can alter the default TSDB chunk size by passing the chunk_size argument (in Bytes) /// The latests sample timestamp (updated sample) - public static TimeStamp TimeSeriesDecrBy(this IDatabase db, string key, double value, TimeStamp timestamp = null, long? retentionTime = null, IReadOnlyCollection labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) + public static TsTimeStamp TimeSeriesDecrBy(this IDatabase db, string key, double value, TsTimeStamp timestamp, long? retentionTime = null, IReadOnlyCollection labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) { var args = BuildTsIncrDecrByArgs(key, value, timestamp, retentionTime, labels, uncompressed, chunkSizeBytes); return ParseTimeStamp(db.Execute(TS.DECRBY, args)); @@ -189,7 +253,7 @@ public static TimeSeriesTuple TimeSeriesGet(this IDatabase db, string key) /// Optional: Aggregation type /// Optional: Time bucket for aggregation in milliseconds /// A list of TimeSeriesTuple - public static IReadOnlyList TimeSeriesRange(this IDatabase db, string key, TimeStamp fromTimeStamp, TimeStamp toTimeStamp, long? count = null, Aggregation aggregation = null, long? timeBucket = null) + public static IReadOnlyList TimeSeriesRange(this IDatabase db, string key, TsTimeStamp fromTimeStamp, TsTimeStamp toTimeStamp, long? count = null, Aggregation aggregation = null, TsTimeBucket? timeBucket = null) { var args = BuildRangeArgs(key, fromTimeStamp, toTimeStamp, count, aggregation, timeBucket); return ParseTimeSeriesTupleArray(db.Execute(TS.RANGE, args)); @@ -206,7 +270,7 @@ public static IReadOnlyList TimeSeriesRange(this IDatabase db, /// Optional: Aggregation type /// Optional: Time bucket for aggregation in milliseconds /// A list of TimeSeriesTuple - public static IReadOnlyList TimeSeriesRevRange(this IDatabase db, string key, TimeStamp fromTimeStamp, TimeStamp toTimeStamp, long? count = null, Aggregation aggregation = null, long? timeBucket = null) + public static IReadOnlyList TimeSeriesRevRange(this IDatabase db, string key, TsTimeStamp fromTimeStamp, TsTimeStamp toTimeStamp, long? count = null, Aggregation aggregation = null, TsTimeBucket? timeBucket = null) { var args = BuildRangeArgs(key, fromTimeStamp, toTimeStamp, count, aggregation, timeBucket); return ParseTimeSeriesTupleArray(db.Execute(TS.REVRANGE, args)); @@ -224,7 +288,7 @@ public static IReadOnlyList TimeSeriesRevRange(this IDatabase d /// Optional: Time bucket for aggregation in milliseconds /// Optional: Include in the reply the label-value pairs that represent metadata labels of the time-series /// A list of <(key, labels, values)> tuples. Each tuple contains the key name, its labels and the values which satisfies the given range and filters. - public static IReadOnlyList<(string key, IReadOnlyList labels, IReadOnlyList values)> TimeSeriesMRange(this IDatabase db, TimeStamp fromTimeStamp, TimeStamp toTimeStamp, IReadOnlyCollection filter, long? count = null, Aggregation aggregation = null, long? timeBucket = null, bool? withLabels = null) + public static IReadOnlyList<(string key, IReadOnlyList labels, IReadOnlyList values)> TimeSeriesMRange(this IDatabase db, TsTimeStamp fromTimeStamp, TsTimeStamp toTimeStamp, IReadOnlyCollection filter, long? count = null, Aggregation aggregation = null, TsTimeBucket? timeBucket = null, bool? withLabels = null) { var args = BuildMultiRangeArgs(fromTimeStamp, toTimeStamp, filter, count, aggregation, timeBucket, withLabels); return ParseMRangeResponse(db.Execute(TS.MRANGE, args)); @@ -242,7 +306,7 @@ public static IReadOnlyList TimeSeriesRevRange(this IDatabase d /// Optional: Time bucket for aggregation in milliseconds /// Optional: Include in the reply the label-value pairs that represent metadata labels of the time-series /// A list of <(key, labels, values)> tuples. Each tuple contains the key name, its labels and the values which satisfies the given range and filters. - public static IReadOnlyList<(string key, IReadOnlyList labels, IReadOnlyList values)> TimeSeriesMRevRange(this IDatabase db, TimeStamp fromTimeStamp, TimeStamp toTimeStamp, IReadOnlyCollection filter, long? count = null, Aggregation aggregation = null, long? timeBucket = null, bool? withLabels = null) + public static IReadOnlyList<(string key, IReadOnlyList labels, IReadOnlyList values)> TimeSeriesMRevRange(this IDatabase db, TsTimeStamp fromTimeStamp, TsTimeStamp toTimeStamp, IReadOnlyCollection filter, long? count = null, Aggregation aggregation = null, TsTimeBucket? timeBucket = null, bool? withLabels = null) { var args = BuildMultiRangeArgs(fromTimeStamp, toTimeStamp, filter, count, aggregation, timeBucket, withLabels); return ParseMRangeResponse(db.Execute(TS.MREVRANGE, args)); diff --git a/NRedisTimeSeries/TimeSeriesClientAsync.cs b/NRedisTimeSeries/TimeSeriesClientAsync.cs index 76bf0aa..11b8a0f 100644 --- a/NRedisTimeSeries/TimeSeriesClientAsync.cs +++ b/NRedisTimeSeries/TimeSeriesClientAsync.cs @@ -61,9 +61,27 @@ public static async Task TimeSeriesAlterAsync(this IDatabase db, string ke /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. /// You can alter the default TSDB chunk size by passing the chunk_size argument (in Bytes) /// The timestamp value of the new sample - public static async Task TimeSeriesAddAsync(this IDatabase db, string key, TimeStamp timestamp, double value, long? retentionTime = null, IReadOnlyCollection labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) + public static async Task TimeSeriesAddAsync(this IDatabase db, string key, TsTimeStamp timestamp, double value, long? retentionTime = null, IReadOnlyCollection labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) { - var args = BuildTsAddArgs(key, timestamp, value, retentionTime, labels, uncompressed, chunkSizeBytes); + var args = BuildTsAddArgs(key, value, retentionTime, labels, uncompressed, chunkSizeBytes, timestamp); + return ParseTimeStamp(await db.ExecuteAsync(TS.ADD, args)); + } + + /// + /// Append (or create and append) a new sample to the series using an automatic timestamp. + /// + /// StackExchange.Redis IDatabase instance + /// Key name for timeseries + /// Numeric data value of the sample. + /// Optional: Maximum age for samples compared to last event time (in milliseconds) + /// Optional: Collaction of label-value pairs that represent metadata labels of the key + /// Optional: Adding this flag will keep data in an uncompressed form + /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. + /// You can alter the default TSDB chunk size by passing the chunk_size argument (in Bytes) + /// The timestamp value of the new sample + public static async Task TimeSeriesAddAsync(this IDatabase db, string key, double value, long? retentionTime = null, IReadOnlyCollection labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) + { + var args = BuildTsAddArgs(key, value, retentionTime, labels, uncompressed, chunkSizeBytes); return ParseTimeStamp(await db.ExecuteAsync(TS.ADD, args)); } @@ -73,45 +91,93 @@ public static async Task TimeSeriesAddAsync(this IDatabase db, string /// StackExchange.Redis IDatabase instance /// An Collection of (key, timestamp, value) tuples /// List of timestamps of the new samples - public static async Task> TimeSeriesMAddAsync(this IDatabase db, IReadOnlyCollection<(string key, TimeStamp timestamp, double value)> sequence) + public static async Task> TimeSeriesMAddAsync(this IDatabase db, IReadOnlyCollection<(string key, TsTimeStamp timestamp, double value)> sequence) { var args = BuildTsMaddArgs(sequence); return ParseTimeStampArray(await db.ExecuteAsync(TS.MADD, args)); } + /// + /// Append new samples to multiple series using an automatic timestamp. + /// + /// StackExchange.Redis IDatabase instance + /// An Collection of (key, value) tuples + /// List of timestamps of the new samples + public static async Task> TimeSeriesMAddAsync(this IDatabase db, IReadOnlyCollection<(string key, double value)> sequence) + { + var args = BuildTsMaddArgs(sequence); + return ParseTimeStampArray(await db.ExecuteAsync(TS.MADD, args)); + } + + /// + /// Creates a new sample that increments the latest sample's value using an automatic timestamp. + /// + /// StackExchange.Redis IDatabase instance + /// Key name for timeseries + /// Delta to add + /// Optional: Maximum age for samples compared to last event time (in milliseconds) + /// Optional: Collaction of label-value pairs that represent metadata labels of the key + /// Optional: Adding this flag will keep data in an uncompressed form + /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. + /// You can alter the default TSDB chunk size by passing the chunk_size argument (in Bytes) + /// The latests sample timestamp (updated sample) + public static async Task TimeSeriesIncrByAsync(this IDatabase db, string key, double value, long? retentionTime = null, IReadOnlyCollection labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) + { + var args = BuildTsIncrDecrByArgs(key, value, null, retentionTime, labels, uncompressed, chunkSizeBytes); + return ParseTimeStamp(await db.ExecuteAsync(TS.INCRBY, args)); + } + /// /// Creates a new sample that increments the latest sample's value. /// /// StackExchange.Redis IDatabase instance /// Key name for timeseries /// Delta to add - /// Optional: TimeStamp to add. UNIX timestamp of the sample. * can be used for automatic timestamp (using the system clock) + /// TimeStamp to add /// Optional: Maximum age for samples compared to last event time (in milliseconds) /// Optional: Collaction of label-value pairs that represent metadata labels of the key /// Optional: Adding this flag will keep data in an uncompressed form /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. /// You can alter the default TSDB chunk size by passing the chunk_size argument (in Bytes) /// The latests sample timestamp (updated sample) - public static async Task TimeSeriesIncrByAsync(this IDatabase db, string key, double value, TimeStamp timestamp = null, long? retentionTime = null, IReadOnlyCollection labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) + public static async Task TimeSeriesIncrByAsync(this IDatabase db, string key, double value, TsTimeStamp timestamp, long? retentionTime = null, IReadOnlyCollection labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) { var args = BuildTsIncrDecrByArgs(key, value, timestamp, retentionTime, labels, uncompressed, chunkSizeBytes); return ParseTimeStamp(await db.ExecuteAsync(TS.INCRBY, args)); } /// - /// Creates a new sample that decrements the latest sample's value. + /// Creates a new sample that decrements the latest sample's value using an automatic timestamp. + /// + /// StackExchange.Redis IDatabase instance + /// Key name for timeseries + /// Delta to substract + /// Optional: Maximum age for samples compared to last event time (in milliseconds) + /// Optional: Collaction of label-value pairs that represent metadata labels of the key + /// Optional: Adding this flag will keep data in an uncompressed form + /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. + /// You can alter the default TSDB chunk size by passing the chunk_size argument (in Bytes) + /// The latests sample timestamp (updated sample) + public static async Task TimeSeriesDecrByAsync(this IDatabase db, string key, double value, long? retentionTime = null, IReadOnlyCollection labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) + { + var args = BuildTsIncrDecrByArgs(key, value, null, retentionTime, labels, uncompressed, chunkSizeBytes); + return ParseTimeStamp(await db.ExecuteAsync(TS.DECRBY, args)); + } + + /// + /// Creates a new sample that decrements the latest sample's value using an automatic timestamp. /// /// StackExchange.Redis IDatabase instance /// Key name for timeseries /// Delta to substract - /// Optional: TimeStamp to add. UNIX timestamp of the sample. * can be used for automatic timestamp (using the system clock) + /// TimeStamp to add /// Optional: Maximum age for samples compared to last event time (in milliseconds) /// Optional: Collaction of label-value pairs that represent metadata labels of the key /// Optional: Adding this flag will keep data in an uncompressed form /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. /// You can alter the default TSDB chunk size by passing the chunk_size argument (in Bytes) /// The latests sample timestamp (updated sample) - public static async Task TimeSeriesDecrByAsync(this IDatabase db, string key, double value, TimeStamp timestamp = null, long? retentionTime = null, IReadOnlyCollection labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) + public static async Task TimeSeriesDecrByAsync(this IDatabase db, string key, double value, TsTimeStamp timestamp, long? retentionTime = null, IReadOnlyCollection labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) { var args = BuildTsIncrDecrByArgs(key, value, timestamp, retentionTime, labels, uncompressed, chunkSizeBytes); return ParseTimeStamp(await db.ExecuteAsync(TS.DECRBY, args)); @@ -188,7 +254,7 @@ public static async Task TimeSeriesGetAsync(this IDatabase db, /// Optional: Aggregation type /// Optional: Time bucket for aggregation in milliseconds /// A list of TimeSeriesTuple - public static async Task> TimeSeriesRangeAsync(this IDatabase db, string key, TimeStamp fromTimeStamp, TimeStamp toTimeStamp, long? count = null, Aggregation aggregation = null, long? timeBucket = null) + public static async Task> TimeSeriesRangeAsync(this IDatabase db, string key, TsTimeStamp fromTimeStamp, TsTimeStamp toTimeStamp, long? count = null, Aggregation aggregation = null, TsTimeBucket? timeBucket = null) { var args = BuildRangeArgs(key, fromTimeStamp, toTimeStamp, count, aggregation, timeBucket); return ParseTimeSeriesTupleArray(await db.ExecuteAsync(TS.RANGE, args)); @@ -205,7 +271,7 @@ public static async Task> TimeSeriesRangeAsync(th /// Optional: Aggregation type /// Optional: Time bucket for aggregation in milliseconds /// A list of TimeSeriesTuple - public static async Task> TimeSeriesRevRangeAsync(this IDatabase db, string key, TimeStamp fromTimeStamp, TimeStamp toTimeStamp, long? count = null, Aggregation aggregation = null, long? timeBucket = null) + public static async Task> TimeSeriesRevRangeAsync(this IDatabase db, string key, TsTimeStamp fromTimeStamp, TsTimeStamp toTimeStamp, long? count = null, Aggregation aggregation = null, TsTimeBucket? timeBucket = null) { var args = BuildRangeArgs(key, fromTimeStamp, toTimeStamp, count, aggregation, timeBucket); return ParseTimeSeriesTupleArray(await db.ExecuteAsync(TS.REVRANGE, args)); @@ -223,7 +289,7 @@ public static async Task> TimeSeriesRevRangeAsync /// Optional: Time bucket for aggregation in milliseconds /// Optional: Include in the reply the label-value pairs that represent metadata labels of the time-series /// A list of <(key, labels, values)> tuples. Each tuple contains the key name, its labels and the values which satisfies the given range and filters. - public static async Task labels, IReadOnlyList values)>> TimeSeriesMRangeAsync(this IDatabase db, TimeStamp fromTimeStamp, TimeStamp toTimeStamp, IReadOnlyCollection filter, long? count = null, Aggregation aggregation = null, long? timeBucket = null, bool? withLabels = null) + public static async Task labels, IReadOnlyList values)>> TimeSeriesMRangeAsync(this IDatabase db, TsTimeStamp fromTimeStamp, TsTimeStamp toTimeStamp, IReadOnlyCollection filter, long? count = null, Aggregation aggregation = null, TsTimeBucket? timeBucket = null, bool? withLabels = null) { var args = BuildMultiRangeArgs(fromTimeStamp, toTimeStamp, filter, count, aggregation, timeBucket, withLabels); return ParseMRangeResponse(await db.ExecuteAsync(TS.MRANGE, args)); @@ -241,7 +307,7 @@ public static async Task> TimeSeriesRevRangeAsync /// Optional: Time bucket for aggregation in milliseconds /// Optional: Include in the reply the label-value pairs that represent metadata labels of the time-series /// A list of <(key, labels, values)> tuples. Each tuple contains the key name, its labels and the values which satisfies the given range and filters. - public static async Task labels, IReadOnlyList values)>> TimeSeriesMRevRangeAsync(this IDatabase db, TimeStamp fromTimeStamp, TimeStamp toTimeStamp, IReadOnlyCollection filter, long? count = null, Aggregation aggregation = null, long? timeBucket = null, bool? withLabels = null) + public static async Task labels, IReadOnlyList values)>> TimeSeriesMRevRangeAsync(this IDatabase db, TsTimeStamp fromTimeStamp, TsTimeStamp toTimeStamp, IReadOnlyCollection filter, long? count = null, Aggregation aggregation = null, TsTimeBucket? timeBucket = null, bool? withLabels = null) { var args = BuildMultiRangeArgs(fromTimeStamp, toTimeStamp, filter, count, aggregation, timeBucket, withLabels); return ParseMRangeResponse(await db.ExecuteAsync(TS.MREVRANGE, args)); diff --git a/NRedisTimeSeries/TimeSeriesClientAux.cs b/NRedisTimeSeries/TimeSeriesClientAux.cs index f7b1ebd..82f4380 100644 --- a/NRedisTimeSeries/TimeSeriesClientAux.cs +++ b/NRedisTimeSeries/TimeSeriesClientAux.cs @@ -55,28 +55,24 @@ private static void AddCount(this IList args, long? count) } } - private static void AddAggregation(this IList args, Aggregation aggregation, long? timeBucket) + private static void AddAggregation(this IList args, Aggregation aggregation, TsTimeBucket timeBucket) { - if(aggregation != null) + if (aggregation != null) { args.Add(CommandArgs.AGGREGATION); args.Add(aggregation.Name); - if (!timeBucket.HasValue) - { - throw new ArgumentException("RANGE Aggregation should have timeBucket value"); - } - args.Add(timeBucket.Value); + args.Add(timeBucket.UnixMilliseconds); } } private static void AddFilters(this List args, IReadOnlyCollection filter) { - if(filter == null || filter.Count == 0) + if (filter == null || filter.Count == 0) { throw new ArgumentException("There should be at least one filter on MRANGE/MREVRANGE"); } args.Add(CommandArgs.FILTER); - foreach(string f in filter) + foreach (string f in filter) { args.Add(f); } @@ -84,18 +80,18 @@ private static void AddFilters(this List args, IReadOnlyCollection args, bool? withLabels) { - if(withLabels.HasValue && withLabels.Value) + if (withLabels.HasValue && withLabels.Value) { args.Add(CommandArgs.WITHLABELS); } } - private static void AddTimeStamp(this IList args, TimeStamp timeStamp) + private static void AddTimeStamp(this IList args, TsTimeStamp? timeStamp) { - if(timeStamp != null) + if (timeStamp != null) { args.Add(CommandArgs.TIMESTAMP); - args.Add(timeStamp.Value); + args.Add(timeStamp?.UnixMilliseconds); } } @@ -104,43 +100,43 @@ private static void AddRule(this IList args, TimeSeriesRule rule) args.Add(rule.DestKey); args.Add(CommandArgs.AGGREGATION); args.Add(rule.Aggregation.Name); - args.Add(rule.TimeBucket); + args.Add(rule.TimeBucket.UnixMilliseconds); } - + private static List BuildTsCreateArgs(string key, long? retentionTime, IReadOnlyCollection labels, bool? uncompressed, long? chunkSizeBytes) { - var args = new List {key}; + var args = new List { key }; args.AddRetentionTime(retentionTime); args.AddChunkSize(chunkSizeBytes); args.AddLabels(labels); args.AddUncompressed(uncompressed); return args; } - + private static List BuildTsAlterArgs(string key, long? retentionTime, IReadOnlyCollection labels) { - var args = new List {key}; + var args = new List { key }; args.AddRetentionTime(retentionTime); args.AddLabels(labels); return args; } - - private static List BuildTsAddArgs(string key, TimeStamp timestamp, double value, long? retentionTime, - IReadOnlyCollection labels, bool? uncompressed, long? chunkSizeBytes) + + private static List BuildTsAddArgs(string key, double value, long? retentionTime, + IReadOnlyCollection labels, bool? uncompressed, long? chunkSizeBytes, TsTimeStamp? timestamp = null) { - var args = new List {key, timestamp.Value, value}; + var args = new List { key, timestamp?.UnixMilliseconds.ToString() ?? "*", value }; AddRetentionTime(args, retentionTime); AddChunkSize(args, chunkSizeBytes); AddLabels(args, labels); AddUncompressed(args, uncompressed); return args; } - - private static List BuildTsIncrDecrByArgs(string key, double value, TimeStamp timestamp, long? retentionTime, + + private static List BuildTsIncrDecrByArgs(string key, double value, TsTimeStamp? timestamp, long? retentionTime, IReadOnlyCollection labels, bool? uncompressed, long? chunkSizeBytes) { - var args = new List {key, value}; + var args = new List { key, value }; args.AddTimeStamp(timestamp); args.AddRetentionTime(retentionTime); args.AddChunkSize(chunkSizeBytes); @@ -149,19 +145,32 @@ private static List BuildTsIncrDecrByArgs(string key, double value, Time return args; } - private static List BuildTsMaddArgs(IReadOnlyCollection<(string key, TimeStamp timestamp, double value)> sequence) + private static List BuildTsMaddArgs(IReadOnlyCollection<(string key, TsTimeStamp timestamp, double value)> sequence) { var args = new List(); - foreach (var tuple in sequence) + foreach (var (key, timestamp, value) in sequence) { - args.Add(tuple.key); - args.Add(tuple.timestamp.Value); - args.Add(tuple.value); + args.Add(key); + args.Add(timestamp.UnixMilliseconds); + args.Add(value); } return args; } - + + private static List BuildTsMaddArgs(IReadOnlyCollection<(string key, double value)> sequence) + { + var args = new List(); + foreach (var (key, value) in sequence) + { + args.Add(key); + args.Add("*"); + args.Add(value); + } + + return args; + } + private static List BuildTsMgetArgs(IReadOnlyCollection filter, bool? withLabels) { var args = new List(); @@ -169,25 +178,37 @@ private static List BuildTsMgetArgs(IReadOnlyCollection filter, AddFilters(args, filter); return args; } - - private static List BuildRangeArgs(string key, TimeStamp fromTimeStamp, TimeStamp toTimeStamp, long? count, - Aggregation aggregation, long? timeBucket) + + private static List BuildRangeArgs(string key, TsTimeStamp fromTimeStamp, TsTimeStamp toTimeStamp, long? count, + Aggregation aggregation, TsTimeBucket? timeBucket) { - var args = new List() - {key, fromTimeStamp.Value, toTimeStamp.Value}; + var args = new List() { key, fromTimeStamp.UnixMilliseconds, toTimeStamp.UnixMilliseconds }; args.AddCount(count); - args.AddAggregation(aggregation, timeBucket); + + if (aggregation != null && !timeBucket.HasValue) + throw new ArgumentException("RANGE Aggregation should have timeBucket value"); + + if (aggregation != null && timeBucket.HasValue) + args.AddAggregation(aggregation, timeBucket.Value); + return args; } - - private static List BuildMultiRangeArgs(TimeStamp fromTimeStamp, TimeStamp toTimeStamp, IReadOnlyCollection filter, - long? count, Aggregation aggregation, long? timeBucket, bool? withLabels) + + private static List BuildMultiRangeArgs(TsTimeStamp fromTimeStamp, TsTimeStamp toTimeStamp, IReadOnlyCollection filter, + long? count, Aggregation aggregation, TsTimeBucket? timeBucket, bool? withLabels) { - var args = new List() {fromTimeStamp.Value, toTimeStamp.Value}; + var args = new List() { fromTimeStamp.UnixMilliseconds, toTimeStamp.UnixMilliseconds }; args.AddCount(count); - args.AddAggregation(aggregation, timeBucket); + + if (aggregation != null && !timeBucket.HasValue) + throw new ArgumentException("RANGE Aggregation should have timeBucket value"); + + if (aggregation != null && timeBucket.HasValue) + args.AddAggregation(aggregation, timeBucket.Value); + args.AddWithLabels(withLabels); args.AddFilters(filter); + return args; } } diff --git a/NRedisTimeSeries/TimeSeriesClientResponseParser.cs b/NRedisTimeSeries/TimeSeriesClientResponseParser.cs index 356b64a..32fd671 100644 --- a/NRedisTimeSeries/TimeSeriesClientResponseParser.cs +++ b/NRedisTimeSeries/TimeSeriesClientResponseParser.cs @@ -13,16 +13,16 @@ private static bool ParseBoolean(RedisResult result) return (string)result == "OK"; } - private static TimeStamp ParseTimeStamp(RedisResult result) + private static TsTimeStamp ParseTimeStamp(RedisResult result) { - if (result.Type == ResultType.None) return null; - return new TimeStamp((long)result); + if (result.Type == ResultType.None) return default; + return new TsTimeStamp((long)result); } - private static IReadOnlyList ParseTimeStampArray(RedisResult result) + private static IReadOnlyList ParseTimeStampArray(RedisResult result) { RedisResult[] redisResults = (RedisResult[])result; - var list = new List(redisResults.Length); + var list = new List(redisResults.Length); if (redisResults.Length == 0) return list; Array.ForEach(redisResults, timestamp => list.Add(ParseTimeStamp(timestamp))); return list; @@ -93,9 +93,9 @@ private static TimeSeriesRule ParseRule(RedisResult result) { RedisResult[] redisResults = (RedisResult[])result; string destKey = (string)redisResults[0]; - long bucketTime = (long)redisResults[1]; + TsTimeBucket timeBucket = new TsTimeBucket((long)redisResults[1]); Aggregation aggregation = (string)redisResults[2]; - return new TimeSeriesRule(destKey, bucketTime, aggregation); + return new TimeSeriesRule(destKey, timeBucket, aggregation); } private static IReadOnlyList ParseRuleArray(RedisResult result) @@ -112,8 +112,8 @@ private static TimeSeriesInformation ParseInfo(RedisResult result) RedisResult[] redisResults = (RedisResult[])result; long totalSamples = (long)redisResults[1]; long memoryUsage = (long)redisResults[3]; - TimeStamp firstTimeStamp = ParseTimeStamp(redisResults[5]); - TimeStamp lastTimeStamp = ParseTimeStamp(redisResults[7]); + TsTimeStamp firstTimeStamp = ParseTimeStamp(redisResults[5]); + TsTimeStamp lastTimeStamp = ParseTimeStamp(redisResults[7]); long retentionTime = (long)redisResults[9]; long chunkCount = (long)redisResults[11]; string chunkSizeProperty = (string)redisResults[12]; @@ -121,7 +121,7 @@ private static TimeSeriesInformation ParseInfo(RedisResult result) // If the property name is maxSamplesPerChunk then this is an old version of RedisTimeSeries and we used the number of samples before ( now Bytes ) if (string.Equals(chunkSizeProperty, "maxSamplesPerChunk")) { - chunkSize = chunkSize * 16; + chunkSize *= 16; } IReadOnlyList labels = ParseLabelArray(redisResults[15]); string destKey = (string)redisResults[17];