diff --git a/src/NRedisStack.Core/Auxiliary.cs b/src/NRedisStack.Core/Auxiliary.cs index 540aa8d1..2e4b53e5 100644 --- a/src/NRedisStack.Core/Auxiliary.cs +++ b/src/NRedisStack.Core/Auxiliary.cs @@ -4,7 +4,7 @@ namespace NRedisStack.Core { public static class Auxiliary { - public static List MergeArgs(RedisKey key, RedisValue[] items) + public static List MergeArgs(RedisKey key, params RedisValue[] items) { var args = new List { key }; foreach (var item in items) args.Add(item); diff --git a/src/NRedisStack.Core/Bloom/BloomCommands.cs b/src/NRedisStack.Core/Bloom/BloomCommands.cs index 21b1c845..a121a6e0 100644 --- a/src/NRedisStack.Core/Bloom/BloomCommands.cs +++ b/src/NRedisStack.Core/Bloom/BloomCommands.cs @@ -70,7 +70,7 @@ public async Task ExistsAsync(RedisKey key, RedisValue item) /// Name of the key to return information about. /// Information of the filter. /// - public BloomInformation? Info(RedisKey key) + public BloomInformation Info(RedisKey key) { var info = _db.Execute(BF.INFO, key); return ResponseParser.ToBloomInfo(info); @@ -82,7 +82,7 @@ public async Task ExistsAsync(RedisKey key, RedisValue item) /// Name of the key to return information about. /// Information of the filter. /// - public async Task InfoAsync(RedisKey key) + public async Task InfoAsync(RedisKey key) { var info = await _db.ExecuteAsync(BF.INFO, key); return ResponseParser.ToBloomInfo(info); @@ -108,8 +108,8 @@ public async Task ExistsAsync(RedisKey key, RedisValue item) double? error = null, int? expansion = null, bool nocreate = false, bool nonscaling = false) { - if (items == null) - throw new ArgumentNullException(nameof(items)); + if (items.Length < 1) + throw new ArgumentOutOfRangeException(nameof(items)); List args = new List { key }; @@ -119,6 +119,7 @@ public async Task ExistsAsync(RedisKey key, RedisValue item) args.Add(capacity); } + if (error != null) { args.Add(BloomArgs.ERROR); @@ -171,8 +172,8 @@ public async Task ExistsAsync(RedisKey key, RedisValue item) double? error = null, int? expansion = null, bool nocreate = false, bool nonscaling = false) { - if (items == null) - throw new ArgumentNullException(nameof(items)); + if (items.Length < 1) + throw new ArgumentOutOfRangeException(nameof(items)); List args = new List { key }; @@ -221,11 +222,11 @@ public async Task ExistsAsync(RedisKey key, RedisValue item) /// Name of the key to restore. /// Iterator value associated with data (returned by SCANDUMP). /// Current data chunk (returned by SCANDUMP). - /// Array with information of the filter. + /// if executed correctly, error otherwise/> /// public bool LoadChunk(RedisKey key, long iterator, Byte[] data) { - return ResponseParser.ParseOKtoBoolean(_db.Execute(BF.LOADCHUNK, key, iterator, data)); + return ResponseParser.OKtoBoolean(_db.Execute(BF.LOADCHUNK, key, iterator, data)); } /// @@ -234,12 +235,12 @@ public bool LoadChunk(RedisKey key, long iterator, Byte[] data) /// Name of the key to restore. /// Iterator value associated with data (returned by SCANDUMP). /// Current data chunk (returned by SCANDUMP). - /// Array with information of the filter. + /// if executed correctly, error otherwise/> /// public async Task LoadChunkAsync(RedisKey key, long iterator, Byte[] data) { var result = await _db.ExecuteAsync(BF.LOADCHUNK, key, iterator, data); - return ResponseParser.ParseOKtoBoolean(result); + return ResponseParser.OKtoBoolean(result); } /// @@ -250,10 +251,10 @@ public async Task LoadChunkAsync(RedisKey key, long iterator, Byte[] data) /// An array of booleans. Each element is either true or false depending on whether the /// corresponding input element was newly added to the filter or may have previously existed. /// - public bool[] MAdd(RedisKey key, RedisValue[] items) + public bool[] MAdd(RedisKey key, params RedisValue[] items) { - if (items == null) - throw new ArgumentNullException(nameof(items)); + if (items.Length < 1) + throw new ArgumentOutOfRangeException(nameof(items)); List args = new List { key }; @@ -273,10 +274,10 @@ public bool[] MAdd(RedisKey key, RedisValue[] items) /// An array of booleans. Each element is either true or false depending on whether the /// corresponding input element was newly added to the filter or may have previously existed. /// - public async Task MAddAsync(RedisKey key, RedisValue[] items) + public async Task MAddAsync(RedisKey key, params RedisValue[] items) { - if (items == null) - throw new ArgumentNullException(nameof(items)); + if (items.Length < 1) + throw new ArgumentOutOfRangeException(nameof(items)); List args = new List { key }; @@ -299,8 +300,8 @@ public async Task MAddAsync(RedisKey key, RedisValue[] items) /// public bool[] MExists(RedisKey key, RedisValue[] items) { - if (items == null) - throw new ArgumentNullException(nameof(items)); + if (items.Length < 1) + throw new ArgumentOutOfRangeException(nameof(items)); List args = new List { key }; @@ -323,8 +324,8 @@ public bool[] MExists(RedisKey key, RedisValue[] items) /// public async Task MExistsAsync(RedisKey key, RedisValue[] items) { - if (items == null) - throw new ArgumentNullException(nameof(items)); + if (items.Length < 1) + throw new ArgumentOutOfRangeException(nameof(items)); List args = new List { key }; @@ -348,7 +349,7 @@ public async Task MExistsAsync(RedisKey key, RedisValue[] items) /// created in size of the last sub-filter multiplied by expansion. /// (Optional) toprevent the filter /// from creating additional sub-filters if initial capacity is reached. - /// if executed correctly, otherwise. + /// if executed correctly, error otherwise/> /// public bool Reserve(RedisKey key, double errorRate, long capacity, int? expansion = null, bool nonscaling = false) @@ -365,7 +366,7 @@ public bool Reserve(RedisKey key, double errorRate, long capacity, args.Add(BloomArgs.NONSCALING); } - return ResponseParser.ParseOKtoBoolean(_db.Execute(BF.RESERVE, args)); + return ResponseParser.OKtoBoolean(_db.Execute(BF.RESERVE, args)); } /// @@ -378,7 +379,7 @@ public bool Reserve(RedisKey key, double errorRate, long capacity, /// created in size of the last sub-filter multiplied by expansion. /// (Optional) toprevent the filter /// from creating additional sub-filters if initial capacity is reached. - /// if executed correctly, otherwise. + /// if executed correctly, Error otherwise. /// public async Task ReserveAsync(RedisKey key, double errorRate, long capacity, int? expansion = null, bool nonscaling = false) @@ -396,7 +397,7 @@ public async Task ReserveAsync(RedisKey key, double errorRate, long capaci } var result = await _db.ExecuteAsync(BF.RESERVE, args); - return ResponseParser.ParseOKtoBoolean(result); + return ResponseParser.OKtoBoolean(result); } /// @@ -406,7 +407,7 @@ public async Task ReserveAsync(RedisKey key, double errorRate, long capaci /// Iterator value; either 0 or the iterator from a previous invocation of this command. /// Tuple of iterator and data. /// - public Tuple? ScanDump(RedisKey key, long iterator) + public Tuple ScanDump(RedisKey key, long iterator) { return ResponseParser.ToScanDumpTuple(_db.Execute(BF.SCANDUMP, key, iterator)); } @@ -418,7 +419,7 @@ public async Task ReserveAsync(RedisKey key, double errorRate, long capaci /// Iterator value; either 0 or the iterator from a previous invocation of this command. /// Tuple of iterator and data. /// - public async Task?> ScanDumpAsync(RedisKey key, long iterator) + public async Task> ScanDumpAsync(RedisKey key, long iterator) { var result = await _db.ExecuteAsync(BF.SCANDUMP, key, iterator); return ResponseParser.ToScanDumpTuple(result); diff --git a/src/NRedisStack.Core/CountMinSketch/CmsCommands.cs b/src/NRedisStack.Core/CountMinSketch/CmsCommands.cs index d20ad077..4c5d42e6 100644 --- a/src/NRedisStack.Core/CountMinSketch/CmsCommands.cs +++ b/src/NRedisStack.Core/CountMinSketch/CmsCommands.cs @@ -47,7 +47,7 @@ public async Task IncrByAsync(RedisKey key, RedisValue item, long incremen /// and the Amount by which the item counter is to be increased. /// Count of each item after increment. /// - public long[]? IncrBy(RedisKey key, Tuple[] itemIncrements) + public long[] IncrBy(RedisKey key, Tuple[] itemIncrements) { if (itemIncrements.Length < 1) throw new ArgumentException(nameof(itemIncrements)); @@ -69,7 +69,7 @@ public async Task IncrByAsync(RedisKey key, RedisValue item, long incremen /// and the Amount by which the item counter is to be increased. /// Count of each item after increment. /// - public async Task IncrByAsync(RedisKey key, Tuple[] itemIncrements) + public async Task IncrByAsync(RedisKey key, Tuple[] itemIncrements) { if (itemIncrements.Length < 1) throw new ArgumentException(nameof(itemIncrements)); @@ -91,7 +91,7 @@ public async Task IncrByAsync(RedisKey key, RedisValue item, long incremen /// Name of the key to return information about. /// Information of the sketch. /// - public CmsInformation? Info(RedisKey key) + public CmsInformation Info(RedisKey key) { var info = _db.Execute(CMS.INFO, key); return ResponseParser.ToCmsInfo(info); @@ -103,13 +103,12 @@ public async Task IncrByAsync(RedisKey key, RedisValue item, long incremen /// Name of the key to return information about. /// Information of the sketch. /// - public async Task InfoAsync(RedisKey key) + public async Task InfoAsync(RedisKey key) { var info = await _db.ExecuteAsync(CMS.INFO, key); return ResponseParser.ToCmsInfo(info); } - //TODO: functions that returns OK cannot return false, they return OK or ERROR. fix this (the Redis functions that can return also false - will return 1 for true ans 0 for false) /// /// Initializes a Count-Min Sketch to dimensions specified by user. /// @@ -121,7 +120,7 @@ public async Task IncrByAsync(RedisKey key, RedisValue item, long incremen /// public bool InitByDim(RedisKey key, long width, long depth) { - return ResponseParser.ParseOKtoBoolean(_db.Execute(CMS.INITBYDIM, key, width, depth)); + return ResponseParser.OKtoBoolean(_db.Execute(CMS.INITBYDIM, key, width, depth)); } /// @@ -136,7 +135,7 @@ public bool InitByDim(RedisKey key, long width, long depth) public async Task InitByDimAsync(RedisKey key, long width, long depth) { var result = await _db.ExecuteAsync(CMS.INITBYDIM, key, width, depth); - return ResponseParser.ParseOKtoBoolean(result); + return ResponseParser.OKtoBoolean(result); } /// @@ -149,7 +148,7 @@ public async Task InitByDimAsync(RedisKey key, long width, long depth) /// public bool InitByProb(RedisKey key, double error, double probability) { - return ResponseParser.ParseOKtoBoolean(_db.Execute(CMS.INITBYPROB, key, error, probability)); + return ResponseParser.OKtoBoolean(_db.Execute(CMS.INITBYPROB, key, error, probability)); } /// @@ -163,7 +162,7 @@ public bool InitByProb(RedisKey key, double error, double probability) public async Task InitByProbAsync(RedisKey key, double error, double probability) { var result = await _db.ExecuteAsync(CMS.INITBYPROB, key, error, probability); - return ResponseParser.ParseOKtoBoolean(result); + return ResponseParser.OKtoBoolean(result); } /// @@ -178,7 +177,7 @@ public async Task InitByProbAsync(RedisKey key, double error, double proba public bool Merge(RedisValue destination, long numKeys, RedisValue[] source, long[]? weight = null) { if (source.Length < 1) - throw new ArgumentNullException(nameof(source)); + throw new ArgumentOutOfRangeException(nameof(source)); List args = new List { destination, numKeys }; @@ -190,7 +189,7 @@ public bool Merge(RedisValue destination, long numKeys, RedisValue[] source, lon foreach (var w in weight) args.Add(w); } - return ResponseParser.ParseOKtoBoolean(_db.Execute(CMS.MERGE, args)); + return ResponseParser.OKtoBoolean(_db.Execute(CMS.MERGE, args)); } /// @@ -205,7 +204,7 @@ public bool Merge(RedisValue destination, long numKeys, RedisValue[] source, lon public async Task MergeAsync(RedisValue destination, long numKeys, RedisValue[] source, long[]? weight = null) { if (source.Length < 1) - throw new ArgumentNullException(nameof(source)); + throw new ArgumentOutOfRangeException(nameof(source)); List args = new List { destination, numKeys }; @@ -218,7 +217,7 @@ public async Task MergeAsync(RedisValue destination, long numKeys, RedisVa } var result = await _db.ExecuteAsync(CMS.MERGE, args); - return ResponseParser.ParseOKtoBoolean(result); + return ResponseParser.OKtoBoolean(result); } /// @@ -228,10 +227,10 @@ public async Task MergeAsync(RedisValue destination, long numKeys, RedisVa /// One or more items for which to return the count. /// Array with a min-count of each of the items in the sketch /// - public long[]? Query(RedisKey key, RedisValue[] items) //TODO: Create second version of this function using params for items input + public long[] Query(RedisKey key, params RedisValue[] items) { if (items.Length < 1) - throw new ArgumentNullException(nameof(items)); + throw new ArgumentOutOfRangeException(nameof(items)); List args = new List { key }; foreach (var item in items) args.Add(item); @@ -247,10 +246,10 @@ public async Task MergeAsync(RedisValue destination, long numKeys, RedisVa /// One or more items for which to return the count. /// Array with a min-count of each of the items in the sketch /// - public async Task QueryAsync(RedisKey key, RedisValue[] items) //TODO: Create second version of this function using params for items input + public async Task QueryAsync(RedisKey key, params RedisValue[] items) { if (items.Length < 1) - throw new ArgumentNullException(nameof(items)); + throw new ArgumentOutOfRangeException(nameof(items)); List args = new List { key }; foreach (var item in items) args.Add(item); diff --git a/src/NRedisStack.Core/CuckooFilter/CuckooCommands.cs b/src/NRedisStack.Core/CuckooFilter/CuckooCommands.cs index e6142a53..32300829 100644 --- a/src/NRedisStack.Core/CuckooFilter/CuckooCommands.cs +++ b/src/NRedisStack.Core/CuckooFilter/CuckooCommands.cs @@ -145,7 +145,7 @@ public async Task ExistsAsync(RedisKey key, RedisValue item) /// Name of the key to return information about. /// Information of the filter. /// - public CuckooInformation? Info(RedisKey key) + public CuckooInformation Info(RedisKey key) { var info = _db.Execute(CF.INFO, key); return ResponseParser.ToCuckooInfo(info); @@ -157,7 +157,7 @@ public async Task ExistsAsync(RedisKey key, RedisValue item) /// Name of the key to return information about. /// Information of the filter. /// - public async Task InfoAsync(RedisKey key) + public async Task InfoAsync(RedisKey key) { var info = await _db.ExecuteAsync(CF.INFO, key); return ResponseParser.ToCuckooInfo(info); @@ -174,8 +174,8 @@ public async Task ExistsAsync(RedisKey key, RedisValue item) /// public bool[] Insert(RedisKey key, RedisValue[] items, int? capacity = null, bool nocreate = false) { - if (items == null) - throw new ArgumentNullException(nameof(items)); + if (items.Length < 1) + throw new ArgumentOutOfRangeException(nameof(items)); List args = new List { key }; @@ -210,8 +210,8 @@ public bool[] Insert(RedisKey key, RedisValue[] items, int? capacity = null, boo /// public async Task InsertAsync(RedisKey key, RedisValue[] items, int? capacity = null, bool nocreate = false) { - if (items == null) - throw new ArgumentNullException(nameof(items)); + if (items.Length < 1) + throw new ArgumentOutOfRangeException(nameof(items)); List args = new List { key }; @@ -249,8 +249,8 @@ public async Task InsertAsync(RedisKey key, RedisValue[] items, int? cap /// public bool[] InsertNX(RedisKey key, RedisValue[] items, int? capacity = null, bool nocreate = false) { - if (items == null) - throw new ArgumentNullException(nameof(items)); + if (items.Length < 1) + throw new ArgumentOutOfRangeException(nameof(items)); List args = new List { key }; @@ -287,8 +287,8 @@ public bool[] InsertNX(RedisKey key, RedisValue[] items, int? capacity = null, b /// public async Task InsertNXAsync(RedisKey key, RedisValue[] items, int? capacity = null, bool nocreate = false) { - if (items == null) - throw new ArgumentNullException(nameof(items)); + if (items.Length < 1) + throw new ArgumentOutOfRangeException(nameof(items)); List args = new List { key }; @@ -323,7 +323,7 @@ public async Task InsertNXAsync(RedisKey key, RedisValue[] items, int? c /// public bool LoadChunk(RedisKey key, long iterator, Byte[] data) { - return ResponseParser.ParseOKtoBoolean(_db.Execute(CF.LOADCHUNK, key, iterator, data)); + return ResponseParser.OKtoBoolean(_db.Execute(CF.LOADCHUNK, key, iterator, data)); } /// @@ -337,7 +337,7 @@ public bool LoadChunk(RedisKey key, long iterator, Byte[] data) public async Task LoadChunkAsync(RedisKey key, long iterator, Byte[] data) { var result = await _db.ExecuteAsync(CF.LOADCHUNK, key, iterator, data); - return ResponseParser.ParseOKtoBoolean(result); + return ResponseParser.OKtoBoolean(result); } /// @@ -348,10 +348,10 @@ public async Task LoadChunkAsync(RedisKey key, long iterator, Byte[] data) /// An array of booleans, for each item means the item may exist in the filter, /// and means the item may exist in the filter. /// - public bool[] MExists(RedisKey key, RedisValue[] items) + public bool[] MExists(RedisKey key, params RedisValue[] items) { - if (items == null) - throw new ArgumentNullException(nameof(items)); + if (items.Length < 1) + throw new ArgumentOutOfRangeException(nameof(items)); List args = new List { key }; @@ -371,10 +371,10 @@ public bool[] MExists(RedisKey key, RedisValue[] items) /// An array of booleans, for each item means the item may exist in the filter, /// and means the item may exist in the filter. /// - public async Task MExistsAsync(RedisKey key, RedisValue[] items) + public async Task MExistsAsync(RedisKey key, params RedisValue[] items) { - if (items == null) - throw new ArgumentNullException(nameof(items)); + if (items.Length < 1) + throw new ArgumentOutOfRangeException(nameof(items)); List args = new List { key }; @@ -397,7 +397,7 @@ public async Task MExistsAsync(RedisKey key, RedisValue[] items) /// declaring filter as full and creating an additional filter. /// (Optional) When capacity is reached, an additional sub-filter is /// created in size of the last sub-filter multiplied by expansion. - /// if executed correctly, otherwise. + /// if executed correctly, Error otherwise. /// public bool Reserve(RedisKey key, long capacity, long? bucketSize = null, int? maxIterations = null, int? expansion = null) @@ -422,7 +422,7 @@ public bool Reserve(RedisKey key, long capacity, args.Add(expansion); } - return ResponseParser.ParseOKtoBoolean(_db.Execute(CF.RESERVE, args)); + return ResponseParser.OKtoBoolean(_db.Execute(CF.RESERVE, args)); } /// @@ -435,7 +435,7 @@ public bool Reserve(RedisKey key, long capacity, /// declaring filter as full and creating an additional filter. /// (Optional) When capacity is reached, an additional sub-filter is /// created in size of the last sub-filter multiplied by expansion. - /// if executed correctly, otherwise. + /// if executed correctly, Error otherwise. /// public async Task ReserveAsync(RedisKey key, long capacity, long? bucketSize = null, int? maxIterations = null, int? expansion = null) @@ -461,7 +461,7 @@ public async Task ReserveAsync(RedisKey key, long capacity, } var result = await _db.ExecuteAsync(CF.RESERVE, args); - return ResponseParser.ParseOKtoBoolean(result); + return ResponseParser.OKtoBoolean(result); } /// @@ -471,7 +471,7 @@ public async Task ReserveAsync(RedisKey key, long capacity, /// Iterator value; either 0 or the iterator from a previous invocation of this command. /// Tuple of iterator and data. /// - public Tuple? ScanDump(RedisKey key, long iterator) + public Tuple ScanDump(RedisKey key, long iterator) { return ResponseParser.ToScanDumpTuple(_db.Execute(CF.SCANDUMP, key, iterator)); } @@ -483,7 +483,7 @@ public async Task ReserveAsync(RedisKey key, long capacity, /// Iterator value; either 0 or the iterator from a previous invocation of this command. /// Tuple of iterator and data. /// - public async Task?> ScanDumpAsync(RedisKey key, long iterator) + public async Task> ScanDumpAsync(RedisKey key, long iterator) { var result = await _db.ExecuteAsync(CF.SCANDUMP, key, iterator); return ResponseParser.ToScanDumpTuple(result); diff --git a/src/NRedisStack.Core/ResponseParser.cs b/src/NRedisStack.Core/ResponseParser.cs index 3b98cff3..9f5adf07 100644 --- a/src/NRedisStack.Core/ResponseParser.cs +++ b/src/NRedisStack.Core/ResponseParser.cs @@ -8,21 +8,21 @@ using NRedisStack.Core.CuckooFilter.DataTypes; using NRedisStack.Core.CountMinSketch.DataTypes; using NRedisStack.Core.TopK.DataTypes; +using NRedisStack.Core.Tdigest.DataTypes; namespace NRedisStack.Core { public static class ResponseParser { - - //TODO: See if I can change the code to remove the warnings - public static bool ParseOKtoBoolean(RedisResult result) + public static bool OKtoBoolean(RedisResult result) { return result.ToString() == "OK"; } public static bool[] ToBooleanArray(RedisResult result) { - RedisResult[] redisResults = (RedisResult[])result; + RedisResult[]? redisResults = ToArray(result); + bool[] boolArr = new bool[redisResults.Length]; for (int i = 0; i < redisResults.Length; i++) { @@ -32,21 +32,50 @@ public static bool[] ToBooleanArray(RedisResult result) return boolArr; } - public static RedisResult[]? ToArray(RedisResult result) + public static RedisResult[] ToArray(RedisResult result) { - return (RedisResult[]?)result; + var redisResults = (RedisResult[]?)result; + if(redisResults != null) + return redisResults; + throw new ArgumentNullException(nameof(redisResults)); + + } public static long ToLong(RedisResult result) { - if (result.Type == ResultType.None) return 0; - return (long)result; + if((long?) result == null) + throw new ArgumentNullException(nameof(result)); + return (long) result; } - public static long[]? ToLongArray(RedisResult result) + public static double ToDouble(RedisResult result) { - if (result.Type == ResultType.None) return null; - return (long[])result; + if((double?) result == null) + throw new ArgumentNullException(nameof(result)); + return (double) result; + } + + public static double[] ToDoubleArray(RedisResult result) + { + List redisResults = new List(); + foreach(var res in ToArray(result)) + { + redisResults.Add(ToDouble(res)); + } + + return redisResults.ToArray(); + } + + public static long[] ToLongArray(RedisResult result) + { + List redisResults = new List(); + foreach(var res in ToArray(result)) + { + redisResults.Add(ToLong(res)); + } + + return redisResults.ToArray(); } public static TimeStamp ToTimeStamp(RedisResult result) @@ -66,35 +95,36 @@ public static IReadOnlyList ToTimeStampArray(RedisResult result) public static TimeSeriesTuple? ToTimeSeriesTuple(RedisResult result) { - RedisResult[]? redisResults = (RedisResult[]?)result; + RedisResult[] redisResults = ToArray(result); if (redisResults.Length == 0) return null; return new TimeSeriesTuple(ToTimeStamp(redisResults[0]), (double)redisResults[1]); } - public static Tuple? ToScanDumpTuple(RedisResult result) + public static Tuple ToScanDumpTuple(RedisResult result) { - RedisResult[]? redisResults = (RedisResult[]?)result; + RedisResult[] redisResults = ToArray(result); if (redisResults == null || redisResults.Length == 0) return null; return new Tuple((long)redisResults[0], (Byte[])redisResults[1]); } - public static HashEntry? ToHashEntry(RedisResult result) + public static HashEntry ToHashEntry(RedisResult result) { - RedisValue[]? redisResults = (RedisValue[]?)result; - if (redisResults.Length == 0) return null; - return new HashEntry(redisResults[0], redisResults[1]); + RedisResult[] redisResults = ToArray(result); + if (redisResults.Length < 2) + throw new ArgumentOutOfRangeException(nameof(result)); + return new HashEntry((RedisValue)(redisResults[0]), ((RedisValue)redisResults[1])); } - public static HashEntry[]? ToHashEntryArray(RedisResult result) + public static HashEntry[] ToHashEntryArray(RedisResult result) { - RedisValue[]? redisResults = (RedisValue[]?)result; + RedisResult[] redisResults = ToArray(result); var hash = new HashEntry[redisResults.Length / 2]; if (redisResults.Length == 0) return hash; for (int i = 0; i < redisResults.Length - 1; i += 2) - hash[i / 2] = new HashEntry(redisResults[i], redisResults[i + 1]); + hash[i / 2] = new HashEntry(((RedisValue)redisResults[i]), ((RedisValue)redisResults[i + 1])); return hash; } @@ -181,13 +211,11 @@ public static IReadOnlyList ToRuleArray(RedisResult result) return DuplicatePolicyExtensions.AsPolicy(policyStatus.ToUpper()); } - public static BloomInformation? ToBloomInfo(RedisResult result) //TODO: Think about a different implementation, because if the output of BF.INFO changes or even just the names of the labels then the parsing will not work + public static BloomInformation ToBloomInfo(RedisResult result) //TODO: Think about a different implementation, because if the output of BF.INFO changes or even just the names of the labels then the parsing will not work { long capacity, size, numberOfFilters, numberOfItemsInserted, expansionRate; capacity = size = numberOfFilters = numberOfItemsInserted = expansionRate = -1; - RedisResult[]? redisResults = (RedisResult[]?)result; - - if (redisResults == null) return null; + RedisResult[] redisResults = ToArray(result); for (int i = 0; i < redisResults.Length; ++i) { @@ -215,7 +243,7 @@ public static IReadOnlyList ToRuleArray(RedisResult result) return new BloomInformation(capacity, size, numberOfFilters, numberOfItemsInserted, expansionRate); } - public static CuckooInformation? ToCuckooInfo(RedisResult result) //TODO: Think about a different implementation, because if the output of BF.INFO changes or even just the names of the labels then the parsing will not work + public static CuckooInformation ToCuckooInfo(RedisResult result) //TODO: Think about a different implementation, because if the output of BF.INFO changes or even just the names of the labels then the parsing will not work { long size, numberOfBuckets, numberOfFilter, numberOfItemsInserted, numberOfItemsDeleted, bucketSize, expansionRate, maxIteration; @@ -224,9 +252,7 @@ public static IReadOnlyList ToRuleArray(RedisResult result) numberOfItemsInserted = numberOfItemsDeleted = bucketSize = expansionRate = maxIteration = -1; - RedisResult[]? redisResults = (RedisResult[]?)result; - - if (redisResults == null) return null; + RedisResult[] redisResults = ToArray(result); for (int i = 0; i < redisResults.Length; ++i) { @@ -265,15 +291,13 @@ public static IReadOnlyList ToRuleArray(RedisResult result) numberOfItemsDeleted, bucketSize, expansionRate, maxIteration); } - public static CmsInformation? ToCmsInfo(RedisResult result) //TODO: Think about a different implementation, because if the output of CMS.INFO changes or even just the names of the labels then the parsing will not work + public static CmsInformation ToCmsInfo(RedisResult result) //TODO: Think about a different implementation, because if the output of CMS.INFO changes or even just the names of the labels then the parsing will not work { long width, depth, count; width = depth = count = -1; - RedisResult[]? redisResults = (RedisResult[]?)result; - - if (redisResults == null) return null; + RedisResult[] redisResults = ToArray(result); for (int i = 0; i < redisResults.Length; ++i) { @@ -296,7 +320,7 @@ public static IReadOnlyList ToRuleArray(RedisResult result) return new CmsInformation(width, depth, count); } - public static TopKInformation? ToTopKInfo(RedisResult result) //TODO: Think about a different implementation, because if the output of CMS.INFO changes or even just the names of the labels then the parsing will not work + public static TopKInformation ToTopKInfo(RedisResult result) //TODO: Think about a different implementation, because if the output of CMS.INFO changes or even just the names of the labels then the parsing will not work { long k, width, depth; double decay; @@ -304,9 +328,7 @@ public static IReadOnlyList ToRuleArray(RedisResult result) k = width = depth = -1; decay = -1.0; - RedisResult[]? redisResults = (RedisResult[]?)result; - - if (redisResults == null) return null; + RedisResult[] redisResults = ToArray(result); for (int i = 0; i < redisResults.Length; ++i) { @@ -332,6 +354,50 @@ public static IReadOnlyList ToRuleArray(RedisResult result) return new TopKInformation(k, width, depth, decay); } + public static TdigestInformation ToTdigestInfo(RedisResult result) //TODO: Think about a different implementation, because if the output of CMS.INFO changes or even just the names of the labels then the parsing will not work + { + long compression, capacity, mergedNodes, unmergedNodes, totalCompressions; + string? mergedWeight, unmergedWeight; + + compression = capacity = mergedNodes = unmergedNodes = totalCompressions = -1; + mergedWeight = unmergedWeight = ""; + + RedisResult[] redisResults = ToArray(result); + + for (int i = 0; i < redisResults.Length; ++i) + { + string? label = redisResults[i++].ToString(); + + switch (label) + { + case "Compression": + compression = (long)redisResults[i]; + break; + case "Capacity": + capacity = (long)redisResults[i]; + break; + case "Merged nodes": + mergedNodes = (long)redisResults[i]; + break; + case "Unmerged nodes": + unmergedNodes = (long)redisResults[i]; + break; + case "Merged weight": + mergedWeight = redisResults[i].ToString(); + break; + case "Unmerged weight": + unmergedWeight = redisResults[i].ToString(); + break; + case "Total compressions": + totalCompressions = (long)redisResults[i]; + break; + } + } + + return new TdigestInformation(compression, capacity, mergedNodes, unmergedNodes, + mergedWeight, unmergedWeight, totalCompressions); + } + public static TimeSeriesInformation ToTimeSeriesInfo(RedisResult result) { long totalSamples = -1, memoryUsage = -1, retentionTime = -1, chunkSize = -1, chunkCount = -1; @@ -392,9 +458,10 @@ public static TimeSeriesInformation ToTimeSeriesInfo(RedisResult result) lastTimestamp, retentionTime, chunkCount, chunkSize, labels, sourceKey, rules, duplicatePolicy); } - public static IReadOnlyList ToStringArray(RedisResult result) + public static IReadOnlyList? ToStringArray(RedisResult result) { - RedisResult[] redisResults = (RedisResult[])result; + RedisResult[] redisResults = ToArray(result); + var list = new List(); if (redisResults.Length == 0) return list; Array.ForEach(redisResults, str => list.Add((string)str)); diff --git a/src/NRedisStack.Core/Tdigest/DataTypes/TdigestInformation.cs b/src/NRedisStack.Core/Tdigest/DataTypes/TdigestInformation.cs new file mode 100644 index 00000000..c51142a7 --- /dev/null +++ b/src/NRedisStack.Core/Tdigest/DataTypes/TdigestInformation.cs @@ -0,0 +1,31 @@ +namespace NRedisStack.Core.Tdigest.DataTypes +{ + /// + /// This class represents the response for TDIGEST.INFO command. + /// This object has Read-only properties and cannot be generated outside a TDIGEST.INFO response. + /// + public class TdigestInformation + { + public long Compression { get; private set; } + public long Capacity { get; private set; } + public long MergedNodes { get; private set; } + public long UnmergedNodes { get; private set; } + public string MergedWeight { get; private set; } + public string UnmergedWeight { get; private set; } + public long TotalCompressions { get; private set; } + + + internal TdigestInformation(long compression, long capacity, long mergedNodes, + long unmergedNodes, string mergedWeight, + string unmergedWeight, long totalCompressions) + { + Compression = compression; + Capacity = capacity; + MergedNodes = mergedNodes; + UnmergedNodes = unmergedNodes; + MergedWeight = mergedWeight; + UnmergedWeight = unmergedWeight; + TotalCompressions = totalCompressions; + } + } +} \ No newline at end of file diff --git a/src/NRedisStack.Core/Tdigest/Literals/CommandArgs.cs b/src/NRedisStack.Core/Tdigest/Literals/CommandArgs.cs new file mode 100644 index 00000000..14e37bbf --- /dev/null +++ b/src/NRedisStack.Core/Tdigest/Literals/CommandArgs.cs @@ -0,0 +1,7 @@ +namespace NRedisStack.Core.Literals +{ + internal class TdigestArgs + { + public static string COMPRESSION => "COMPRESSION"; + } +} \ No newline at end of file diff --git a/src/NRedisStack.Core/Tdigest/Literals/Commands.cs b/src/NRedisStack.Core/Tdigest/Literals/Commands.cs new file mode 100644 index 00000000..d4633f3c --- /dev/null +++ b/src/NRedisStack.Core/Tdigest/Literals/Commands.cs @@ -0,0 +1,17 @@ +namespace NRedisStack.Core.Literals +{ + internal class TDIGEST + { + public static string CREATE => "TDIGEST.CREATE"; + public static string RESET => "TDIGEST.RESET"; + public static string ADD => "TDIGEST.ADD"; + public static string MERGE => "TDIGEST.MERGE"; + public static string MERGESTORE => "TDIGEST.MERGESTORE"; + public static string MIN => "TDIGEST.MIN"; + public static string MAX => "TDIGEST.MAX"; + public static string QUANTILE => "TDIGEST.QUANTILE"; + public static string CDF => "TDIGEST.CDF"; + public static string TRIMMED_MEAN => "TDIGEST.TRIMMED_MEAN"; + public static string INFO => "TDIGEST.INFO"; + } +} \ No newline at end of file diff --git a/src/NRedisStack.Core/Tdigest/TdigestCommands.cs b/src/NRedisStack.Core/Tdigest/TdigestCommands.cs new file mode 100644 index 00000000..be77ff2a --- /dev/null +++ b/src/NRedisStack.Core/Tdigest/TdigestCommands.cs @@ -0,0 +1,402 @@ +using NRedisStack.Core.Tdigest.DataTypes; +using NRedisStack.Core.Literals; +using StackExchange.Redis; +namespace NRedisStack.Core +{ + + public class TdigestCommands + { + IDatabase _db; + public TdigestCommands(IDatabase db) + { + _db = db; + } + + /// + /// Adds one or more observations to a t-digest sketch. + /// + /// The name of the sketch. + /// The value of the observation. + /// The weight of this observation. + /// if executed correctly, error otherwise + /// + public bool Add(RedisKey key, double item, double weight) + { + if (weight < 0) throw new ArgumentException(nameof(weight)); + + return ResponseParser.OKtoBoolean(_db.Execute(TDIGEST.ADD, key, item, weight)); + } + + /// + /// Adds one or more observations to a t-digest sketch. + /// + /// The name of the sketch. + /// The value of the observation. + /// The weight of this observation. + /// if executed correctly, error otherwise + /// + public async Task AddAsync(RedisKey key, double item, double weight) + { + if (weight < 0) throw new ArgumentException(nameof(weight)); + + var result = await _db.ExecuteAsync(TDIGEST.ADD, key, item); + return ResponseParser.OKtoBoolean(result); + } + + /// + /// Adds one or more observations to a t-digest sketch. + /// + /// The name of the sketch. + /// Tuple of the value of the observation and The weight of this observation. + /// if executed correctly, error otherwise + /// + public bool Add(RedisKey key, Tuple[] valueWeight) + { + var args = new List { key }; + + foreach (var pair in valueWeight) + { + if (pair.Item2 < 0) throw new ArgumentException(nameof(pair.Item2)); + args.Add(pair.Item1); + args.Add(pair.Item2); + } + return ResponseParser.OKtoBoolean(_db.Execute(TDIGEST.ADD, args)); + } + + /// + /// Adds one or more observations to a t-digest sketch. + /// + /// The name of the sketch. + /// Tuple of the value of the observation and The weight of this observation. + /// if executed correctly, error otherwise + /// + public async Task AddAsync(RedisKey key, Tuple[] valueWeight) + { + var args = new List { key }; + + foreach (var pair in valueWeight) + { + if (pair.Item2 < 0) throw new ArgumentException(nameof(pair.Item2)); + args.Add(pair.Item1); + args.Add(pair.Item2); + } + return ResponseParser.OKtoBoolean(await _db.ExecuteAsync(TDIGEST.ADD, args)); + } + + /// + /// Estimate the fraction of all observations added which are <= value. + /// + /// The name of the sketch. + /// upper limit of observation value. + /// double-reply - estimation of the fraction of all observations added which are <= value + /// + public double CDF(RedisKey key, double item) + { + return ResponseParser.ToDouble(_db.Execute(TDIGEST.ADD, key, item)); + } + + /// + /// Estimate the fraction of all observations added which are <= value. + /// + /// The name of the sketch. + /// upper limit of observation value. + /// double-reply - estimation of the fraction of all observations added which are <= value + /// + public async Task CDF(RedisKey key, double item, double weight) + { + var result = await _db.ExecuteAsync(TDIGEST.ADD, key, item); + return ResponseParser.ToDouble(result); + } + + /// + /// Allocate memory and initialize a t-digest sketch. + /// + /// The name of the sketch. + /// The compression parameter. + /// double-reply - estimation of the fraction of all observations added which are <= value + /// + public double Create(RedisKey key, long compression = 100) + { + return ResponseParser.ToDouble(_db.Execute(TDIGEST.CREATE, key, compression)); + } + + /// + /// Allocate memory and initialize a t-digest sketch. + /// + /// The name of the sketch. + /// The compression parameter. + /// double-reply - estimation of the fraction of all observations added which are <= value + /// + public async Task CreateAsync(RedisKey key, long compression = 100) + { + return ResponseParser.ToDouble(await _db.ExecuteAsync(TDIGEST.CREATE, key, compression)); + } + + /// + /// Returns information about a sketch. + /// + /// The name of the sketch. + /// information about a sketch + /// + public TdigestInformation Info(RedisKey key) + { + return ResponseParser.ToTdigestInfo(_db.Execute(TDIGEST.INFO, key)); + } + + /// + /// Returns information about a sketch. + /// + /// The name of the sketch. + /// information about a sketch + /// + public async Task InfoAsync(RedisKey key) + { + return ResponseParser.ToTdigestInfo(await _db.ExecuteAsync(TDIGEST.INFO, key)); + } + + + /// + /// Get the maximum observation value from the sketch. + /// + /// The name of the sketch. + /// the maximum observation value from the sketch + /// + public RedisResult Max(RedisKey key) + { + return _db.Execute(TDIGEST.MAX, key); + } + + /// + /// Get the maximum observation value from the sketch. + /// + /// The name of the sketch. + /// the maximum observation value from the sketch + /// + public async Task MaxAsync(RedisKey key) + { + return await _db.ExecuteAsync(TDIGEST.MAX, key); + } + + /// + /// Get the minimum observation value from the sketch. + /// + /// The name of the sketch. + /// the minimum observation value from the sketch + /// + public RedisResult Min(RedisKey key) + { + return _db.Execute(TDIGEST.MIN, key); + } + + /// + /// Get the minimum observation value from the sketch. + /// + /// The name of the sketch. + /// the minimum observation value from the sketch + /// + public async Task MinAsync(RedisKey key) + { + return await _db.ExecuteAsync(TDIGEST.MIN, key); + } + + /// + /// Get the minimum observation value from the sketch. + /// + /// TSketch to copy observation values to (a t-digest data structure). + /// Sketch to copy observation values from (a t-digest data structure). + /// if executed correctly, error otherwise + /// + public bool Merge(RedisKey destinationKey, RedisKey sourceKey) + { + return ResponseParser.OKtoBoolean(_db.Execute(TDIGEST.MERGE, destinationKey, sourceKey)); + } + + /// + /// Get the minimum observation value from the sketch. + /// + /// TSketch to copy observation values to (a t-digest data structure). + /// Sketch to copy observation values from (a t-digest data structure). + /// if executed correctly, error otherwise + /// + public async Task MergeAsync(RedisKey destinationKey, RedisKey sourceKey) + { + var result = await _db.ExecuteAsync(TDIGEST.MERGE, destinationKey, sourceKey); + return ResponseParser.OKtoBoolean(result); + } + + /// + /// Get the minimum observation value from the sketch. + /// + /// TSketch to copy observation values to (a t-digest data structure). + /// Sketch to copy observation values from (a t-digest data structure). + /// if executed correctly, error otherwise + /// + public bool Merge(RedisKey destinationKey, params RedisKey[] sourceKeys) + { + if (sourceKeys.Length < 1) throw new ArgumentException(nameof(sourceKeys)); + + var args = sourceKeys.ToList(); + args.Insert(0, destinationKey); + + return ResponseParser.OKtoBoolean(_db.Execute(TDIGEST.MERGE, args)); + } + + /// + /// Get the minimum observation value from the sketch. + /// + /// TSketch to copy observation values to (a t-digest data structure). + /// Sketch to copy observation values from (a t-digest data structure). + /// if executed correctly, error otherwise + /// + public async Task MergeAsync(RedisKey destinationKey, params RedisKey[] sourceKeys) + { + if (sourceKeys.Length < 1) throw new ArgumentException(nameof(sourceKeys)); + + var args = sourceKeys.ToList(); + args.Insert(0, destinationKey); + + var result = await _db.ExecuteAsync(TDIGEST.MERGE, args); + return ResponseParser.OKtoBoolean(result); + } + + /// + /// Merges all of the values from 'from' keys to 'destination-key' sketch. + /// + /// TSketch to copy observation values to (a t-digest data structure). + /// Number of sketch(es) to copy observation values from. + /// The compression parameter. + /// Sketch to copy observation values from (a t-digest data structure). + /// if executed correctly, error otherwise + /// + public bool MergeStore(RedisKey destinationKey, long numkeys, long compression = 100, params RedisKey[] sourceKeys) + { + if (sourceKeys.Length < 1) throw new ArgumentException(nameof(sourceKeys)); + + var args = new List { destinationKey, numkeys }; + foreach (var key in sourceKeys) args.Add(key); + args.Add(TdigestArgs.COMPRESSION); + args.Add(compression); + + return ResponseParser.OKtoBoolean(_db.Execute(TDIGEST.MERGE, args)); + } + + /// + /// Merges all of the values from 'from' keys to 'destination-key' sketch. + /// + /// TSketch to copy observation values to (a t-digest data structure). + /// Number of sketch(es) to copy observation values from. + /// The compression parameter. + /// Sketch to copy observation values from (a t-digest data structure). + /// if executed correctly, error otherwise + /// + public async Task MergeStoreAsync(RedisKey destinationKey, long numkeys, long compression = 100, params RedisKey[] sourceKeys) + { + if (sourceKeys.Length < 1) throw new ArgumentException(nameof(sourceKeys)); + + var args = new List { destinationKey, numkeys }; + foreach (var key in sourceKeys) args.Add(key); + args.Add(TdigestArgs.COMPRESSION); + args.Add(compression); + + var result = await _db.ExecuteAsync(TDIGEST.MERGE, args); + return ResponseParser.OKtoBoolean(result); + } + + /// + /// Returns estimates of one or more cutoffs such that a specified fraction of the observations + ///added to this t-digest would be less than or equal to each of the specified cutoffs. + /// + /// The name of the sketch (a t-digest data structure). + /// The desired fraction (between 0 and 1 inclusively). + /// An array of results populated with quantile_1, cutoff_1, quantile_2, cutoff_2, ..., quantile_N, cutoff_N. + /// + public double[] Quantile(RedisKey key, params double[] quantile) + { + if (quantile.Length < 1) throw new ArgumentException(nameof(quantile)); + + var args = new List { key }; + foreach (var q in quantile) args.Add(q); + + return ResponseParser.ToDoubleArray(_db.Execute(TDIGEST.QUANTILE, args)); + } + + /// + /// Returns estimates of one or more cutoffs such that a specified fraction of the observations + ///added to this t-digest would be less than or equal to each of the specified cutoffs. + /// + /// The name of the sketch (a t-digest data structure). + /// The desired fraction (between 0 and 1 inclusively). + /// An array of results populated with quantile_1, cutoff_1, quantile_2, cutoff_2, ..., quantile_N, cutoff_N. + /// + public async Task QuantileAsync(RedisKey key, params double[] quantile) + { + if (quantile.Length < 1) throw new ArgumentException(nameof(quantile)); + + var args = new List { key }; + foreach (var q in quantile) args.Add(q); + + return ResponseParser.ToDoubleArray(await _db.ExecuteAsync(TDIGEST.QUANTILE, args)); + } + + /// + /// Reset the sketch - empty the sketch and re-initialize it + /// + /// The name of the sketch (a t-digest data structure). + /// if executed correctly, error otherwise. + /// + public bool Reset(RedisKey key, params double[] quantile) + { + return ResponseParser.OKtoBoolean(_db.Execute(TDIGEST.RESET, key)); + } + + /// + /// Reset the sketch - empty the sketch and re-initialize it + /// + /// The name of the sketch (a t-digest data structure). + /// if executed correctly, error otherwise. + /// + public async Task ResetAsync(RedisKey key, params double[] quantile) + { + return ResponseParser.OKtoBoolean(await _db.ExecuteAsync(TDIGEST.RESET, key)); + } + + /// + /// Reset the sketch - empty the sketch and re-initialize it + /// + /// The name of the sketch (a t-digest data structure). + /// Exclude observation values lower than this quantile. + /// Exclude observation values higher than this quantile. + /// estimation of the mean value. Will return DBL_MAX if the sketch is empty. + /// + public RedisResult TrimmedMean(RedisKey key, double lowCutQuantile, double highCutQuantile) + { + return _db.Execute(TDIGEST.RESET, key, lowCutQuantile, highCutQuantile); + } + + /// + /// Reset the sketch - empty the sketch and re-initialize it + /// + /// The name of the sketch (a t-digest data structure). + /// Exclude observation values lower than this quantile. + /// Exclude observation values higher than this quantile. + /// estimation of the mean value. Will return DBL_MAX if the sketch is empty. + /// + public async Task TrimmedMeanAsync(RedisKey key, double lowCutQuantile, double highCutQuantile) + { + return await _db.ExecuteAsync(TDIGEST.RESET, key, lowCutQuantile, highCutQuantile); + } + + + + + + + + + + + + + + } +} diff --git a/src/NRedisStack.Core/TimeSeries/TimeSeriesCommands.cs b/src/NRedisStack.Core/TimeSeries/TimeSeriesCommands.cs index 19a1ecec..c728b28c 100644 --- a/src/NRedisStack.Core/TimeSeries/TimeSeriesCommands.cs +++ b/src/NRedisStack.Core/TimeSeries/TimeSeriesCommands.cs @@ -17,7 +17,7 @@ public TimeSeriesCommands(IDatabase db) public bool 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 ResponseParser.ParseOKtoBoolean(_db.Execute(TS.CREATE, args)); + return ResponseParser.OKtoBoolean(_db.Execute(TS.CREATE, args)); } public TimeSeriesInformation Info(string key) @@ -28,7 +28,7 @@ public TimeSeriesInformation Info(string key) public bool TimeSeriesAlter(string key, long? retentionTime = null, IReadOnlyCollection labels = null) { var args = TimeSeriesAux.BuildTsAlterArgs(key, retentionTime, labels); - return ResponseParser.ParseOKtoBoolean(_db.Execute(TS.ALTER, args)); + return ResponseParser.OKtoBoolean(_db.Execute(TS.ALTER, args)); } } diff --git a/src/NRedisStack.Core/TopK/DataTypes/TopKInformation.cs b/src/NRedisStack.Core/TopK/DataTypes/TopKInformation.cs index 906e8f14..eb6b5d2d 100644 --- a/src/NRedisStack.Core/TopK/DataTypes/TopKInformation.cs +++ b/src/NRedisStack.Core/TopK/DataTypes/TopKInformation.cs @@ -1,8 +1,8 @@ namespace NRedisStack.Core.TopK.DataTypes { /// - /// This class represents the response for CMS.INFO command. - /// This object has Read-only properties and cannot be generated outside a CMS.INFO response. + /// This class represents the response for TOPK.INFO command. + /// This object has Read-only properties and cannot be generated outside a TOPK.INFO response. /// public class TopKInformation { diff --git a/src/NRedisStack.Core/TopK/Literals/CommandArgs.cs b/src/NRedisStack.Core/TopK/Literals/CommandArgs.cs index ed0e5b4e..0844e5dd 100644 --- a/src/NRedisStack.Core/TopK/Literals/CommandArgs.cs +++ b/src/NRedisStack.Core/TopK/Literals/CommandArgs.cs @@ -2,6 +2,6 @@ namespace NRedisStack.Core.Literals { internal class TopKArgs { - //TODO: TOPK doesn't have literals to save, consider deleting it, or keep it in case they need it in the future + // TOPK doesn't have literals to save, it's here in case they need it in the future } } \ No newline at end of file diff --git a/src/NRedisStack.Core/TopK/TopKCommands.cs b/src/NRedisStack.Core/TopK/TopKCommands.cs index 9ad80080..80e40345 100644 --- a/src/NRedisStack.Core/TopK/TopKCommands.cs +++ b/src/NRedisStack.Core/TopK/TopKCommands.cs @@ -4,7 +4,7 @@ namespace NRedisStack.Core { - public class TopKCommands //TODO: Finish this + public class TopKCommands { IDatabase _db; public TopKCommands(IDatabase db) @@ -12,24 +12,24 @@ public TopKCommands(IDatabase db) _db = db; } - /// - /// Increases the count of item by increment. - /// - /// The name of the sketch. - /// Item to be added. - /// Array of simple-string-reply - if an element was dropped from the TopK list, null otherwise - /// - public RedisResult[]? Add(RedisKey key, RedisValue item) - { - return ResponseParser.ToArray(_db.Execute(TOPK.ADD, key, item)); - } + // /// + // /// Increases the count of item by increment. + // /// + // /// The name of the sketch. + // /// Item to be added. + // /// Array of simple-string-reply - if an element was dropped from the TopK list, null otherwise + // /// + // public RedisResult[] Add(RedisKey key, RedisValue item) + // { + // return ResponseParser.ToArray(_db.Execute(TOPK.ADD, key, item)); + // } - /// - public async Task AddAsync(RedisKey key, RedisValue item) - { - var result = await _db.ExecuteAsync(TOPK.ADD, key, item); - return ResponseParser.ToArray(result); - } + // /// + // public async Task AddAsync(RedisKey key, RedisValue item) + // { + // var result = await _db.ExecuteAsync(TOPK.ADD, key, item); + // return ResponseParser.ToArray(result); + // } /// /// Increases the count of item by increment. @@ -40,38 +40,43 @@ public TopKCommands(IDatabase db) /// public RedisResult[]? Add(RedisKey key, params RedisValue[] items) { - var args = Auxiliary.MergeArgs(key, items); + if (items.Length < 1) + throw new ArgumentOutOfRangeException(nameof(items)); + var args = Auxiliary.MergeArgs(key, items); return (RedisResult[]?)_db.Execute(TOPK.ADD, args); } /// public async Task AddAsync(RedisKey key, params RedisValue[] items) { + if (items.Length < 1) + throw new ArgumentOutOfRangeException(nameof(items)); + var args = Auxiliary.MergeArgs(key, items); var result = await _db.ExecuteAsync(TOPK.ADD, args); return (RedisResult[]?)result; } - /// - /// Returns count for an item. - /// - /// Name of sketch where item is counted - /// Item to be counted. - /// count for responding item. - /// - public long Count(RedisKey key, RedisValue item) - { - return ResponseParser.ToLong(_db.Execute(TOPK.COUNT, key, item)); - } + // /// + // /// Returns count for an item. + // /// + // /// Name of sketch where item is counted + // /// Item to be counted. + // /// count for responding item. + // /// + // public long Count(RedisKey key, RedisValue item) + // { + // return ResponseParser.ToLong(_db.Execute(TOPK.COUNT, key, item)); + // } - /// - public async Task CountAsync(RedisKey key, RedisValue item) - { - var result = await _db.ExecuteAsync(TOPK.COUNT, key, item); - return ResponseParser.ToLong(result); - } + // /// + // public async Task CountAsync(RedisKey key, RedisValue item) + // { + // var result = await _db.ExecuteAsync(TOPK.COUNT, key, item); + // return ResponseParser.ToLong(result); + // } /// /// Returns count for an items. @@ -80,15 +85,21 @@ public async Task CountAsync(RedisKey key, RedisValue item) /// Items to be counted. /// count for responding item. /// - public long[]? Count(RedisKey key, params RedisValue[] items) + public long[] Count(RedisKey key, params RedisValue[] items) { + if (items.Length < 1) + throw new ArgumentOutOfRangeException(nameof(items)); + var args = Auxiliary.MergeArgs(key, items); return ResponseParser.ToLongArray(_db.Execute(TOPK.COUNT, args)); } /// - public async Task CountAsync(RedisKey key, params RedisValue[] items) + public async Task CountAsync(RedisKey key, params RedisValue[] items) { + if (items.Length < 1) + throw new ArgumentOutOfRangeException(nameof(items)); + var args = Auxiliary.MergeArgs(key, items); var result = await _db.ExecuteAsync(TOPK.COUNT, args); return ResponseParser.ToLongArray(result); @@ -103,7 +114,7 @@ public async Task CountAsync(RedisKey key, RedisValue item) /// and the Amount by which the item score is to be increased. /// Score of each item after increment. /// - public RedisResult[]? IncrBy(RedisKey key, params Tuple[] itemIncrements) + public RedisResult[] IncrBy(RedisKey key, params Tuple[] itemIncrements) { if (itemIncrements.Length < 1) throw new ArgumentException(nameof(itemIncrements)); @@ -125,7 +136,7 @@ public async Task CountAsync(RedisKey key, RedisValue item) /// and the Amount by which the item score is to be increased. /// Score of each item after increment. /// - public async Task IncrByAsync(RedisKey key, params Tuple[] itemIncrements) + public async Task IncrByAsync(RedisKey key, params Tuple[] itemIncrements) { if (itemIncrements.Length < 1) throw new ArgumentException(nameof(itemIncrements)); @@ -141,27 +152,25 @@ public async Task CountAsync(RedisKey key, RedisValue item) return ResponseParser.ToArray(result); } - // //TODO: information about what? /// /// Return TopK information. /// /// Name of the key to return information about. /// TopK Information. /// - public TopKInformation? Info(RedisKey key) + public TopKInformation Info(RedisKey key) { var info = _db.Execute(TOPK.INFO, key); return ResponseParser.ToTopKInfo(info); } - // //TODO: information about what? /// /// Return TopK information. /// /// Name of the key to return information about. /// TopK Information. /// - public async Task InfoAsync(RedisKey key) + public async Task InfoAsync(RedisKey key) { var info = await _db.ExecuteAsync(TOPK.INFO, key); return ResponseParser.ToTopKInfo(info); @@ -174,7 +183,7 @@ public async Task CountAsync(RedisKey key, RedisValue item) /// return Count of each element is returned. /// Full list of items in Top K list /// - public RedisResult[]? List(RedisKey key, bool withcount = false) + public RedisResult[] List(RedisKey key, bool withcount = false) { var result = (withcount) ? _db.Execute(TOPK.LIST, key, "WITHCOUNT") : _db.Execute(TOPK.LIST, key); @@ -188,7 +197,7 @@ public async Task CountAsync(RedisKey key, RedisValue item) /// return Count of each element is returned. /// Full list of items in Top K list /// - public async Task ListAsync(RedisKey key, bool withcount = false) + public async Task ListAsync(RedisKey key, bool withcount = false) { var result = await ((withcount) ? _db.ExecuteAsync(TOPK.LIST, key, "WITHCOUNT") : _db.ExecuteAsync(TOPK.LIST, key)); @@ -202,7 +211,7 @@ public async Task CountAsync(RedisKey key, RedisValue item) /// Item to be queried. /// if item is in Top-K, otherwise/> /// - public bool? Query(RedisKey key, RedisValue item) + public bool Query(RedisKey key, RedisValue item) { return _db.Execute(TOPK.QUERY, key, item).ToString() == "1"; } @@ -214,7 +223,7 @@ public async Task CountAsync(RedisKey key, RedisValue item) /// Item to be queried. /// if item is in Top-K, otherwise/> /// - public async Task QueryAsync(RedisKey key, RedisValue item) + public async Task QueryAsync(RedisKey key, RedisValue item) { var result = await _db.ExecuteAsync(TOPK.QUERY, key, item); return result.ToString() == "1"; @@ -227,10 +236,10 @@ public async Task CountAsync(RedisKey key, RedisValue item) /// Items to be queried. /// Bolean Array where if item is in Top-K, otherwise/> /// - public bool[]? Query(RedisKey key, params RedisValue[] items) + public bool[] Query(RedisKey key, params RedisValue[] items) { if (items.Length < 1) - throw new ArgumentNullException(nameof(items)); + throw new ArgumentOutOfRangeException(nameof(items)); var args = Auxiliary.MergeArgs(key, items); @@ -244,10 +253,10 @@ public async Task CountAsync(RedisKey key, RedisValue item) /// Items to be queried. /// Bolean Array where if item is in Top-K, otherwise/> /// - public async Task QueryAsync(RedisKey key, params RedisValue[] items) + public async Task QueryAsync(RedisKey key, params RedisValue[] items) { if (items.Length < 1) - throw new ArgumentNullException(nameof(items)); + throw new ArgumentOutOfRangeException(nameof(items)); var args = Auxiliary.MergeArgs(key, items); @@ -265,9 +274,9 @@ public async Task CountAsync(RedisKey key, RedisValue item) /// The probability of reducing a counter in an occupied bucket. (Default 0.9) /// if executed correctly, error otherwise/> /// - public bool? Reserve(RedisKey key, long topk, long width = 7, long depth = 8, double decay = 0.9) + public bool Reserve(RedisKey key, long topk, long width = 7, long depth = 8, double decay = 0.9) { - return ResponseParser.ParseOKtoBoolean(_db.Execute(TOPK.RESERVE, key, topk, width, depth, decay)); + return ResponseParser.OKtoBoolean(_db.Execute(TOPK.RESERVE, key, topk, width, depth, decay)); } /// @@ -280,10 +289,10 @@ public async Task CountAsync(RedisKey key, RedisValue item) /// The probability of reducing a counter in an occupied bucket. (Default 0.9) /// if executed correctly, error otherwise/> /// - public async Task ReserveAsync(RedisKey key, long topk, long width = 7, long depth = 8, double decay = 0.9) + public async Task ReserveAsync(RedisKey key, long topk, long width = 7, long depth = 8, double decay = 0.9) { var result = await _db.ExecuteAsync(TOPK.RESERVE, key, topk, width, depth, decay); - return ResponseParser.ParseOKtoBoolean(result); + return ResponseParser.OKtoBoolean(result); } } } diff --git a/tests/NRedisStack.Tests/Bloom/BloomTests.cs b/tests/NRedisStack.Tests/Bloom/BloomTests.cs index ad441070..6a8eb037 100644 --- a/tests/NRedisStack.Tests/Bloom/BloomTests.cs +++ b/tests/NRedisStack.Tests/Bloom/BloomTests.cs @@ -225,7 +225,7 @@ public async void TestExistsNonExistAsync() } [Fact] - public void TestInfo() //TODO: think again about the returned value of BF.INFO, maybe creating a new returned type + public void TestInfo() { IDatabase db = redisFixture.Redis.GetDatabase(); db.Execute("FLUSHALL"); diff --git a/tests/NRedisStack.Tests/CountMinSketch/CmsTests.cs b/tests/NRedisStack.Tests/CountMinSketch/CmsTests.cs index 346b0083..c744de70 100644 --- a/tests/NRedisStack.Tests/CountMinSketch/CmsTests.cs +++ b/tests/NRedisStack.Tests/CountMinSketch/CmsTests.cs @@ -86,7 +86,7 @@ public void TestKeyAlreadyExists() public async void TestKeyAlreadyExistsAsync() { IDatabase db = redisFixture.Redis.GetDatabase(); - db.Execute("FLUSHALL"); //TODO: Check if I need Execute("FLUSHALL") to be Async in the async test + db.Execute("FLUSHALL"); await db.CMS().InitByDimAsync("dup", 16, 4); await Assert.ThrowsAsync(() => db.CMS().InitByDimAsync("dup", 8, 6)); diff --git a/tests/NRedisStack.Tests/CuckooFilter/CuckooTests.cs b/tests/NRedisStack.Tests/CuckooFilter/CuckooTests.cs index 70065a88..8689ad7d 100644 --- a/tests/NRedisStack.Tests/CuckooFilter/CuckooTests.cs +++ b/tests/NRedisStack.Tests/CuckooFilter/CuckooTests.cs @@ -169,7 +169,7 @@ public async void TestDeleteAsync() } [Fact] - public void TestInfo() //TODO: think again about the returned value of CF.INFO, maybe creating a new returned type + public void TestInfo() { IDatabase db = redisFixture.Redis.GetDatabase(); db.Execute("FLUSHALL"); @@ -184,7 +184,7 @@ public async void TestDeleteAsync() } [Fact] - public async void TestInfoAsync() //TODO: think again about the returned value of CF.INFO, maybe creating a new returned type + public async void TestInfoAsync() { IDatabase db = redisFixture.Redis.GetDatabase(); db.Execute("FLUSHALL");