diff --git a/src/NRedisStack/TimeSeries/TimeSeriesAux.cs b/src/NRedisStack/TimeSeries/TimeSeriesAux.cs index 2cf7bb28..65ad7c94 100644 --- a/src/NRedisStack/TimeSeries/TimeSeriesAux.cs +++ b/src/NRedisStack/TimeSeries/TimeSeriesAux.cs @@ -300,10 +300,9 @@ public static List BuildRangeArgs(string key, TsBucketTimestamps? bt, bool empty) { - var args = new List() - {key, fromTimeStamp.Value, toTimeStamp.Value}; + var args = new List() { key, fromTimeStamp.Value, toTimeStamp.Value }; args.AddLatest(latest); - if (filterByTs != null) args.AddFilterByTs(filterByTs); + args.AddFilterByTs(filterByTs); args.AddFilterByValue(filterByValue); args.AddCount(count); args.AddAggregation(align, aggregation, timeBucket, bt, empty); @@ -328,6 +327,7 @@ public static List BuildMultiRangeArgs(TimeStamp fromTimeStamp, (string, TsReduce)? groupbyTuple) { var args = new List() { fromTimeStamp.Value, toTimeStamp.Value }; + args.AddLatest(latest); args.AddFilterByTs(filterByTs); args.AddFilterByValue(filterByValue); args.AddWithLabels(withLabels, selectLabels); @@ -338,4 +338,4 @@ public static List BuildMultiRangeArgs(TimeStamp fromTimeStamp, return args; } } -} \ No newline at end of file +} diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMRange.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMRange.cs index cbec11ba..34b9ee38 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMRange.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMRange.cs @@ -8,12 +8,13 @@ namespace NRedisStack.Tests.TimeSeries.TestAPI { public class TestMRange : AbstractNRedisStackTest, 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) { } - private List CreateData(ITimeSeriesCommands ts, int timeBucket) + private List CreateData(ITimeSeriesCommands ts, int timeBucket, string[]? keys = null) { + keys ??= _keys; var tuples = new List(); for (int i = 0; i < 10; i++) @@ -36,17 +37,17 @@ public void TestSimpleMRange() var ts = db.TS(); TimeSeriesLabel label = new TimeSeriesLabel("MRANGEkey", "MRANGEvalue"); var labels = new List { label }; - foreach (string key in keys) + foreach (string key in _keys) { ts.Create(key, labels: labels); } var tuples = CreateData(ts, 50); var results = ts.MRange("-", "+", new List { "MRANGEkey=MRANGEvalue" }); - Assert.Equal(keys.Length, results.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, results[i].values); } @@ -59,17 +60,17 @@ public void TestMRangeWithLabels() var ts = db.TS(); TimeSeriesLabel label = new TimeSeriesLabel("key", "MRangeWithLabels"); var labels = new List { label }; - foreach (string key in keys) + foreach (string key in _keys) { ts.Create(key, labels: labels); } var tuples = CreateData(ts, 50); var results = ts.MRange("-", "+", new List { "key=MRangeWithLabels" }, withLabels: true); - Assert.Equal(keys.Length, results.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(labels, results[i].labels); Assert.Equal(tuples, results[i].values); } @@ -83,9 +84,9 @@ public void TestMRangeSelectLabels() var ts = db.TS(); TimeSeriesLabel label1 = new TimeSeriesLabel("key", "MRangeSelectLabels"); TimeSeriesLabel[] labels = new TimeSeriesLabel[] { new TimeSeriesLabel("team", "CTO"), new TimeSeriesLabel("team", "AUT") }; - for (int i = 0; i < keys.Length; i++) + for (int i = 0; i < _keys.Length; i++) { - ts.Create(keys[i], labels: new List { label1, labels[i] }); + ts.Create(_keys[i], labels: new List { label1, labels[i] }); } var tuples = CreateData(ts, 50); @@ -95,10 +96,10 @@ public void TestMRangeSelectLabels() Assert.Equal("withLabels and selectLabels cannot be specified together.", ex.Message); var results = ts.MRange("-", "+", new List { "key=MRangeSelectLabels" }, selectLabels: new List { "team" }); - Assert.Equal(keys.Length, results.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(labels[i], results[i].labels[0]); Assert.Equal(tuples, results[i].values); } @@ -112,11 +113,11 @@ public void TestMRangeFilter() var ts = db.TS(); TimeSeriesLabel label = new TimeSeriesLabel("key", "MRangeFilter"); var labels = new List { label }; - ts.Create(keys[0], labels: labels); + ts.Create(_keys[0], labels: labels); var tuples = CreateData(ts, 50); var results = ts.MRange("-", "+", 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); } @@ -129,7 +130,7 @@ public void TestMRangeCount() var ts = db.TS(); TimeSeriesLabel label = new TimeSeriesLabel("key", "MRangeCount"); var labels = new List { label }; - foreach (string key in keys) + foreach (string key in _keys) { ts.Create(key, labels: labels); } @@ -137,10 +138,10 @@ public void TestMRangeCount() var tuples = CreateData(ts, 50); long count = 5; var results = ts.MRange("-", "+", new List { "key=MRangeCount" }, count: count); - Assert.Equal(keys.Length, results.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); } @@ -154,17 +155,17 @@ public void TestMRangeAggregation() var ts = db.TS(); TimeSeriesLabel label = new TimeSeriesLabel("key", "MRangeAggregation"); var labels = new List { label }; - foreach (string key in keys) + foreach (string key in _keys) { ts.Create(key, labels: labels); } var tuples = CreateData(ts, 50); var results = ts.MRange("-", "+", new List { "key=MRangeAggregation" }, aggregation: TsAggregation.Min, timeBucket: 50); - Assert.Equal(keys.Length, results.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, results[i].values); } @@ -178,7 +179,7 @@ public void TestMRangeAlign() var ts = db.TS(); TimeSeriesLabel label = new TimeSeriesLabel("key", "MRangeAlign"); var labels = new List { label }; - ts.Create(keys[0], labels: labels); + ts.Create(_keys[0], labels: labels); CreateData(ts, 50); var expected = new List { new TimeSeriesTuple(0,1), @@ -187,7 +188,7 @@ public void TestMRangeAlign() }; var results = ts.MRange(0, "+", new List { "key=MRangeAlign" }, align: "-", aggregation: TsAggregation.Count, timeBucket: 10, count: 3); Assert.Equal(1, results.Count); - Assert.Equal(keys[0], results[0].key); + Assert.Equal(_keys[0], results[0].key); Assert.Equal(expected, results[0].values); results = ts.MRange(1, 500, new List { "key=MRangeAlign" }, align: "+", aggregation: TsAggregation.Count, timeBucket: 10, count: 1); Assert.Equal(expected[1], results[0].values[0]); @@ -201,7 +202,7 @@ public void TestMissingFilter() var ts = db.TS(); TimeSeriesLabel label = new TimeSeriesLabel("key", "MissingFilter"); var labels = new List { label }; - foreach (string key in keys) + foreach (string key in _keys) { ts.Create(key, labels: labels); } @@ -219,7 +220,7 @@ public void TestMissingTimeBucket() var ts = db.TS(); TimeSeriesLabel label = new TimeSeriesLabel("key", "MissingTimeBucket"); var labels = new List { label }; - foreach (string key in keys) + foreach (string key in _keys) { ts.Create(key, labels: labels); } @@ -235,22 +236,22 @@ public void TestMRangeGroupby() IDatabase db = redisFixture.Redis.GetDatabase(); db.Execute("FLUSHALL"); var ts = db.TS(); - for (int i = 0; i < keys.Length; i++) + for (int i = 0; i < _keys.Length; i++) { var label1 = new TimeSeriesLabel("key", "MRangeGroupby"); var label2 = new TimeSeriesLabel("group", i.ToString()); - ts.Create(keys[i], labels: new List { label1, label2 }); + ts.Create(_keys[i], labels: new List { label1, label2 }); } var tuples = CreateData(ts, 50); var results = ts.MRange("-", "+", new List { "key=MRangeGroupby" }, withLabels: true, groupbyTuple: ("group", TsReduce.Min)); - Assert.Equal(keys.Length, results.Count); + Assert.Equal(_keys.Length, results.Count); for (int i = 0; i < results.Count; i++) { Assert.Equal("group=" + i, results[i].key); Assert.Equal(new TimeSeriesLabel("group", i.ToString()), results[i].labels[0]); Assert.Equal(new TimeSeriesLabel("__reducer__", "min"), results[i].labels[1]); - Assert.Equal(new TimeSeriesLabel("__source__", keys[i]), results[i].labels[2]); + Assert.Equal(new TimeSeriesLabel("__source__", _keys[i]), results[i].labels[2]); Assert.Equal(tuples, results[i].values); } } @@ -261,7 +262,7 @@ public void TestMRangeReduce() IDatabase db = redisFixture.Redis.GetDatabase(); db.Execute("FLUSHALL"); var ts = db.TS(); - foreach (var key in keys) + foreach (var key in _keys) { var label = new TimeSeriesLabel("key", "MRangeReduce"); ts.Create(key, labels: new List { label }); @@ -273,7 +274,7 @@ public void TestMRangeReduce() Assert.Equal("key=MRangeReduce", results[0].key); Assert.Equal(new TimeSeriesLabel("key", "MRangeReduce"), results[0].labels[0]); Assert.Equal(new TimeSeriesLabel("__reducer__", "sum"), results[0].labels[1]); - Assert.Equal(new TimeSeriesLabel("__source__", string.Join(",", keys)), results[0].labels[2]); + Assert.Equal(new TimeSeriesLabel("__source__", string.Join(",", _keys)), results[0].labels[2]); for (int i = 0; i < results[0].values.Count; i++) { Assert.Equal(tuples[i].Val * 2, results[0].values[i].Val); @@ -288,7 +289,7 @@ public void TestMRangeFilterBy() var ts = db.TS(); TimeSeriesLabel label = new TimeSeriesLabel("key", "MRangeFilterBy"); var labels = new List { label }; - foreach (string key in keys) + foreach (string key in _keys) { ts.Create(key, labels: labels); } @@ -306,5 +307,36 @@ public void TestMRangeFilterBy() Assert.Equal(tuples.GetRange(0, 1), results[i].values); } } + + [SkipIfRedis(Is.OSSCluster)] + public void TestMRangeLatest() + { + IDatabase db = redisFixture.Redis.GetDatabase(); + db.Execute("FLUSHALL"); + var ts = db.TS(); + var label = new TimeSeriesLabel("key", "MRangeLatest"); + var compactedLabel = new TimeSeriesLabel("compact", "true"); + string primaryTsKey = _keys[0], compactedTsKey = _keys[1]; + var compactionRule = new TimeSeriesRule( + compactedTsKey, + (long)TimeSpan.FromHours(1).TotalMilliseconds, // 1h used to force partial bucket + TsAggregation.Sum); + + ts.Create(primaryTsKey, labels: [label]); + ts.Create(compactedTsKey, labels: [label, compactedLabel]); + ts.CreateRule(primaryTsKey, compactionRule); + var tuples = CreateData(ts, 50, [primaryTsKey]); + + var results = ts.MRange("-", "+", ["key=MRangeLatest", "compact=true"], latest: true); + Assert.Single(results); + Assert.Equal(compactedTsKey, results[0].key); + Assert.NotEmpty(results[0].values); + Assert.Equal(tuples.Sum(x => x.Val), results[0].values.Sum(x => x.Val)); + + results = ts.MRange("-", "+", ["key=MRangeLatest", "compact=true"], latest: false); + Assert.Single(results); + Assert.Equal(compactedTsKey, results[0].key); + Assert.Empty(results[0].values); + } } } \ No newline at end of file