Skip to content

Commit 8fe55a6

Browse files
authored
Add async methods (#7)
* Add Async Version for all bloom commands * Async tests for TOPK, CF and CMS * Add Bloom Async Tests
1 parent 71b940c commit 8fe55a6

File tree

9 files changed

+1186
-9
lines changed

9 files changed

+1186
-9
lines changed

src/NRedisStack.Core/Bloom/BloomCommands.cs

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,19 @@ public bool Add(RedisKey key, RedisValue item)
2424
return _db.Execute(BF.ADD, key, item).ToString() == "1";
2525
}
2626

27+
/// <summary>
28+
/// Adds an item to a Bloom Filter.
29+
/// </summary>
30+
/// <param name="key">The key under which the filter is found.</param>
31+
/// <param name="item">The item to add.</param>
32+
/// <returns><see langword="true"/> if the item did not exist in the filter, <see langword="false"/> otherwise.</returns>
33+
/// <remarks><seealso href="https://redis.io/commands/bf.add"/></remarks>
34+
public async Task<bool> AddAsync(RedisKey key, RedisValue item)
35+
{
36+
var result = await _db.ExecuteAsync(BF.ADD, key, item);
37+
return result.ToString() == "1";
38+
}
39+
2740
/// <summary>
2841
/// Checks whether an item exist in the Bloom Filter or not.
2942
/// </summary>
@@ -37,6 +50,20 @@ public bool Exists(RedisKey key, RedisValue item)
3750
return _db.Execute(BF.EXISTS, key, item).ToString() == "1";
3851
}
3952

53+
/// <summary>
54+
/// Checks whether an item exist in the Bloom Filter or not.
55+
/// </summary>
56+
/// <param name="key">The name of the filter.</param>
57+
/// <param name="item">The item to check for.</param>
58+
/// <returns><see langword="true"/> means the item may exist in the filter,
59+
/// and <see langword="false"/> means it does not exist in the filter.</returns>
60+
/// <remarks><seealso href="https://redis.io/commands/bf.exists"/></remarks>
61+
public async Task<bool> ExistsAsync(RedisKey key, RedisValue item)
62+
{
63+
var result = await _db.ExecuteAsync(BF.EXISTS, key, item);
64+
return result.ToString() == "1";
65+
}
66+
4067
/// <summary>
4168
/// Return information about a bloom filter.
4269
/// </summary>
@@ -49,6 +76,18 @@ public bool Exists(RedisKey key, RedisValue item)
4976
return ResponseParser.ToBloomInfo(info);
5077
}
5178

79+
/// <summary>
80+
/// Return information about a bloom filter.
81+
/// </summary>
82+
/// <param name="key">Name of the key to return information about.</param>
83+
/// <returns>Information of the filter.</returns>
84+
/// <remarks><seealso href="https://redis.io/commands/bf.info"/></remarks>
85+
public async Task<BloomInformation?> InfoAsync(RedisKey key)
86+
{
87+
var info = await _db.ExecuteAsync(BF.INFO, key);
88+
return ResponseParser.ToBloomInfo(info);
89+
}
90+
5291
/// <summary>
5392
/// Adds one or more items to a Bloom Filter. A filter will be created if it does not exist.
5493
/// </summary>
@@ -112,6 +151,70 @@ public bool Exists(RedisKey key, RedisValue item)
112151
return ResponseParser.ToBooleanArray(_db.Execute(BF.INSERT, args));
113152
}
114153

