Skip to content

Commit 17a9817

Browse files
authored
Hyperloglog commands (#92)
Signed-off-by: Alex Rehnby-Martin <[email protected]>
1 parent 011fa15 commit 17a9817

File tree

9 files changed

+551
-4
lines changed

9 files changed

+551
-4
lines changed

sources/Valkey.Glide/Abstract/IDatabaseAsync.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace Valkey.Glide;
88
/// Describes functionality that is common to both standalone and cluster servers.<br />
99
/// See also <see cref="GlideClient" /> and <see cref="GlideClusterClient" />.
1010
/// </summary>
11-
public interface IDatabaseAsync : IConnectionManagementCommands, IGenericCommands, IGenericBaseCommands, IHashCommands, IListCommands, IServerManagementCommands, ISetCommands, ISortedSetCommands, IStringCommands
11+
public interface IDatabaseAsync : IConnectionManagementCommands, IGenericCommands, IGenericBaseCommands, IHashCommands, IHyperLogLogCommands, IListCommands, IServerManagementCommands, ISetCommands, ISortedSetCommands, IStringCommands
1212
{
1313
/// <summary>
1414
/// Execute an arbitrary command against the server; this is primarily intended for executing modules,
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
2+
3+
using Valkey.Glide.Commands;
4+
using Valkey.Glide.Internals;
5+
6+
namespace Valkey.Glide;
7+
8+
public abstract partial class BaseClient : IHyperLogLogCommands
9+
{
10+
public async Task<bool> HyperLogLogAddAsync(ValkeyKey key, ValkeyValue element, CommandFlags flags = CommandFlags.None)
11+
{
12+
Utils.Requires<NotImplementedException>(flags == CommandFlags.None, "Command flags are not supported by GLIDE");
13+
return await Command(Request.HyperLogLogAddAsync(key, element));
14+
}
15+
16+
public async Task<bool> HyperLogLogAddAsync(ValkeyKey key, ValkeyValue[] elements, CommandFlags flags = CommandFlags.None)
17+
{
18+
Utils.Requires<NotImplementedException>(flags == CommandFlags.None, "Command flags are not supported by GLIDE");
19+
return await Command(Request.HyperLogLogAddAsync(key, elements));
20+
}
21+
22+
public async Task<long> HyperLogLogLengthAsync(ValkeyKey key, CommandFlags flags = CommandFlags.None)
23+
{
24+
Utils.Requires<NotImplementedException>(flags == CommandFlags.None, "Command flags are not supported by GLIDE");
25+
return await Command(Request.HyperLogLogLengthAsync(key));
26+
}
27+
28+
public async Task<long> HyperLogLogLengthAsync(ValkeyKey[] keys, CommandFlags flags = CommandFlags.None)
29+
{
30+
Utils.Requires<NotImplementedException>(flags == CommandFlags.None, "Command flags are not supported by GLIDE");
31+
return await Command(Request.HyperLogLogLengthAsync(keys));
32+
}
33+
34+
public async Task HyperLogLogMergeAsync(ValkeyKey destination, ValkeyKey first, ValkeyKey second, CommandFlags flags = CommandFlags.None)
35+
{
36+
Utils.Requires<NotImplementedException>(flags == CommandFlags.None, "Command flags are not supported by GLIDE");
37+
await Command(Request.HyperLogLogMergeAsync(destination, first, second));
38+
}
39+
40+
public async Task HyperLogLogMergeAsync(ValkeyKey destination, ValkeyKey[] sourceKeys, CommandFlags flags = CommandFlags.None)
41+
{
42+
Utils.Requires<NotImplementedException>(flags == CommandFlags.None, "Command flags are not supported by GLIDE");
43+
await Command(Request.HyperLogLogMergeAsync(destination, sourceKeys));
44+
}
45+
}
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
2+
3+
namespace Valkey.Glide.Commands;
4+
5+
/// <summary>
6+
/// Supports commands for the "HyperLogLog" group for a standalone client.
7+
/// <br />
8+
/// See <see href="https://valkey.io/commands#hyperloglog">HyperLogLog Commands</see>.
9+
/// </summary>
10+
public interface IHyperLogLogCommands
11+
{
12+
/// <summary>
13+
/// Adds one element to the HyperLogLog data structure stored at the specified key.
14+
/// </summary>
15+
/// <seealso href="https://valkey.io/commands/pfadd/"/>
16+
/// <param name="key">The key of the HyperLogLog.</param>
17+
/// <param name="element">The element to add to the HyperLogLog.</param>
18+
/// <param name="flags">The command flags. Currently flags are ignored.</param>
19+
/// <returns>
20+
/// <see langword="true"/> if at least one HyperLogLog internal register was altered,
21+
/// <see langword="false"/> otherwise.
22+
/// </returns>
23+
/// <remarks>
24+
/// <example>
25+
/// <code>
26+
/// bool result = await client.HyperLogLogAddAsync("my_hll", "element1");
27+
/// Console.WriteLine(result); // Output: True (if this is a new element)
28+
/// </code>
29+
/// </example>
30+
/// </remarks>
31+
Task<bool> HyperLogLogAddAsync(ValkeyKey key, ValkeyValue element, CommandFlags flags = CommandFlags.None);
32+
33+
/// <summary>
34+
/// Adds multiple elements to the HyperLogLog data structure stored at the specified key.
35+
/// </summary>
36+
/// <seealso href="https://valkey.io/commands/pfadd/"/>
37+
/// <param name="key">The key of the HyperLogLog.</param>
38+
/// <param name="elements">The elements to add to the HyperLogLog.</param>
39+
/// <param name="flags">The command flags. Currently flags are ignored.</param>
40+
/// <returns>
41+
/// <see langword="true"/> if at least one HyperLogLog internal register was altered,
42+
/// <see langword="false"/> otherwise.
43+
/// </returns>
44+
/// <remarks>
45+
/// <example>
46+
/// <code>
47+
/// bool result = await client.HyperLogLogAddAsync("my_hll", ["element1", "element2", "element3"]);
48+
/// Console.WriteLine(result); // Output: True (if at least one element is new)
49+
/// </code>
50+
/// </example>
51+
/// </remarks>
52+
Task<bool> HyperLogLogAddAsync(ValkeyKey key, ValkeyValue[] elements, CommandFlags flags = CommandFlags.None);
53+
54+
/// <summary>
55+
/// Returns the approximated cardinality computed by the HyperLogLog data structure stored at the specified key.
56+
/// </summary>
57+
/// <seealso href="https://valkey.io/commands/pfcount/"/>
58+
/// <param name="key">The key of the HyperLogLog.</param>
59+
/// <param name="flags">The command flags. Currently flags are ignored.</param>
60+
/// <returns>
61+
/// The approximated number of unique elements observed by the HyperLogLog at key.
62+
/// </returns>
63+
/// <remarks>
64+
/// <example>
65+
/// <code>
66+
/// long count = await client.HyperLogLogLengthAsync("my_hll");
67+
/// Console.WriteLine(count); // Output: approximated cardinality
68+
/// </code>
69+
/// </example>
70+
/// </remarks>
71+
Task<long> HyperLogLogLengthAsync(ValkeyKey key, CommandFlags flags = CommandFlags.None);
72+
73+
/// <summary>
74+
/// Returns the approximated cardinality of the union of the HyperLogLogs stored at the specified keys.
75+
/// </summary>
76+
/// <seealso href="https://valkey.io/commands/pfcount/"/>
77+
/// <param name="keys">The keys of the HyperLogLogs.</param>
78+
/// <param name="flags">The command flags. Currently flags are ignored.</param>
79+
/// <returns>
80+
/// The approximated number of unique elements observed by the union of the HyperLogLogs.
81+
/// </returns>
82+
/// <remarks>
83+
/// <example>
84+
/// <code>
85+
/// long count = await client.HyperLogLogLengthAsync(["hll1", "hll2", "hll3"]);
86+
/// Console.WriteLine(count); // Output: approximated cardinality of union
87+
/// </code>
88+
/// </example>
89+
/// </remarks>
90+
Task<long> HyperLogLogLengthAsync(ValkeyKey[] keys, CommandFlags flags = CommandFlags.None);
91+
92+
/// <summary>
93+
/// Merges multiple HyperLogLog values into a unique value that will approximate the cardinality of the union of the observed Sets of the source HyperLogLog structures.
94+
/// </summary>
95+
/// <seealso href="https://valkey.io/commands/pfmerge/"/>
96+
/// <param name="destination">The key of the destination HyperLogLog.</param>
97+
/// <param name="first">The key of the first source HyperLogLog.</param>
98+
/// <param name="second">The key of the second source HyperLogLog.</param>
99+
/// <param name="flags">The command flags. Currently flags are ignored.</param>
100+
/// <returns>A task that represents the asynchronous operation.</returns>
101+
/// <remarks>
102+
/// <example>
103+
/// <code>
104+
/// await client.HyperLogLogMergeAsync("dest_hll", "hll1", "hll2");
105+
/// </code>
106+
/// </example>
107+
/// </remarks>
108+
Task HyperLogLogMergeAsync(ValkeyKey destination, ValkeyKey first, ValkeyKey second, CommandFlags flags = CommandFlags.None);
109+
110+
/// <summary>
111+
/// Merges multiple HyperLogLog values into a unique value that will approximate the cardinality of the union of the observed Sets of the source HyperLogLog structures.
112+
/// </summary>
113+
/// <seealso href="https://valkey.io/commands/pfmerge/"/>
114+
/// <param name="destination">The key of the destination HyperLogLog.</param>
115+
/// <param name="sourceKeys">The keys of the source HyperLogLogs.</param>
116+
/// <param name="flags">The command flags. Currently flags are ignored.</param>
117+
/// <returns>A task that represents the asynchronous operation.</returns>
118+
/// <remarks>
119+
/// <example>
120+
/// <code>
121+
/// await client.HyperLogLogMergeAsync("dest_hll", ["hll1", "hll2", "hll3"]);
122+
/// </code>
123+
/// </example>
124+
/// </remarks>
125+
Task HyperLogLogMergeAsync(ValkeyKey destination, ValkeyKey[] sourceKeys, CommandFlags flags = CommandFlags.None);
126+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
2+
3+
using static Valkey.Glide.Internals.FFI;
4+
5+
namespace Valkey.Glide.Internals;
6+
7+
internal partial class Request
8+
{
9+
/// <summary>
10+
/// Creates a command to add one element to a HyperLogLog data structure.
11+
/// </summary>
12+
/// <param name="key">The key of the HyperLogLog.</param>
13+
/// <param name="element">The element to add.</param>
14+
/// <returns>A command that adds the element to the HyperLogLog and returns true if altered.</returns>
15+
public static Cmd<bool, bool> HyperLogLogAddAsync(ValkeyKey key, ValkeyValue element)
16+
=> Simple<bool>(RequestType.PfAdd, [key.ToGlideString(), element.ToGlideString()]);
17+
18+
/// <summary>
19+
/// Creates a command to add multiple elements to a HyperLogLog data structure.
20+
/// </summary>
21+
/// <param name="key">The key of the HyperLogLog.</param>
22+
/// <param name="elements">The elements to add.</param>
23+
/// <returns>A command that adds the elements to the HyperLogLog and returns true if altered.</returns>
24+
public static Cmd<bool, bool> HyperLogLogAddAsync(ValkeyKey key, ValkeyValue[] elements)
25+
{
26+
GlideString[] args = new GlideString[elements.Length + 1];
27+
args[0] = key.ToGlideString();
28+
for (int i = 0; i < elements.Length; i++)
29+
{
30+
args[i + 1] = elements[i].ToGlideString();
31+
}
32+
return Simple<bool>(RequestType.PfAdd, args);
33+
}
34+
35+
/// <summary>
36+
/// Creates a command to get the cardinality of a HyperLogLog data structure.
37+
/// </summary>
38+
/// <param name="key">The key of the HyperLogLog.</param>
39+
/// <returns>A command that returns the approximated cardinality of the HyperLogLog.</returns>
40+
public static Cmd<long, long> HyperLogLogLengthAsync(ValkeyKey key)
41+
=> Simple<long>(RequestType.PfCount, [key.ToGlideString()]);
42+
43+
/// <summary>
44+
/// Creates a command to get the cardinality of the union of multiple HyperLogLog data structures.
45+
/// </summary>
46+
/// <param name="keys">The keys of the HyperLogLogs.</param>
47+
/// <returns>A command that returns the approximated cardinality of the union of HyperLogLogs.</returns>
48+
public static Cmd<long, long> HyperLogLogLengthAsync(ValkeyKey[] keys)
49+
=> Simple<long>(RequestType.PfCount, keys.ToGlideStrings());
50+
51+
/// <summary>
52+
/// Creates a command to merge HyperLogLog data structures.
53+
/// </summary>
54+
/// <param name="destination">The key of the destination HyperLogLog.</param>
55+
/// <param name="first">The key of the first source HyperLogLog.</param>
56+
/// <param name="second">The key of the second source HyperLogLog.</param>
57+
/// <returns>A command that merges the HyperLogLogs.</returns>
58+
public static Cmd<string, string> HyperLogLogMergeAsync(ValkeyKey destination, ValkeyKey first, ValkeyKey second)
59+
=> OK(RequestType.PfMerge, [destination.ToGlideString(), first.ToGlideString(), second.ToGlideString()]);
60+
61+
/// <summary>
62+
/// Creates a command to merge multiple HyperLogLog data structures.
63+
/// </summary>
64+
/// <param name="destination">The key of the destination HyperLogLog.</param>
65+
/// <param name="sourceKeys">The keys of the source HyperLogLogs.</param>
66+
/// <returns>A command that merges the HyperLogLogs.</returns>
67+
public static Cmd<string, string> HyperLogLogMergeAsync(ValkeyKey destination, ValkeyKey[] sourceKeys)
68+
{
69+
GlideString[] args = new GlideString[sourceKeys.Length + 1];
70+
args[0] = destination.ToGlideString();
71+
for (int i = 0; i < sourceKeys.Length; i++)
72+
{
73+
args[i + 1] = sourceKeys[i].ToGlideString();
74+
}
75+
return OK(RequestType.PfMerge, args);
76+
}
77+
}

sources/Valkey.Glide/Pipeline/BaseBatch.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,31 @@ internal T AddCmd(ICmd cmd)
6565
/// <inheritdoc cref="IBatch.Info(Section[])" />
6666
public T Info(Section[] sections) => AddCmd(Request.Info(sections));
6767

68+
/// <inheritdoc cref="IBatchHyperLogLogCommands.HyperLogLogAdd(ValkeyKey, ValkeyValue)" />
69+
public T HyperLogLogAdd(ValkeyKey key, ValkeyValue element) => AddCmd(Request.HyperLogLogAddAsync(key, element));
70+
71+
/// <inheritdoc cref="IBatchHyperLogLogCommands.HyperLogLogAdd(ValkeyKey, ValkeyValue[])" />
72+
public T HyperLogLogAdd(ValkeyKey key, ValkeyValue[] elements) => AddCmd(Request.HyperLogLogAddAsync(key, elements));
73+
74+
/// <inheritdoc cref="IBatchHyperLogLogCommands.HyperLogLogLength(ValkeyKey)" />
75+
public T HyperLogLogLength(ValkeyKey key) => AddCmd(Request.HyperLogLogLengthAsync(key));
76+
77+
/// <inheritdoc cref="IBatchHyperLogLogCommands.HyperLogLogLength(ValkeyKey[])" />
78+
public T HyperLogLogLength(ValkeyKey[] keys) => AddCmd(Request.HyperLogLogLengthAsync(keys));
79+
80+
/// <inheritdoc cref="IBatchHyperLogLogCommands.HyperLogLogMerge(ValkeyKey, ValkeyKey, ValkeyKey)" />
81+
public T HyperLogLogMerge(ValkeyKey destination, ValkeyKey first, ValkeyKey second) => AddCmd(Request.HyperLogLogMergeAsync(destination, first, second));
82+
83+
/// <inheritdoc cref="IBatchHyperLogLogCommands.HyperLogLogMerge(ValkeyKey, ValkeyKey[])" />
84+
public T HyperLogLogMerge(ValkeyKey destination, ValkeyKey[] sourceKeys) => AddCmd(Request.HyperLogLogMergeAsync(destination, sourceKeys));
85+
6886
IBatch IBatch.CustomCommand(GlideString[] args) => CustomCommand(args);
6987
IBatch IBatch.Info() => Info();
7088
IBatch IBatch.Info(Section[] sections) => Info(sections);
89+
IBatch IBatchHyperLogLogCommands.HyperLogLogAdd(ValkeyKey key, ValkeyValue element) => HyperLogLogAdd(key, element);
90+
IBatch IBatchHyperLogLogCommands.HyperLogLogAdd(ValkeyKey key, ValkeyValue[] elements) => HyperLogLogAdd(key, elements);
91+
IBatch IBatchHyperLogLogCommands.HyperLogLogLength(ValkeyKey key) => HyperLogLogLength(key);
92+
IBatch IBatchHyperLogLogCommands.HyperLogLogLength(ValkeyKey[] keys) => HyperLogLogLength(keys);
93+
IBatch IBatchHyperLogLogCommands.HyperLogLogMerge(ValkeyKey destination, ValkeyKey first, ValkeyKey second) => HyperLogLogMerge(destination, first, second);
94+
IBatch IBatchHyperLogLogCommands.HyperLogLogMerge(ValkeyKey destination, ValkeyKey[] sourceKeys) => HyperLogLogMerge(destination, sourceKeys);
7195
}

sources/Valkey.Glide/Pipeline/IBatch.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
namespace Valkey.Glide.Pipeline;
88

99
// BaseBatch was split into two types, one for docs, another for the impl. This also ease the testing.
10-
internal interface IBatch : IBatchSetCommands, IBatchStringCommands, IBatchListCommands, IBatchSortedSetCommands, IBatchGenericCommands, IBatchConnectionManagementCommands, IBatchHashCommands, IBatchServerManagementCommands
10+
internal interface IBatch : IBatchSetCommands, IBatchStringCommands, IBatchListCommands, IBatchSortedSetCommands, IBatchGenericCommands, IBatchConnectionManagementCommands, IBatchHashCommands, IBatchServerManagementCommands, IBatchHyperLogLogCommands
1111
{
1212
// inherit all docs except `remarks` section which stores en example (not relevant for batch)
1313
// and returns section, because we customize it.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
2+
3+
using Valkey.Glide.Commands;
4+
5+
namespace Valkey.Glide.Pipeline;
6+
7+
/// <summary>
8+
/// Supports commands for the "HyperLogLog" group for batch operations.
9+
/// </summary>
10+
internal interface IBatchHyperLogLogCommands
11+
{
12+
/// <inheritdoc cref="IHyperLogLogCommands.HyperLogLogAddAsync(ValkeyKey, ValkeyValue, CommandFlags)" path="/summary" />
13+
/// <inheritdoc cref="IHyperLogLogCommands.HyperLogLogAddAsync(ValkeyKey, ValkeyValue, CommandFlags)" path="/param" />
14+
/// <returns>Command Response - <inheritdoc cref="IHyperLogLogCommands.HyperLogLogAddAsync(ValkeyKey, ValkeyValue, CommandFlags)" /></returns>
15+
IBatch HyperLogLogAdd(ValkeyKey key, ValkeyValue element);
16+
17+
/// <inheritdoc cref="IHyperLogLogCommands.HyperLogLogAddAsync(ValkeyKey, ValkeyValue[], CommandFlags)" path="/summary" />
18+
/// <inheritdoc cref="IHyperLogLogCommands.HyperLogLogAddAsync(ValkeyKey, ValkeyValue[], CommandFlags)" path="/param" />
19+
/// <returns>Command Response - <inheritdoc cref="IHyperLogLogCommands.HyperLogLogAddAsync(ValkeyKey, ValkeyValue[], CommandFlags)" /></returns>
20+
IBatch HyperLogLogAdd(ValkeyKey key, ValkeyValue[] elements);
21+
22+
/// <inheritdoc cref="IHyperLogLogCommands.HyperLogLogLengthAsync(ValkeyKey, CommandFlags)" path="/summary" />
23+
/// <inheritdoc cref="IHyperLogLogCommands.HyperLogLogLengthAsync(ValkeyKey, CommandFlags)" path="/param" />
24+
/// <returns>Command Response - <inheritdoc cref="IHyperLogLogCommands.HyperLogLogLengthAsync(ValkeyKey, CommandFlags)" /></returns>
25+
IBatch HyperLogLogLength(ValkeyKey key);
26+
27+
/// <inheritdoc cref="IHyperLogLogCommands.HyperLogLogLengthAsync(ValkeyKey[], CommandFlags)" path="/summary" />
28+
/// <inheritdoc cref="IHyperLogLogCommands.HyperLogLogLengthAsync(ValkeyKey[], CommandFlags)" path="/param" />
29+
/// <returns>Command Response - <inheritdoc cref="IHyperLogLogCommands.HyperLogLogLengthAsync(ValkeyKey[], CommandFlags)" /></returns>
30+
IBatch HyperLogLogLength(ValkeyKey[] keys);
31+
32+
/// <inheritdoc cref="IHyperLogLogCommands.HyperLogLogMergeAsync(ValkeyKey, ValkeyKey, ValkeyKey, CommandFlags)" path="/summary" />
33+
/// <inheritdoc cref="IHyperLogLogCommands.HyperLogLogMergeAsync(ValkeyKey, ValkeyKey, ValkeyKey, CommandFlags)" path="/param" />
34+
/// <returns>Command Response - <inheritdoc cref="IHyperLogLogCommands.HyperLogLogMergeAsync(ValkeyKey, ValkeyKey, ValkeyKey, CommandFlags)" /></returns>
35+
IBatch HyperLogLogMerge(ValkeyKey destination, ValkeyKey first, ValkeyKey second);
36+
37+
/// <inheritdoc cref="IHyperLogLogCommands.HyperLogLogMergeAsync(ValkeyKey, ValkeyKey[], CommandFlags)" path="/summary" />
38+
/// <inheritdoc cref="IHyperLogLogCommands.HyperLogLogMergeAsync(ValkeyKey, ValkeyKey[], CommandFlags)" path="/param" />
39+
/// <returns>Command Response - <inheritdoc cref="IHyperLogLogCommands.HyperLogLogMergeAsync(ValkeyKey, ValkeyKey[], CommandFlags)" /></returns>
40+
IBatch HyperLogLogMerge(ValkeyKey destination, ValkeyKey[] sourceKeys);
41+
}

0 commit comments

Comments
 (0)