Repository navigation
Expand file tree
/
Copy pathCmsCommands.cs
More file actions
78 lines (65 loc) · 2.94 KB
/
Copy pathCmsCommands.cs
File metadata and controls
78 lines (65 loc) · 2.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
using NRedisStack.CountMinSketch.DataTypes;
using StackExchange.Redis;
namespace NRedisStack;
/// <summary>
/// The original synchronous Count-Min Sketch surface, served from the <see cref="RespCountMinSketch"/> group.
/// </summary>
/// <remarks>
/// The group is async-only, as StackExchange.Redis's own groups are. The synchronous methods here send through a
/// <b>blocking</b> context (<c>db.Context.Blocking()</c>): every send then completes on the calling thread and the
/// <see cref="ValueTask"/> comes back already completed, so <c>GetAwaiter().GetResult()</c> is a read, not a wait.
/// This is how the synchronous <see cref="IDatabase"/> methods are implemented too.
/// </remarks>
public class CmsCommands : CmsCommandsAsync, ICmsCommands
{
private readonly IDatabase _db;
private readonly RespCountMinSketch _blocking;
public CmsCommands(IDatabase db) : base(db)
{
_db = db;
// once, not per call: a context is immutable and the database's does not change, and Blocking()
// allocates a new one each time it is asked - the same reason RedisDatabase keeps its own
_blocking = db.Context.Blocking().CountMinSketch;
}
private RespCountMinSketch Group
{
get
{
_db.SetLibraryInfoOnce();
return _blocking;
}
}
/// <inheritdoc/>
public long IncrBy(RedisKey key, RedisValue item, long increment)
=> Group.IncrByAsync(key, item, increment).GetAwaiter().GetResult();
/// <inheritdoc/>
public long[] IncrBy(RedisKey key, Tuple<RedisValue, long>[] itemIncrements)
=> ToArray(Group.IncrByAsync(key, ToPairs(itemIncrements)));
/// <inheritdoc/>
public CmsInformation Info(RedisKey key)
=> Group.InfoAsync(key).GetAwaiter().GetResult();
/// <inheritdoc/>
public bool InitByDim(RedisKey key, long width, long depth)
=> True(Group.InitByDimAsync(key, width, depth));
/// <inheritdoc/>
public bool InitByProb(RedisKey key, double error, double probability)
=> True(Group.InitByProbAsync(key, error, probability));
/// <inheritdoc/>
public bool Merge(RedisValue destination, long numKeys, RedisValue[] source, long[]? weight = null)
=> True(Group.MergeAsync(ToKey(destination), ToKeys(source, numKeys), weight ?? default(ReadOnlySpan<long>)));
/// <inheritdoc/>
public long[] Query(RedisKey key, params RedisValue[] items)
=> ToArray(Group.QueryAsync(key, items));
// the old surface reported "OK" as true, and threw otherwise; the new one just completes or throws
private static bool True(ValueTask completed)
{
completed.GetAwaiter().GetResult();
return true;
}
// the old surface promised an array the caller owns; the group hands back a pooled lease
private static long[] ToArray(ValueTask<ReadOnlyLease<long>> completed)
{
using var lease = completed.GetAwaiter().GetResult();
return lease.ToArray();
}
}