154+
/// <summary>
155+
/// Adds one or more items to a Bloom Filter. A filter will be created if it does not exist.
156+
/// </summary>
157+
/// <param name="key">The name of the filter.</param>
158+
/// <param name="items">One or more items to add.</param>
159+
/// <param name="capacity">(Optional) Specifies the desired capacity for the filter to be created.</param>
160+
/// <param name="error">(Optional) Specifies the error ratio of the newly created filter if it does not yet exist.</param>
161+
/// <param name="expansion">(Optional) When capacity is reached, an additional sub-filter is
162+
/// created in size of the last sub-filter multiplied by expansion.</param>
163+
/// <param name="nocreate">(Optional) <see langword="true"/> to indicates that the
164+
/// filter should not be created if it does not already exist.</param>
165+
/// <param name="nonscaling">(Optional) <see langword="true"/> toprevent the filter
166+
/// from creating additional sub-filters if initial capacity is reached.</param>
167+
/// <returns>An array of booleans. Each element is either true or false depending on whether the
168+
/// corresponding input element was newly added to the filter or may have previously existed.</returns>
169+
/// <remarks><seealso href="https://redis.io/commands/bf.insert"/></remarks>
170+
public async Task<bool[]> InsertAsync(RedisKey key, RedisValue[] items, int? capacity = null, //TODO: create enother function that get one item, because right now if the user want to insert one item he needs to insert this as RedisValue[]
171+
double? error = null, int? expansion = null,
172+
bool nocreate = false, bool nonscaling = false)
173+
{
174+
if (items == null)
175+
throw new ArgumentNullException(nameof(items));
176+
177+
List<object> args = new List<object> { key };
178+
179+
if (capacity != null)
180+
{
181+
args.Add(BloomArgs.CAPACITY);
182+
args.Add(capacity);
183+
}
184+
185+
if (error != null)
186+
{
187+
args.Add(BloomArgs.ERROR);
188+
args.Add(error);
189+
}
190+
191+
if (expansion != null)
192+
{
193+
args.Add(BloomArgs.EXPANSION);
194+
args.Add(expansion);
195+
}
196+
197+
if (nocreate)
198+
{
199+
args.Add(BloomArgs.NOCREATE);
200+
201+
}
202+
203+
if (nonscaling)
204+
{
205+
args.Add(BloomArgs.NONSCALING);
206+
}
207+
208+
args.Add(BloomArgs.ITEMS);
209+
foreach (var item in items)
210+
{
211+
args.Add(item);
212+
}
213+
214+
var result = await _db.ExecuteAsync(BF.INSERT, args);
215+
return ResponseParser.ToBooleanArray(result);
216+
}
217+
115218
/// <summary>
116219
/// Restores a filter previosly saved using SCANDUMP.
117220
/// </summary>
@@ -125,6 +228,20 @@ public bool LoadChunk(RedisKey key, long iterator, Byte[] data)
125228
return ResponseParser.ParseOKtoBoolean(_db.Execute(BF.LOADCHUNK, key, iterator, data));
126229
}
127230

231+
/// <summary>
232+
/// Restores a filter previosly saved using SCANDUMP.
233+
/// </summary>
234+
/// <param name="key">Name of the key to restore.</param>
235+
/// <param name="iterator">Iterator value associated with data (returned by SCANDUMP).</param>
236+
/// <param name="data">Current data chunk (returned by SCANDUMP).</param>
237+
/// <returns>Array with information of the filter.</returns>
238+
/// <remarks><seealso href="https://redis.io/commands/bf.loadchunk"/></remarks>
239+
public async Task<bool> LoadChunkAsync(RedisKey key, long iterator, Byte[] data)
240+
{
241+
var result = await _db.ExecuteAsync(BF.LOADCHUNK, key, iterator, data);
242+
return ResponseParser.ParseOKtoBoolean(result);
243+
}
244+
128245
/// <summary>
129246
/// Adds one or more items to the Bloom Filter. A filter will be created if it does not exist yet.
130247
/// </summary>
@@ -148,6 +265,30 @@ public bool[] MAdd(RedisKey key, RedisValue[] items)
148265
return ResponseParser.ToBooleanArray(_db.Execute(BF.MADD, args));
149266
}
150267

268+
/// <summary>
269+
/// Adds one or more items to the Bloom Filter. A filter will be created if it does not exist yet.
270+
/// </summary>
271+
/// <param name="key">The name of the filter.</param>
272+
/// <param name="items">One or more items to add.</param>
273+
/// <returns>An array of booleans. Each element is either true or false depending on whether the
274+
/// corresponding input element was newly added to the filter or may have previously existed.</returns>
275+
/// <remarks><seealso href="https://redis.io/commands/bf.madd"/></remarks>
276+
public async Task<bool[]> MAddAsync(RedisKey key, RedisValue[] items)
277+
{
278+
if (items == null)
279+
throw new ArgumentNullException(nameof(items));
280+
281+
List<object> args = new List<object> { key };
282+
283+
foreach (var item in items)
284+
{
285+
args.Add(item);
286+
}
287+
288+
var result = await _db.ExecuteAsync(BF.MADD, args);
289+
return ResponseParser.ToBooleanArray(result);
290+
}
291+
151292
/// <summary>
152293
/// Checks whether one or more items may exist in the filter or not.
153294
/// </summary>
@@ -172,6 +313,31 @@ public bool[] MExists(RedisKey key, RedisValue[] items)
172313

