diff --git a/src/NRedisStack/TimeSeries/DataTypes/TSParameters.cs b/src/NRedisStack/TimeSeries/DataTypes/TSParameters.cs new file mode 100644 index 00000000..f70e9629 --- /dev/null +++ b/src/NRedisStack/TimeSeries/DataTypes/TSParameters.cs @@ -0,0 +1,96 @@ +using NRedisStack.DataTypes; +using NRedisStack.Literals.Enums; + +namespace NRedisStack +{ + public class TsBaseParams + { + protected IList parameters; + + internal TsBaseParams() + { + this.parameters = new List(); + } + + internal TsBaseParams(IList parameters) + { + this.parameters = parameters; + } + + internal object[] ToArray(string key) + { + parameters.Insert(0, key); + return parameters.ToArray(); + } + } + + public class TsCreateParams : TsBaseParams + { + internal TsCreateParams(IList parameters) : base(parameters) { } + + internal TsCreateParams(long? retentionTime, IReadOnlyCollection? labels, bool? uncompressed, + long? chunkSizeBytes, TsDuplicatePolicy? policy) + { + parameters.AddRetentionTime(retentionTime); + parameters.AddChunkSize(chunkSizeBytes); + parameters.AddLabels(labels); + parameters.AddUncompressed(uncompressed); + parameters.AddDuplicatePolicy(policy); + } + } + + public class TsAlterParams : TsBaseParams + { + internal TsAlterParams(IList parameters) : base(parameters) { } + + internal TsAlterParams(long? retentionTime, long? chunkSizeBytes, TsDuplicatePolicy? policy, IReadOnlyCollection? labels) + { + parameters.AddRetentionTime(retentionTime); + parameters.AddChunkSize(chunkSizeBytes); + parameters.AddDuplicatePolicy(policy); + parameters.AddLabels(labels); + } + } + + public class TsAddParams : TsBaseParams + { + internal TsAddParams(IList parameters) : base(parameters) { } + + internal TsAddParams(TimeStamp timestamp, double value, long? retentionTime, IReadOnlyCollection? labels, bool? uncompressed, long? chunkSizeBytes, TsDuplicatePolicy? policy) + { + parameters.Add(timestamp.Value); + parameters.Add(value); + parameters.AddRetentionTime(retentionTime); + parameters.AddChunkSize(chunkSizeBytes); + parameters.AddLabels(labels); + parameters.AddUncompressed(uncompressed); + parameters.AddOnDuplicate(policy); + } + } + + public class TsIncrByParams : TsBaseParams + { + internal TsIncrByParams(IList parameters) : base(parameters) { } + + internal TsIncrByParams(double value, TimeStamp? timestampMaybe, long? retentionTime, + IReadOnlyCollection? labels, bool? uncompressed, long? chunkSizeBytes) + { + parameters.Add(value); + if (timestampMaybe is { } timestamp) parameters.AddTimeStamp(timestamp); + parameters.AddRetentionTime(retentionTime); + parameters.AddChunkSize(chunkSizeBytes); + if (labels != null) parameters.AddLabels(labels); + parameters.AddUncompressed(uncompressed); + } + } + + public class TsDecrByParams : TsIncrByParams + { + internal TsDecrByParams(IList parameters) : base(parameters) { } + + internal TsDecrByParams(double value, TimeStamp? timestampMaybe, long? retentionTime, IReadOnlyCollection? labels, bool? uncompressed, long? chunkSizeBytes) + : base(value, timestampMaybe, retentionTime, labels, uncompressed, chunkSizeBytes) + { } + } + +} diff --git a/src/NRedisStack/TimeSeries/Literals/CommandArgs.cs b/src/NRedisStack/TimeSeries/Literals/CommandArgs.cs index 7b17ed4a..2c7df31c 100644 --- a/src/NRedisStack/TimeSeries/Literals/CommandArgs.cs +++ b/src/NRedisStack/TimeSeries/Literals/CommandArgs.cs @@ -23,5 +23,6 @@ internal class TimeSeriesArgs public const string DEBUG = "DEBUG"; public const string BUCKETTIMESTAMP = "BUCKETTIMESTAMP"; public const string EMPTY = "EMPTY"; + public const String IGNORE = "IGNORE"; } } diff --git a/src/NRedisStack/TimeSeries/TimeSeriesAux.cs b/src/NRedisStack/TimeSeries/TimeSeriesAux.cs index 54c20f65..e9c8d870 100644 --- a/src/NRedisStack/TimeSeries/TimeSeriesAux.cs +++ b/src/NRedisStack/TimeSeries/TimeSeriesAux.cs @@ -12,45 +12,6 @@ public static void AddLatest(this IList args, bool latest) if (latest) args.Add(TimeSeriesArgs.LATEST); } - public static void AddRetentionTime(this IList args, long? retentionTime) - { - if (retentionTime.HasValue) - { - args.Add(TimeSeriesArgs.RETENTION); - args.Add(retentionTime); - } - } - - public static void AddChunkSize(this IList args, long? chunkSize) - { - if (chunkSize.HasValue) - { - args.Add(TimeSeriesArgs.CHUNK_SIZE); - args.Add(chunkSize); - } - } - - public static void AddLabels(this IList args, IReadOnlyCollection? labels) - { - if (labels != null) - { - args.Add(TimeSeriesArgs.LABELS); - foreach (var label in labels) - { - args.Add(label.Key); - args.Add(label.Value); - } - } - } - - public static void AddUncompressed(this IList args, bool? uncompressed) - { - if (uncompressed.HasValue) - { - args.Add(TimeSeriesArgs.UNCOMPRESSED); - } - } - public static void AddCount(this IList args, long? count) { if (count.HasValue) @@ -60,25 +21,6 @@ public static void AddCount(this IList args, long? count) } } - public static void AddDuplicatePolicy(this IList args, TsDuplicatePolicy? policy) - { - if (policy.HasValue) - { - args.Add(TimeSeriesArgs.DUPLICATE_POLICY); - args.Add(policy.Value.AsArg()); - } - } - - - public static void AddOnDuplicate(this IList args, TsDuplicatePolicy? policy) - { - if (policy.HasValue) - { - args.Add(TimeSeriesArgs.ON_DUPLICATE); - args.Add(policy.Value.AsArg()); - } - } - public static void AddAlign(this IList args, TimeStamp? alignMaybe) { if (alignMaybe is { } align) @@ -212,53 +154,6 @@ public static void AddRule(this IList args, TimeSeriesRule rule) args.Add(rule.TimeBucket); } - public static List BuildTsCreateArgs(string key, long? retentionTime, IReadOnlyCollection? labels, bool? uncompressed, - long? chunkSizeBytes, TsDuplicatePolicy? policy) - { - var args = new List { key }; - args.AddRetentionTime(retentionTime); - args.AddChunkSize(chunkSizeBytes); - args.AddLabels(labels); - args.AddUncompressed(uncompressed); - args.AddDuplicatePolicy(policy); - return args; - } - - public static List BuildTsAlterArgs(string key, long? retentionTime, long? chunkSizeBytes, - TsDuplicatePolicy? policy, IReadOnlyCollection? labels) - { - var args = new List { key }; - args.AddRetentionTime(retentionTime); - args.AddChunkSize(chunkSizeBytes); - args.AddDuplicatePolicy(policy); - args.AddLabels(labels); - return args; - } - - public static List BuildTsAddArgs(string key, TimeStamp timestamp, double value, long? retentionTime, - IReadOnlyCollection? labels, bool? uncompressed, long? chunkSizeBytes, TsDuplicatePolicy? policy) - { - var args = new List { key, timestamp.Value, value }; - args.AddRetentionTime(retentionTime); - args.AddChunkSize(chunkSizeBytes); - args.AddLabels(labels); - args.AddUncompressed(uncompressed); - args.AddOnDuplicate(policy); - return args; - } - - public static List BuildTsIncrDecrByArgs(string key, double value, TimeStamp? timestampMaybe, long? retentionTime, - IReadOnlyCollection? labels, bool? uncompressed, long? chunkSizeBytes) - { - var args = new List { key, value }; - if (timestampMaybe is { } timestamp) args.AddTimeStamp(timestamp); - args.AddRetentionTime(retentionTime); - args.AddChunkSize(chunkSizeBytes); - if (labels != null) args.AddLabels(labels); - args.AddUncompressed(uncompressed); - return args; - } - public static List BuildTsDelArgs(string key, TimeStamp fromTimeStamp, TimeStamp toTimeStamp) { var args = new List diff --git a/src/NRedisStack/TimeSeries/TimeSeriesCommands.cs b/src/NRedisStack/TimeSeries/TimeSeriesCommands.cs index 3b304b79..4f759524 100644 --- a/src/NRedisStack/TimeSeries/TimeSeriesCommands.cs +++ b/src/NRedisStack/TimeSeries/TimeSeriesCommands.cs @@ -14,6 +14,7 @@ public TimeSeriesCommands(IDatabase db) : base(db) #region Create /// + [Obsolete("Please use the other method with TsCreateParams and check related builder TsCreateParamsBuilder to build parameters.")] public bool Create(string key, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null) { return _db.Execute(TimeSeriesCommandsBuilder.Create(key, retentionTime, labels, @@ -21,18 +22,25 @@ public bool Create(string key, long? retentionTime = null, IReadOnlyCollection + public bool Create(string key, TsCreateParams parameters) => _db.Execute(TimeSeriesCommandsBuilder.Create(key, parameters)).OKtoBoolean(); + #endregion #region Update /// + [Obsolete("Please use the other method with TsAlterParams and check related builder TsAlterParamsBuilder to build parameters.")] public bool Alter(string key, long? retentionTime = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null, IReadOnlyCollection? labels = null) { return _db.Execute(TimeSeriesCommandsBuilder.Alter(key, retentionTime, chunkSizeBytes, duplicatePolicy, labels)).OKtoBoolean(); } + /// + public bool Alter(string key, TsAlterParams parameters) => _db.Execute(TimeSeriesCommandsBuilder.Alter(key, parameters)).OKtoBoolean(); /// + [Obsolete("Please use the other method with TsAddParams and check related builder TsAddParamsBuilder to build parameters.")] public TimeStamp Add(string key, TimeStamp timestamp, double value, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null) @@ -41,6 +49,9 @@ public TimeStamp Add(string key, TimeStamp timestamp, double value, long? retent uncompressed, chunkSizeBytes, duplicatePolicy)).ToTimeStamp(); } + /// + public TimeStamp Add(string key, TsAddParams parameters) => _db.Execute(TimeSeriesCommandsBuilder.Add(key, parameters)).ToTimeStamp(); + /// public IReadOnlyList MAdd(IReadOnlyCollection<(string key, TimeStamp timestamp, double value)> sequence) { @@ -48,6 +59,7 @@ public IReadOnlyList MAdd(IReadOnlyCollection<(string key, TimeStamp } /// + [Obsolete("Please use the other method with TsIncrByParams and check related builder TsIncryByParamsBuilder to build parameters.")] public TimeStamp IncrBy(string key, double value, TimeStamp? timestamp = null, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) { return _db.Execute(TimeSeriesCommandsBuilder.IncrBy(key, value, timestamp, retentionTime, @@ -55,12 +67,19 @@ public TimeStamp IncrBy(string key, double value, TimeStamp? timestamp = null, l } /// + public TimeStamp IncrBy(string key, TsIncrByParams parameters) => _db.Execute(TimeSeriesCommandsBuilder.IncrBy(key, parameters)).ToTimeStamp(); + + /// + [Obsolete("Please use the other method with TsDecrByParams and check related builder TsDecryByParamsBuilder to build parameters.")] public TimeStamp DecrBy(string key, double value, TimeStamp? timestamp = null, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) { return _db.Execute(TimeSeriesCommandsBuilder.DecrBy(key, value, timestamp, retentionTime, labels, uncompressed, chunkSizeBytes)).ToTimeStamp(); } + /// + public TimeStamp DecrBy(string key, TsDecrByParams parameters) => _db.Execute(TimeSeriesCommandsBuilder.DecrBy(key, parameters)).ToTimeStamp(); + /// public long Del(string key, TimeStamp fromTimeStamp, TimeStamp toTimeStamp) { diff --git a/src/NRedisStack/TimeSeries/TimeSeriesCommandsAsync.cs b/src/NRedisStack/TimeSeries/TimeSeriesCommandsAsync.cs index 3a7e1a4b..a6486f48 100644 --- a/src/NRedisStack/TimeSeries/TimeSeriesCommandsAsync.cs +++ b/src/NRedisStack/TimeSeries/TimeSeriesCommandsAsync.cs @@ -14,6 +14,7 @@ public TimeSeriesCommandsAsync(IDatabaseAsync db) #region Create /// + [Obsolete("Please use the other method with TsCreateParams and check related builder TsCreateParamsBuilder to build parameters.")] public async Task CreateAsync(string key, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null) { return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.Create(key, retentionTime, labels, @@ -21,23 +22,34 @@ public async Task CreateAsync(string key, long? retentionTime = null, IRea duplicatePolicy))).OKtoBoolean(); } + /// + public async Task CreateAsync(string key, TsCreateParams parameters) => (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.Create(key, parameters))).OKtoBoolean(); + #endregion #region Update /// + [Obsolete("Please use the other method with TsAlterParams and check related builder TsAlterParamsBuilder to build parameters.")] public async Task AlterAsync(string key, long? retentionTime = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null, IReadOnlyCollection? labels = null) { return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.Alter(key, retentionTime, chunkSizeBytes, duplicatePolicy, labels))).OKtoBoolean(); } /// + public async Task AlterAsync(string key, TsAlterParams parameters) => (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.Alter(key, parameters))).OKtoBoolean(); + + /// + [Obsolete("Please use the other method with TsAddParams and check related builder TsAddParamsBuilder to build parameters.")] public async Task AddAsync(string key, TimeStamp timestamp, double value, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null) { return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.Add(key, timestamp, value, retentionTime, labels, uncompressed, chunkSizeBytes, duplicatePolicy))).ToTimeStamp(); } + /// + public async Task AddAsync(string key, TsAddParams parameters) => (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.Add(key, parameters))).ToTimeStamp(); + /// public async Task> MAddAsync(IReadOnlyCollection<(string key, TimeStamp timestamp, double value)> sequence) { @@ -51,6 +63,12 @@ public async Task IncrByAsync(string key, double value, TimeStamp? ti labels, uncompressed, chunkSizeBytes))).ToTimeStamp(); } + + /// + [Obsolete("Please use the other method with TsIncrByParams and check related builder TsIncryByParamsBuilder to build parameters.")] + public async Task IncrByAsync(string key, TsIncrByParams parameters) => (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.IncrBy(key, parameters))).ToTimeStamp(); + + /// public async Task DecrByAsync(string key, double value, TimeStamp? timestamp = null, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) { @@ -58,6 +76,10 @@ public async Task DecrByAsync(string key, double value, TimeStamp? ti labels, uncompressed, chunkSizeBytes))).ToTimeStamp(); } + /// + [Obsolete("Please use the other method with TsDecrByParams and check related builder TsDecryByParamsBuilder to build parameters.")] + public async Task DecrByAsync(string key, TsDecrByParams parameters) => (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.DecrBy(key, parameters))).ToTimeStamp(); + /// public async Task DelAsync(string key, TimeStamp fromTimeStamp, TimeStamp toTimeStamp) { diff --git a/src/NRedisStack/TimeSeries/TimeSeriesCommandsBuilder.cs b/src/NRedisStack/TimeSeries/TimeSeriesCommandsBuilder.cs index a9ae45a9..b26d3a13 100644 --- a/src/NRedisStack/TimeSeries/TimeSeriesCommandsBuilder.cs +++ b/src/NRedisStack/TimeSeries/TimeSeriesCommandsBuilder.cs @@ -9,28 +9,45 @@ public static class TimeSeriesCommandsBuilder { #region Create + [Obsolete()] public static SerializedCommand Create(string key, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null) { - var args = TimeSeriesAux.BuildTsCreateArgs(key, retentionTime, labels, uncompressed, chunkSizeBytes, duplicatePolicy); - return new SerializedCommand(TS.CREATE, args); + var parameters = new TsCreateParams(retentionTime, labels, uncompressed, chunkSizeBytes, duplicatePolicy); + return new SerializedCommand(TS.CREATE, parameters.ToArray(key)); + } + + public static SerializedCommand Create(string key, TsCreateParams parameters) + { + return new SerializedCommand(TS.CREATE, parameters.ToArray(key)); } #endregion #region Update - + [Obsolete()] public static SerializedCommand Alter(string key, long? retentionTime = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null, IReadOnlyCollection? labels = null) { - var args = TimeSeriesAux.BuildTsAlterArgs(key, retentionTime, chunkSizeBytes, duplicatePolicy, labels); - return new SerializedCommand(TS.ALTER, args); + var parameters = new TsAlterParams(retentionTime, chunkSizeBytes, duplicatePolicy, labels); + return new SerializedCommand(TS.ALTER, parameters.ToArray(key)); } + public static SerializedCommand Alter(string key, TsAlterParams parameters) + { + return new SerializedCommand(TS.ALTER, parameters.ToArray(key)); + } + + [Obsolete()] public static SerializedCommand Add(string key, TimeStamp timestamp, double value, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null) { - var args = TimeSeriesAux.BuildTsAddArgs(key, timestamp, value, retentionTime, labels, uncompressed, chunkSizeBytes, duplicatePolicy); - return new SerializedCommand(TS.ADD, args); + var parameters = new TsAddParams(timestamp, value, retentionTime, labels, uncompressed, chunkSizeBytes, duplicatePolicy); + return new SerializedCommand(TS.ADD, parameters.ToArray(key)); + } + + public static SerializedCommand Add(string key, TsAddParams parameters) + { + return new SerializedCommand(TS.ADD, parameters.ToArray(key)); } public static SerializedCommand MAdd(IReadOnlyCollection<(string key, TimeStamp timestamp, double value)> sequence) @@ -39,16 +56,28 @@ public static SerializedCommand MAdd(IReadOnlyCollection<(string key, TimeStamp return new SerializedCommand(TS.MADD, args); } + [Obsolete()] public static SerializedCommand IncrBy(string key, double value, TimeStamp? timestamp = null, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) { - var args = TimeSeriesAux.BuildTsIncrDecrByArgs(key, value, timestamp, retentionTime, labels, uncompressed, chunkSizeBytes); - return new SerializedCommand(TS.INCRBY, args); + var parameters = new TsIncrByParams(value, timestamp, retentionTime, labels, uncompressed, chunkSizeBytes); + return new SerializedCommand(TS.INCRBY, parameters.ToArray(key)); + } + + public static SerializedCommand IncrBy(string key, TsIncrByParams parameters) + { + return new SerializedCommand(TS.INCRBY, parameters.ToArray(key)); } + [Obsolete()] public static SerializedCommand DecrBy(string key, double value, TimeStamp? timestamp = null, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) { - var args = TimeSeriesAux.BuildTsIncrDecrByArgs(key, value, timestamp, retentionTime, labels, uncompressed, chunkSizeBytes); - return (new SerializedCommand(TS.DECRBY, args)); + var parameters = new TsDecrByParams(value, timestamp, retentionTime, labels, uncompressed, chunkSizeBytes); + return new SerializedCommand(TS.DECRBY, parameters.ToArray(key)); + } + + public static SerializedCommand DecrBy(string key, TsDecrByParams parameters) + { + return new SerializedCommand(TS.DECRBY, parameters.ToArray(key)); } public static SerializedCommand Del(string key, TimeStamp fromTimeStamp, TimeStamp toTimeStamp) diff --git a/src/NRedisStack/TimeSeries/TimeSeriesParamsBuilder.cs b/src/NRedisStack/TimeSeries/TimeSeriesParamsBuilder.cs new file mode 100644 index 00000000..c9345d04 --- /dev/null +++ b/src/NRedisStack/TimeSeries/TimeSeriesParamsBuilder.cs @@ -0,0 +1,246 @@ +using NRedisStack.Literals; +using NRedisStack.Literals.Enums; +using NRedisStack.DataTypes; +using System.Collections.ObjectModel; +using NRedisStack.Extensions; + +namespace NRedisStack +{ + + public abstract class TsBaseParamsBuilder where T : TsBaseParamsBuilder + { + internal protected long? retentionTime; + internal protected IReadOnlyCollection? labels; + internal protected long? chunkSizeBytes; + internal protected long? ignoreMaxTimeDiff; + internal protected long? ignoreMaxValDiff; + + + internal protected double? value; + internal protected TimeStamp? timestamp; + internal protected bool? uncompressed; + internal protected TsDuplicatePolicy? duplicatePolicy; + + internal TsBaseParamsBuilder() + { } + + public T AddRetentionTime(long retentionTime) + { + this.retentionTime = retentionTime; + return (T)this; + } + public T AddLabels(ReadOnlyCollection labels) + { + this.labels = labels; + return (T)this; + } + public T AddChunkSizeBytes(long chunkSizeBytes) + { + this.chunkSizeBytes = chunkSizeBytes; + return (T)this; + } + + public T AddIgnoreValues(long ignoreMaxTimeDiff, long ignoreMaxValDiff) + { + this.ignoreMaxTimeDiff = ignoreMaxTimeDiff; + this.ignoreMaxValDiff = ignoreMaxValDiff; + return (T)this; + } + + protected T AddValue(double value) + { + this.value = value; + return (T)this; + } + + protected T AddTimestamp(TimeStamp timestamp) + { + this.timestamp = timestamp; + return (T)this; + } + + protected T AddUncompressed(bool uncompressed) + { + this.uncompressed = uncompressed; + return (T)this; + } + + protected T AddDuplicatePolicy(TsDuplicatePolicy duplicatePolicy) + { + this.duplicatePolicy = duplicatePolicy; + return (T)this; + } + + } + + public static class TsParamsHelper + { + public static void AddRetentionTime(this IList args, long? retentionTime) + { + if (retentionTime.HasValue) + { + args.Add(TimeSeriesArgs.RETENTION); + args.Add(retentionTime); + } + } + + public static void AddChunkSize(this IList args, long? chunkSize) + { + if (chunkSize.HasValue) + { + args.Add(TimeSeriesArgs.CHUNK_SIZE); + args.Add(chunkSize); + } + } + + public static void AddLabels(this IList args, IReadOnlyCollection? labels) + { + if (labels != null) + { + args.Add(TimeSeriesArgs.LABELS); + foreach (var label in labels) + { + args.Add(label.Key); + args.Add(label.Value); + } + } + } + + public static void AddUncompressed(this IList args, bool? uncompressed) + { + if (uncompressed.HasValue) + { + args.Add(TimeSeriesArgs.UNCOMPRESSED); + } + } + + public static void AddIgnoreValues(this IList args, long? ignoreMaxTimeDiff, long? ignoreMaxValDiff) + { + if (ignoreMaxTimeDiff != null || ignoreMaxValDiff != null) + { + args.Add(TimeSeriesArgs.IGNORE); + args.Add(ignoreMaxTimeDiff ?? 0); + args.Add(ignoreMaxValDiff ?? 0); + } + } + + public static void AddDuplicatePolicy(this IList args, TsDuplicatePolicy? policy) + { + if (policy.HasValue) + { + args.Add(TimeSeriesArgs.DUPLICATE_POLICY); + args.Add(policy.Value.AsArg()); + } + } + + public static void AddOnDuplicate(this IList args, TsDuplicatePolicy? policy) + { + if (policy.HasValue) + { + args.Add(TimeSeriesArgs.ON_DUPLICATE); + args.Add(policy.Value.AsArg()); + } + } + } + + public class TsCreateParamsBuilder : TsBaseParamsBuilder + { + public TsCreateParams build() + { + var args = new List(); + args.AddRetentionTime(retentionTime); + args.AddChunkSize(chunkSizeBytes); + args.AddLabels(labels); + args.AddUncompressed(uncompressed); + args.AddDuplicatePolicy(duplicatePolicy); + args.AddIgnoreValues(ignoreMaxTimeDiff, ignoreMaxValDiff); + return new TsCreateParams(args); + } + + public TsCreateParamsBuilder AddUncompressed(bool uncompressed) => base.AddUncompressed(uncompressed); + public TsCreateParamsBuilder AddDuplicatePolicy(TsDuplicatePolicy duplicatePolicy) => base.AddDuplicatePolicy(duplicatePolicy); + + } + + public class TsAlterParamsBuilder : TsBaseParamsBuilder + { + public TsAlterParams build() + { + var args = new List(); + args.AddRetentionTime(retentionTime); + args.AddChunkSize(chunkSizeBytes); + args.AddDuplicatePolicy(duplicatePolicy); + args.AddLabels(labels); + args.AddIgnoreValues(ignoreMaxTimeDiff, ignoreMaxValDiff); + return new TsAlterParams(args); + } + + public TsAlterParamsBuilder AddDuplicatePolicy(TsDuplicatePolicy duplicatePolicy) => base.AddDuplicatePolicy(duplicatePolicy); + } + + public class TsAddParamsBuilder : TsBaseParamsBuilder + { + public TsAddParams build() + { + if (timestamp == null) throw new NotSupportedException("Operation without 'timestamp' is not supported!"); + if (value == null) throw new NotSupportedException("Operation without 'value' is not supported!"); + + var args = new List { timestamp.Value.Value, value }; + args.AddRetentionTime(retentionTime); + args.AddChunkSize(chunkSizeBytes); + args.AddLabels(labels); + args.AddUncompressed(uncompressed); + args.AddOnDuplicate(duplicatePolicy); + args.AddIgnoreValues(ignoreMaxTimeDiff, ignoreMaxValDiff); + return new TsAddParams(args); + } + + public TsAddParamsBuilder AddValue(double value) => base.AddValue(value); + public TsAddParamsBuilder AddTimestamp(TimeStamp timestamp) => base.AddTimestamp(timestamp); + public TsAddParamsBuilder AddUncompressed(bool uncompressed) => base.AddUncompressed(uncompressed); + public TsAddParamsBuilder AddOnDuplicate(TsDuplicatePolicy duplicatePolicy) => base.AddDuplicatePolicy(duplicatePolicy); + } + + public class TsIncrByParamsBuilder : TsBaseParamsBuilder + { + public TsIncrByParams build() + { + if (value == null) throw new NotSupportedException("Operation without 'value' is not supported!"); + + var args = new List { value }; + if (timestamp != null) args.AddTimeStamp(timestamp.Value); + args.AddRetentionTime(retentionTime); + args.AddChunkSize(chunkSizeBytes); + if (labels != null) args.AddLabels(labels); + args.AddUncompressed(uncompressed); + args.AddIgnoreValues(ignoreMaxTimeDiff, ignoreMaxValDiff); + return new TsIncrByParams(args); + } + + public TsIncrByParamsBuilder AddValue(double value) => base.AddValue(value); + public TsIncrByParamsBuilder AddTimestamp(TimeStamp timestamp) => base.AddTimestamp(timestamp); + public TsIncrByParamsBuilder AddUncompressed(bool uncompressed) => base.AddUncompressed(uncompressed); + public TsIncrByParamsBuilder AddDuplicatePolicy(TsDuplicatePolicy duplicatePolicy) => base.AddDuplicatePolicy(duplicatePolicy); + } + + public class TsDecrByParamsBuilder : TsBaseParamsBuilder + { + public TsDecrByParams build() + { + if (value == null) throw new NotSupportedException("Operation without 'value' is not supported!"); + + var args = new List { value }; + if (timestamp != null) args.AddTimeStamp(timestamp.Value); + args.AddRetentionTime(retentionTime); + args.AddChunkSize(chunkSizeBytes); + if (labels != null) args.AddLabels(labels); + args.AddUncompressed(uncompressed); + args.AddIgnoreValues(ignoreMaxTimeDiff, ignoreMaxValDiff); + return new TsDecrByParams(args); + } + public TsDecrByParamsBuilder AddValue(double value) => base.AddValue(value); + public TsDecrByParamsBuilder AddTimestamp(TimeStamp timestamp) => base.AddTimestamp(timestamp); + public TsDecrByParamsBuilder AddUncompressed(bool uncompressed) => base.AddUncompressed(uncompressed); + public TsDecrByParamsBuilder AddDuplicatePolicy(TsDuplicatePolicy duplicatePolicy) => base.AddDuplicatePolicy(duplicatePolicy); + } +} \ No newline at end of file diff --git a/tests/NRedisStack.Tests/Search/SearchTests.cs b/tests/NRedisStack.Tests/Search/SearchTests.cs index 0376a54c..86ae7304 100644 --- a/tests/NRedisStack.Tests/Search/SearchTests.cs +++ b/tests/NRedisStack.Tests/Search/SearchTests.cs @@ -702,7 +702,7 @@ public void AlterAdd() IDatabase db = redisFixture.Redis.GetDatabase(); db.Execute("FLUSHALL"); var ft = db.FT(); - Schema sc = new Schema().AddTextField("title", 1.0); + Schema sc = new Schema().AddTextField("title", 1.0, sortable: true, unf: true); Assert.True(ft.Create(index, FTCreateParams.CreateParams(), sc)); diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAdd.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAdd.cs index 804eda42..a7f40554 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAdd.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAdd.cs @@ -229,5 +229,24 @@ public void TestWrongParameters() ex = Assert.Throws(() => ts.Add(key, "-", value)); Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); } + + [SkipIfRedis(Comparison.LessThan, "7.4.0")] + public void TestAddAndIgnoreValues() + { + IDatabase db = redisFixture.Redis.GetDatabase(); + db.Execute("FLUSHALL"); + var ts = db.TS(); + var parameters = new TsAddParamsBuilder().AddTimestamp(101).AddValue(102).AddIgnoreValues(15, 16).build(); + ts.Add(key, parameters); + + int j = -1, k = -1; + RedisResult info = TimeSeriesHelper.getInfo(db, key, out j, out k); + Assert.NotNull(info); + Assert.True(info.Length > 0); + Assert.NotEqual(j, -1); + Assert.NotEqual(k, -1); + Assert.Equal(15, (long)info[j + 1]); + Assert.Equal(16, (long)info[k + 1]); + } } } diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAlter.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAlter.cs index 281518b4..befd8b98 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAlter.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAlter.cs @@ -59,5 +59,25 @@ public void TestAlterPolicyAndChunk() Assert.Equal(128, info.ChunkSize); Assert.Equal(TsDuplicatePolicy.MIN, info.DuplicatePolicy); } + + [SkipIfRedis(Comparison.LessThan, "7.4.0")] + public void TestAlterAndIgnoreValues() + { + IDatabase db = redisFixture.Redis.GetDatabase(); + db.Execute("FLUSHALL"); + var ts = db.TS(); + ts.Create(key, new TsCreateParamsBuilder().build()); + var parameters = new TsAlterParamsBuilder().AddIgnoreValues(13, 14).build(); + Assert.True(ts.Alter(key, parameters)); + + int j = -1, k = -1; + RedisResult info = TimeSeriesHelper.getInfo(db, key, out j, out k); + Assert.NotNull(info); + Assert.True(info.Length > 0); + Assert.NotEqual(j, -1); + Assert.NotEqual(k, -1); + Assert.Equal(13, (long)info[j + 1]); + Assert.Equal(14, (long)info[k + 1]); + } } } diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestCreate.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestCreate.cs index 317235af..69a9c263 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestCreate.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestCreate.cs @@ -3,6 +3,7 @@ using NRedisStack.RedisStackCommands; using NRedisStack.Literals.Enums; using Xunit; +using System.Runtime.CompilerServices; namespace NRedisStack.Tests.TimeSeries.TestAPI { @@ -117,5 +118,23 @@ public void TestCreatehDuplicatePolicySum() var ts = db.TS(); Assert.True(ts.Create(key, duplicatePolicy: TsDuplicatePolicy.SUM)); } + + [SkipIfRedis(Comparison.LessThan, "7.4.0")] + public void TestCreateAndIgnoreValues() + { + IDatabase db = redisFixture.Redis.GetDatabase(); + db.Execute("FLUSHALL"); + var ts = db.TS(); + var parameters = new TsCreateParamsBuilder().AddIgnoreValues(11, 12).build(); + Assert.True(ts.Create(key, parameters)); + + int j = -1, k = -1; + RedisResult info = TimeSeriesHelper.getInfo(db, key, out j, out k); + + Assert.NotEqual(j, -1); + Assert.NotEqual(k, -1); + Assert.Equal(11, (long)info[j + 1]); + Assert.Equal(12, (long)info[k + 1]); + } } } diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestDecrBy.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestDecrBy.cs index 14e54e6c..52d516c7 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestDecrBy.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestDecrBy.cs @@ -100,5 +100,24 @@ public void TestWrongParameters() ex = Assert.Throws(() => ts.DecrBy(key, value, timestamp: "-")); Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); } + + [SkipIfRedis(Comparison.LessThan, "7.4.0")] + public async void TestIncrDecryByAndIgnoreValues() + { + IDatabase db = redisFixture.Redis.GetDatabase(); + db.Execute("FLUSHALL"); + var ts = db.TS(); + var decrParameters = new TsDecrByParamsBuilder().AddValue(1).AddIgnoreValues(15, 16).build(); + ts.DecrBy(key, decrParameters); + + int j = -1, k = -1; + RedisResult info = TimeSeriesHelper.getInfo(db, key, out j, out k); + Assert.NotNull(info); + Assert.True(info.Length > 0); + Assert.NotEqual(j, -1); + Assert.NotEqual(k, -1); + Assert.Equal(15, (long)info[j + 1]); + Assert.Equal(16, (long)info[k + 1]); + } } } diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestIncrBy.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestIncrBy.cs index af1d35bf..2b6bc8c7 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestIncrBy.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestIncrBy.cs @@ -100,5 +100,24 @@ public void TestWrongParameters() ex = Assert.Throws(() => ts.IncrBy(key, value, timestamp: "-")); Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); } + + [SkipIfRedis(Comparison.LessThan, "7.4.0")] + public async void TestIncrByAndIgnoreValues() + { + IDatabase db = redisFixture.Redis.GetDatabase(); + db.Execute("FLUSHALL"); + var ts = db.TS(); + var incrParameters = new TsIncrByParamsBuilder().AddValue(1).AddIgnoreValues(15, 16).build(); + ts.IncrBy(key, incrParameters); + + int j = -1, k = -1; + RedisResult info = TimeSeriesHelper.getInfo(db, key, out j, out k); + Assert.NotNull(info); + Assert.True(info.Length > 0); + Assert.NotEqual(j, -1); + Assert.NotEqual(k, -1); + Assert.Equal(15, (long)info[j + 1]); + Assert.Equal(16, (long)info[k + 1]); + } } } diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TimeSeriesHelper.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TimeSeriesHelper.cs new file mode 100644 index 00000000..4cef7208 --- /dev/null +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TimeSeriesHelper.cs @@ -0,0 +1,23 @@ +using StackExchange.Redis; +using NRedisStack.RedisStackCommands; + +namespace NRedisStack.Tests.TimeSeries.TestAPI +{ + public class TimeSeriesHelper + { + public static RedisResult getInfo(IDatabase db, string key, out int j, out int k) + { + var cmd = new SerializedCommand("TS.INFO", key); + RedisResult info = db.Execute(cmd); + + j = -1; + k = -1; + for (int i = 0; i < info.Length; i++) + { + if (info[i].ToString().Equals("ignoreMaxTimeDiff")) j = i; + if (info[i].ToString().Equals("ignoreMaxValDiff")) k = i; + } + return info; + } + } +}