Ruvio.Extensions.Caching
0.1.0
dotnet add package Ruvio.Extensions.Caching --version 0.1.0
NuGet\Install-Package Ruvio.Extensions.Caching -Version 0.1.0
<PackageReference Include="Ruvio.Extensions.Caching" Version="0.1.0" />
<PackageVersion Include="Ruvio.Extensions.Caching" Version="0.1.0" />
<PackageReference Include="Ruvio.Extensions.Caching" />
paket add Ruvio.Extensions.Caching --version 0.1.0
#r "nuget: Ruvio.Extensions.Caching, 0.1.0"
#:package Ruvio.Extensions.Caching@0.1.0
#addin nuget:?package=Ruvio.Extensions.Caching&version=0.1.0
#tool nuget:?package=Ruvio.Extensions.Caching&version=0.1.0
Ruvio.Extensions.Caching
Binary-safe IDistributedCache for .NET 8, using Microsoft.Extensions packages only;
there is no ASP.NET Core shared-framework dependency.
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.DependencyInjection;
using Ruvio.Client;
using Ruvio.Extensions.Caching;
// Connect during application startup. Keep this connection alive for the app lifetime.
await using var client = await RuvioClient.ConnectAsync("localhost", 6379);
services.AddSingleton<IRuvioClient>(client);
services.AddRuvioDistributedCache(options => options.InstanceName = "orders");
// Resolve IDistributedCache through DI in application code.
await cache.SetAsync("invoice:42", new byte[] { 0, 255, 128 },
new DistributedCacheEntryOptions
{
SlidingExpiration = TimeSpan.FromMinutes(5),
AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1)
}, cancellationToken);
The application owns the client. This provider never connects or disposes it.
An injected substitute must implement IRuvioClient.ExecuteBinaryAsync; the default
interface implementation explicitly rejects unsupported binary commands. Registration
uses TryAdd, preserving an existing IDistributedCache. Options are validated at
registration and construction and then snapshotted; no hot reload is performed.
Contract and expiration
- Empty keys and zero-byte values are valid; null keys, values, and entry options are rejected. A missing key returns null; an empty value returns an empty array.
- All byte values round-trip directly as RESP bulk strings, including invalid UTF-8. Keys and namespaces are strict UTF-8. Do not modify input bytes until Set completes.
- Set is one
SET, withPXorPXATwhen the entry expires. Get and Refresh are oneGET. A sliding entry then sends one shortEVALthat appliesPEXPIREATonly when the stored bytes are still the ones just read, so a replacement does not receive the previous lifetime. Remove is oneDEL. Get renews sliding expiration before returning; Refresh does not return the payload. - Sliding renewal never extends the absolute deadline. When both absolute options
are specified, the earlier deadline wins. Relative absolute expiration is converted
to a UTC deadline in
SetAsyncbefore dispatch, using the client's clock. Explicit and relative absolute expiration both require synchronized client/server UTC clocks. Queueing/network time consumes the remaining lifetime; deadlines already past on the server produce no live entry. Sliding-only expiration uses the server's relative TTL. - Millisecond resolution: positive durations below 1 ms are rejected; fractional milliseconds are rounded down. Absolute deadlines are rounded down to Unix ms and must be future at dispatch. Expired entries are never revived by a read or refresh.
- Set writes the final envelope and its expiry in one
SET. Sliding renewal uses the client clock and never passes the stored absolute deadline. - Server/protocol/corrupt-envelope errors propagate; they never become cache misses. Cancellation propagates, but cancellation/disconnection after sending cannot prove whether a mutation ran. No transport-failure mutation replay is performed. Atomic isolation is not a rollback guarantee: server resource/script-limit failures after a script has begun mutating can affect the entry or its TTL. Older Ruvio servers without expiration-aware script rollback do not restore native key TTLs. Treat a failed mutation/renewal as an uncertain outcome and reconcile or remove the affected entry; do not rely on its previous expiration or blindly retry the mutation. Explicit MOVED redirects may be followed because the server rejected that command. Sync methods block on their async equivalent on the thread pool (avoiding caller synchronization-context deadlocks). This adds scheduling overhead; prefer async code.
Storage, limits, and operations
The physical key is <InstanceName>:ruvio:cache:v1:<key>. Reserve this namespace for
this provider; do not edit the stored values or TTLs with other clients. Cluster hash
tags in keys/namespaces retain their normal meaning. Scripts declare exactly one key
and work with the client's cluster routing.
One native string entry contains RDC1\n<absolute-ms-or-0>\n<sliding-ms-or-0>\n<payload>.
The envelope costs 9–37 bytes (ASCII decimal fields), not base64 expansion. Native
key/object/index overhead is additional and implementation-dependent. Persistent
entries have no TTL; no extra metadata keys, hash fields, polling tasks, timers, or
server changes are introduced. Sliding-only entries use only native expiry plus the
in-value sliding duration. The provider adds no telemetry or key/value logging.
Defaults: 1 MiB payload and 1024 UTF-8 bytes for the full namespaced key.
MaxValueBytes (zero allows only empty values) and MaxKeyBytes are configurable.
The client RESP bulk ceiling is 64 MiB; the provider reserves 64 bytes for the envelope.
Server protocol/value/request limits and script limits must also accommodate the
envelope and the SET command; increasing provider limits does not raise
server limits. Only a sliding renewal sends EVAL, and that script is one fixed
text cached on the shard.
Tests
dotnet test integrations/dotnet/Ruvio.Extensions.Caching.Tests
RUVIO_TEST_ADDR=127.0.0.1:6379 dotnet test integrations/dotnet/Ruvio.Extensions.Caching.Tests
Live tests are explicitly skipped unless RUVIO_TEST_ADDR is set. They use unique
namespaces and clean up their own keys (never FLUSHDB). Use an isolated disposable
server for the live suite; it exercises expiration and concurrent writers.
| 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
- Microsoft.Extensions.Caching.Abstractions (>= 8.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Options (>= 8.0.0)
- Ruvio.Client (>= 0.2.9)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.1.0 | 93 | 10/2/2026 |