173314
}
174315

316+
/// <summary>
317+
/// Checks whether one or more items may exist in the filter or not.
318+
/// </summary>
319+
/// <param name="key">The name of the filter.</param>
320+
/// <param name="items">One or more items to check.</param>
321+
/// <returns>An array of booleans, for each item <see langword="true"/> means the item may exist in the filter,
322+
/// and <see langword="false"/> means the item may exist in the filter.</returns>
323+
/// <remarks><seealso href="https://redis.io/commands/bf.mexists"/></remarks>
324+
public async Task<bool[]> MExistsAsync(RedisKey key, RedisValue[] items)
325+
{
326+
if (items == null)
327+
throw new ArgumentNullException(nameof(items));
328+
329+
List<object> args = new List<object> { key };
330+
331+
foreach (var item in items)
332+
{
333+
args.Add(item);
334+
}
335+
336+
var result = await _db.ExecuteAsync(BF.MEXISTS, args);
337+
return ResponseParser.ToBooleanArray(result);
338+
339+
}
340+
175341
/// <summary>
176342
/// Creates a new Bloom Filter.
177343
/// </summary>
@@ -202,6 +368,37 @@ public bool Reserve(RedisKey key, double errorRate, long capacity,
202368
return ResponseParser.ParseOKtoBoolean(_db.Execute(BF.RESERVE, args));
203369
}
204370

371+
/// <summary>
372+
/// Creates a new Bloom Filter.
373+
/// </summary>
374+
/// <param name="key">The key under which the filter is found.</param>
375+
/// <param name="errorRate">The desired probability for false positives (value between 0 to 1).</param>
376+
/// <param name="capacity">The number of entries intended to be added to the filter.</param>
377+
/// <param name="expansion">(Optional) When capacity is reached, an additional sub-filter is
378+
/// created in size of the last sub-filter multiplied by expansion.</param>
379+
/// <param name="nonscaling">(Optional) <see langword="true"/> toprevent the filter
380+
/// from creating additional sub-filters if initial capacity is reached.</param>
381+
/// <returns><see langword="true"/> if executed correctly, <see langword="false"/> otherwise.</returns>
382+
/// <remarks><seealso href="https://redis.io/commands/bf.reserve"/></remarks>
383+
public async Task<bool> ReserveAsync(RedisKey key, double errorRate, long capacity,
384+
int? expansion = null, bool nonscaling = false)
385+
{
386+
List<object> args = new List<object> { key, errorRate, capacity };
387+
388+
if (expansion != null)
389+
{
390+
args.Add(expansion);
391+
}
392+
393+
if (nonscaling)
394+
{
395+
args.Add(BloomArgs.NONSCALING);
396+
}
397+
398+
var result = await _db.ExecuteAsync(BF.RESERVE, args);
399+
return ResponseParser.ParseOKtoBoolean(result);
400+
}
401+
205402
/// <summary>
206403
/// Restores a filter previosly saved using SCANDUMP.
207404
/// </summary>
@@ -213,5 +410,18 @@ public bool Reserve(RedisKey key, double errorRate, long capacity,
213410
{
214411
return ResponseParser.ToScanDumpTuple(_db.Execute(BF.SCANDUMP, key, iterator));
215412
}
413+
414+
/// <summary>
415+
/// Restores a filter previosly saved using SCANDUMP.
416+
/// </summary>
417+
/// <param name="key">Name of the filter.</param>
418+
/// <param name="iterator">Iterator value; either 0 or the iterator from a previous invocation of this command.</param>
419+
/// <returns>Tuple of iterator and data.</returns>
420+
/// <remarks><seealso href="https://redis.io/commands/bf.scandump"/></remarks>
421+
public async Task<Tuple<long,Byte[]>?> ScanDumpAsync(RedisKey key, long iterator)
422+
{
423+
var result = await _db.ExecuteAsync(BF.SCANDUMP, key, iterator);
424+
return ResponseParser.ToScanDumpTuple(result);
425+
}
216426
}
217427
}

0 commit comments

Comments
 (0)