Ruvio.Client
0.2.9
See the version list below for details.
dotnet add package Ruvio.Client --version 0.2.9
NuGet\Install-Package Ruvio.Client -Version 0.2.9
<PackageReference Include="Ruvio.Client" Version="0.2.9" />
<PackageVersion Include="Ruvio.Client" Version="0.2.9" />
<PackageReference Include="Ruvio.Client" />
paket add Ruvio.Client --version 0.2.9
#r "nuget: Ruvio.Client, 0.2.9"
#:package Ruvio.Client@0.2.9
#addin nuget:?package=Ruvio.Client&version=0.2.9
#tool nuget:?package=Ruvio.Client&version=0.2.9
Ruvio.Client
Binary commands
IRuvioClient.ExecuteBinaryAsync(IReadOnlyList<ReadOnlyMemory<byte>>, CancellationToken)
sends raw RESP bulk arguments without UTF-8/base64 conversion; binary replies are in
RespValue.Bytes. Keep argument memory unchanged until the operation completes.
The default interface implementation throws NotSupportedException, so existing
implementations remain compatible but must opt into binary support.
await client.ExecuteBinaryAsync(new ReadOnlyMemory<byte>[]
{
"SET"u8.ToArray(), "binary-key"u8.ToArray(), new byte[] { 0, 255, 128 }
}, cancellationToken);
This API never replays a command after a transport failure; cancellation after dispatch does not establish whether the server executed it. Explicit MOVED rejections may redirect. Standalone mode accepts arbitrary commands. Cluster mode supports GET, SET, DEL, UNLINK, EXISTS, HGET, HSET, HMGET, HMSET, HDEL, PEXPIRE, PEXPIREAT, PTTL, TTL, PERSIST, IDEM, EVAL, EVALSHA, PING, and ECHO. Binary keys use raw-byte hash slots; all keys must share one slot. Cross-slot splitting and cluster transactions are deliberately not supported by this API; unsupported commands fail explicitly. Existing string APIs are unchanged.
RESP2 client for Ruvio. Connecting does not send CLIENT SETINFO or HELLO. The typed methods cover every command in docs/compatibility-matrix.json and the options that change what Ruvio does. FLUSHDB ASYNC (it runs synchronously) and HELLO AUTH/SETNAME have no typed form. Anything else can go through ExecuteAsync with the same argument lists as redis-cli.
Reads start with Get. Writes use the mutation: Set, Add, Remove, Delete, Increment. A range that returns values is GetSortedSetRangeByRankWithScoresAsync.
using Ruvio.Client;
await using var db = await RuvioClient.ConnectAsync("127.0.0.1", 6379);
await db.SubscribeAsync("news", msg => Console.WriteLine(msg.Payload));
await db.PublishAsync("news", "hello");
await db.AddSortedSetAsync("leaderboard", ("player2", 50), ("player1", 100));
IReadOnlyList<SortedSetEntry> rows = await db.GetSortedSetRangeByRankWithScoresAsync(
"leaderboard",
0,
-1,
descending: true);
Connecting
Native idempotency is exposed as BeginIdempotencyAsync(key, fingerprint, owner, ttlMs) and CompleteIdempotencyAsync(key, fingerprint, owner, result).
Begin returns a RESP array (acquired, pending, conflict, or completed plus
result bytes); complete returns a boolean acknowledgment. The completion helper
takes text; ExecuteBinaryAsync supports arbitrary binary tokens/results with
IDEM key BEGIN ... / IDEM key COMPLETE .... No Lua is loaded.
Only acquired authorizes the caller to execute its operation. Neither replay
nor completion renews retention, and no ambiguous write is automatically retried.
See the native contract before using it for
external side effects.
Give the client one address. On connect it sends CLUSTER SLOTS. A standalone server replies with an error and the client keeps that one socket. A sharded server returns the slot map; the client then opens one socket per shard and sends each command to the shard that owns the key. MOVED refreshes the map and retries. Multi-key reads and writes (MGET, MSET, DEL, UNLINK, EXISTS, TOUCH) are split by slot and merged. FLUSHDB, FLUSHALL, and DBSIZE go to every shard.
await using var cluster = await RuvioClient.ConnectAsync("127.0.0.1", 6379);
await cluster.SetAsync("session:ada", "hello");
await cluster.SetAsync("somekey", "on-another-shard");
IReadOnlyList<string?> values = await cluster.GetManyAsync("session:ada", "somekey");
RuvioClient.GetHashSlot(key) is the same 0–16383 slot Ruvio uses, including {hash tags}. Set RuvioClientOptions.DiscoverCluster to false to stay on the seed socket.
The library is marked AOT-compatible. Ruvio.Client.Tour publishes a native binary (PublishAot). Command names such as GET and GEOADD are UTF-8 spans generated from RespVerbs.txt, so a standalone GET or INCR does not allocate an argument array for the verb.
Client CPU cost, separate from socket time, is in Ruvio.Client.Benchmarks (BenchmarkDotNet). It writes a GET and a GEOADD frame, a pipeline of 32 GETs, and reads an integer, a bulk, and an array on a reused reader. It also hashes a plain key and a hash tag.
dotnet run -c Release --project clients/csharp/Ruvio.Client.Benchmarks
A standalone client is still one TCP connection bound to one logical database. Pick the database when you connect and use the client as that database:
await using var cache = await RuvioClient.ConnectAsync("127.0.0.1", 6379, database: 2);
await using var sessions = await RuvioClient.ConnectAsync(IPAddress.Loopback, 6379, database: 3);
await using var main = await RuvioClient.ConnectAsync(new IPEndPoint(IPAddress.Parse("10.0.0.5"), 6379));
await using var secured = await RuvioClient.ConnectAsync(new RuvioClientOptions
{
Host = "10.0.0.5",
Port = 6379,
Username = "app",
Password = "secret",
Database = 4,
ConnectTimeout = TimeSpan.FromSeconds(2),
});
Database 0 sends nothing after AUTH and CLUSTER SLOTS. Any other index sends SELECT after discovery, before ConnectAsync returns. Indexes run from 0 to the server's databases setting minus one (16 by default, at most 256). Cluster mode has only database 0; connecting with another index throws.
SelectAsync and GetDatabaseAsync send SELECT on the same connection; every later command on that client uses the new database. GetDatabaseAsync returns the same client, not a second socket. Open one client per database when two parts of an application need different databases at the same time.
Interfaces
RuvioClient is sealed. ConnectAsync still opens the socket and returns that object. It implements two interfaces:
IRuvioClientis the command surface (GetStringAsync,SetAsync,TakeAsync,ExecuteAsync, and the other public commands). Application services take this. A test substitute answers a command without a socket.IRuvioConnectionis the socket:IsConnected,IsCluster,ShardCount,ReconnectAsync,ConnectionLost,ConnectionRestored,ConnectionFailed, and dispose.
Ruvio.Client.AspNetCore registers one instance as RuvioClient, IRuvioClient, and IRuvioConnection. There is no GetDatabase factory that opens a second object. GetDatabaseAsync still sends SELECT and returns this client.
FlushDatabaseAsync, FlushAllDatabasesAsync, SwapDatabasesAsync, and MoveKeyAsync send FLUSHDB, FLUSHALL, SWAPDB, and MOVE. See docs/LOGICAL_DATABASES.md.
Options
| Command | Methods |
|---|---|
SET |
SetAsync (PX, NX, XX), SetAsync(key, value, DateTimeOffset) (PXAT), SetKeepingTimeToLiveAsync (KEEPTTL), SetAndGetAsync (GET) |
LPOP / RPOP |
one element or a count |
SPOP / SRANDMEMBER |
one member or a count; a negative SRANDMEMBER count may repeat |
HSCAN / SCAN |
MATCH and COUNT |
ZADD |
(member, score) tuples, SortedSetEntry, or one member, score; SortedSetAddFlags: NX, XX, GT, LT, CH; IncrementSortedSetAsync(..., flags) sends INCR |
HEXPIRE family |
ExpireHashFieldsAsync(key, ttl, [condition,] fields) sends HEXPIRE for whole seconds, otherwise HPEXPIRE; FieldExpireCondition: NX, XX, GT, LT. ExpireHashFieldsAtAsync sends HEXPIREAT or HPEXPIREAT. One reply per field |
ZPOPMIN / ZPOPMAX |
optional count; PopSortedSetMinBlockingAsync / PopSortedSetMaxBlockingAsync send BZPOPMIN / BZPOPMAX for one key or a key list |
XADD |
AddStreamEntryAsync(key, id, maxLength, ...) sends MAXLEN |
XRANGE / XREVRANGE |
optional COUNT |
XREAD / XREADGROUP |
StreamReadOptions: COUNT, BLOCK, NOACK (group reads only) |
XGROUP CREATE |
createStream: true sends MKSTREAM |
XPENDING |
summary, or the extended form with IDLE, a range, a count, and a consumer |
XCLAIM |
StreamClaimOptions: IDLE, TIME, RETRYCOUNT, FORCE, LASTID; ClaimStreamEntryIdsAsync sends JUSTID |
INFO |
optional section; prometheus returns Prometheus text |
FUNCTION LOAD |
LoadFunctionAsync(name, body); the body is plain Lua and is lost on restart |
A blocking read (BLPOP, XREAD BLOCK, XREADGROUP BLOCK) holds the connection until it returns. Use a separate client for it.
Subscribe opens a second TCP socket. GET / SET / PUBLISH stay on the command socket. Register Message or SubscribeAsync(channel, handler) (StackExchange / Garnet app style), or await foreach ListenAsync. ReadPubSubMessageAsync still works. IsConnected is false when every command socket is broken.
A dropped socket is opened again before the next command, including a shard socket in cluster mode. The command that discovers the drop fails, so a write is not applied twice. One exception: a single GET, MGET, EXISTS, HGET, TTL, or PTTL is sent once more when the socket closes before any byte of the reply arrives. A pipeline is not retried. A reply that has already started is not retried. Pub/Sub channels are subscribed again on the new socket. ConnectionLost and ConnectionRestored report that, and ConnectionFailed still fires on the drop. Set RuvioClientOptions.Reconnect to false and call ReconnectAsync yourself, or set ReconnectDelay to own the wait. ReconnectDelay returning null stops the retry.
A password is sent as AUTH only when RuvioClientOptions.Password is set. One client runs commands one at a time. ExecuteManyAsync pipelines several commands on that connection. A server error reply leaves the connection usable. A broken read or write closes it.
Unreleased
- Hash field TTLs:
ExpireHashFieldsAsync,ExpireHashFieldsAtAsync,GetHashFieldTimeToLiveAsync,GetHashFieldTimeToLiveMillisecondsAsync,GetHashFieldExpireTimeAsync,GetHashFieldExpireTimeMillisecondsAsync, andPersistHashFieldsAsyncsendHEXPIRE,HPEXPIRE,HEXPIREAT,HPEXPIREAT,HTTL,HPTTL,HEXPIRETIME,HPEXPIRETIME, andHPERSIST. AcquireSemaphoreAsyncsendsSEMAPHORE;ReleaseAsyncfrees a semaphore token as well as a lease.IncrementWithLimitAsyncsendsINCRBY key delta MAX limitand returns null when the limit would be passed.- Sorted sets:
PopSortedSetMinAsync,PopSortedSetMaxAsync,PopSortedSetMinBlockingAsync,PopSortedSetMaxBlockingAsync,RemoveSortedSetRangeByRankAsync,RemoveSortedSetRangeByScoreAsync, andRemoveSortedSetRangeByLexAsyncsendZPOPMIN,ZPOPMAX,BZPOPMIN,BZPOPMAX,ZREMRANGEBYRANK,ZREMRANGEBYSCORE, andZREMRANGEBYLEX. - A
GETsent on a socket that closed before any reply byte is sent once more on a new socket, asExecuteAsyncalready did. Before, the fastGETpath threw instead.
0.2.7
- The library is AOT-compatible and trimmable.
Ruvio.Client.Tourpublishes a native binary. GET,INCR, andGEOADDon a standalone connection write the command name from a generated UTF-8 span.
0.2.6
- A dropped command or shard socket is opened again before the next command. The command that sees the drop fails. A single
GET,MGET,EXISTS,HGET,TTL, orPTTLis sent once more when no reply byte arrived. Pipelines are not retried. Pub/Sub channels are subscribed again on the new socket. ConnectionLostandConnectionRestored(RuvioConnectionNotice: host, port, subscriber, error).ConnectionFailedstill fires on the drop.RuvioClientOptions.Reconnect(default true),MaxReconnectAttempts,ReconnectBaseDelay,ReconnectMaxDelay, andReconnectDelay.ReconnectDelayreturning null stops the retry and ignoresMaxReconnectAttempts.ReconnectAsyncopens the socket when automatic retry is off.
0.2.5
- Pub/Sub uses a dedicated socket.
SubscribeAsync(channel, handler),Message, andListenAsyncdeliver payloads without a manual read loop on the command connection. IsConnectedandConnectionFailed.
0.2.4
DeleteAsync(key)sendsDELfor one key. The list overload remains for many keys.PopListLeftBlockingAsync(key, timeout)andPopListRightBlockingAsync(key, timeout)sendBLPOP/BRPOPwithout a key list.
0.2.3
- A
MOVEDreply after a plain connect (or with discovery off) learns the slot map and retries, soSETon the seed port no longer throws.
0.2.2
- A sharded server is discovered from one seed address. Commands are routed by hash slot,
MOVEDis followed, andMGET/MSET/DELsplit across shards. GetClusterShardsAsync,GetClusterInfoAsync,GetClusterMyIdAsync,GetClusterKeySlotAsync,ReadOnlyAsync,ReadWriteAsync.GetHashSlot,IsCluster,ShardCount, andRuvioClientOptions.DiscoverCluster.
0.2.1
AddSortedSetAsync(key, ("ada", 100), ("bob", 50))takes(member, score)tuples, with or withoutSortedSetAddFlags.AddSortedSetAsync(key, member, score)adds one member and returns whether it was new.
0.2.0
ConnectAsync(host, port, database),ConnectAsync(IPAddress, port, database),ConnectAsync(IPEndPoint, database), andRuvioClientOptions.Database.SelectAsync,GetDatabaseAsync,FlushDatabaseAsync,FlushAllDatabasesAsync,SwapDatabasesAsync,MoveKeyAsync.- The option overloads in the table above, and
PingAsync(message). - Breaking:
LoadFunctionAsync(body)becameLoadFunctionAsync(name, body). The old form sent a request Ruvio always refused.DeleteFunctionAsyncreturnsTask<bool>.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- No dependencies.
NuGet packages (6)
Showing the top 5 NuGet packages that depend on Ruvio.Client:
| Package | Downloads |
|---|---|
|
Ruvio.Client.AspNetCore
ASP.NET Core integration for the Ruvio.Client RESP2 SDK. |
|
|
Ruvio.Extensions.Caching
Binary-safe IDistributedCache integration for Ruvio. |
|
|
Ruvio.AspNetCore.RateLimiting
Opt-in distributed fixed-window HTTP rate limiting backed by Ruvio. |
|
|
Ruvio.AspNetCore.DataProtection
Append-only ASP.NET Core Data Protection key-ring storage on Ruvio. |
|
|
Ruvio.AspNetCore.OutputCaching
Binary ASP.NET Core output caching with distributed tag invalidation on Ruvio. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.3.1 | 37 | 10/10/2026 |
| 0.3.0 | 39 | 10/9/2026 |
| 0.2.13 | 106 | 10/5/2026 |
| 0.2.12 | 105 | 10/2/2026 |
| 0.2.11 | 103 | 10/2/2026 |
| 0.2.10 | 103 | 10/2/2026 |
| 0.2.9 | 178 | 10/2/2026 |
| 0.2.8 | 97 | 10/1/2026 |
| 0.2.7 | 97 | 9/30/2026 |
| 0.2.6 | 109 | 9/26/2026 |
| 0.2.5 | 115 | 9/26/2026 |
| 0.2.4 | 102 | 9/26/2026 |
| 0.2.3 | 107 | 9/26/2026 |
| 0.2.2 | 115 | 9/25/2026 |
| 0.2.1 | 116 | 9/25/2026 |
| 0.2.0 | 103 | 9/25/2026 |
| 0.1.3 | 96 | 9/23/2026 |
| 0.1.2 | 90 | 9/23/2026 |
| 0.1.1 | 103 | 9/23/2026 |
| 0.1.0 | 90 | 9/23/2026 |