Respire.Extensions.DependencyInjection
0.3.0
Prefix Reserved
See the version list below for details.
dotnet add package Respire.Extensions.DependencyInjection --version 0.3.0
NuGet\Install-Package Respire.Extensions.DependencyInjection -Version 0.3.0
<PackageReference Include="Respire.Extensions.DependencyInjection" Version="0.3.0" />
<PackageVersion Include="Respire.Extensions.DependencyInjection" Version="0.3.0" />
<PackageReference Include="Respire.Extensions.DependencyInjection" />
paket add Respire.Extensions.DependencyInjection --version 0.3.0
#r "nuget: Respire.Extensions.DependencyInjection, 0.3.0"
#:package Respire.Extensions.DependencyInjection@0.3.0
#addin nuget:?package=Respire.Extensions.DependencyInjection&version=0.3.0
#tool nuget:?package=Respire.Extensions.DependencyInjection&version=0.3.0
Respire
Respire is a fast, modern RESP client for .NET. It works with Redis, Valkey, KeyDB, and other RESP-compatible servers while keeping the API familiar to C# developers.
await using var redis = await RespireClient.ConnectAsync("redis://localhost");
await redis.SetAsync("greeting", "hello", expiry: TimeSpan.FromMinutes(5));
string? greeting = await redis.GetStringAsync("greeting");
await redis.SetAsync("user:1", new User("Ada", 36));
User? user = await redis.GetAsync<User>("user:1");
Status: Respire is pre-release, so its API may still change. Sentinel support and RESP3 client-side caching are on the roadmap.
Why Respire?
- Natural .NET APIs. Get
string?,long,bool,TimeSpan?, orT?directly—no protocol wrapper to unpack. Nullability tells you when a result can be missing. - Fast by default. Respire coalesces commands from concurrent callers into fewer socket writes, parses replies from pooled buffers, and spreads work across multiplexed connections. No batching switch is required.
- Blocking commands that do not block everything else. Commands such as
BLPOPuse a dedicated pooled connection, leaving normal traffic free to flow. - An API that is easy to explore. Commands are grouped by data type (
redis.Hashes,redis.Streams,redis.SortedSets, and more), while common string operations remain on the client itself. - Modern async patterns. Pub/sub, stream consumer groups, and
SCANuseIAsyncEnumerable. Expiries useTimeSpanandDateTimeOffset. - Safer failure modes. Early batch awaits fail immediately instead of deadlocking. Cancellation abandons the wait without leaving a partial RESP frame on the connection.
- Production-friendly. Built-in reconnection, resubscribing pub/sub, OpenTelemetry, dependency injection, typed serialization, and testable interfaces.
Everyday patterns
Blocking list reads
Set waitFor and Respire automatically uses a dedicated connection:
string? job = await redis.Lists.LeftPopAsync(
"jobs",
waitFor: TimeSpan.FromSeconds(30));
Pub/sub
Subscriptions are async streams. Leaving the loop and disposing the subscription handles cleanup—no delegate bookkeeping required.
await using var subscription = redis.Subscribe("orders");
await foreach (var message in subscription.WithCancellation(token))
{
Console.WriteLine($"{message.Channel}: {message.Text}");
}
Redis 7 sharded pub/sub uses SSUBSCRIBE and SPUBLISH. Run this as a separate consumer:
await using var shard = redis.SubscribeSharded("orders:europe");
await using var shardMessages = shard.GetAsyncEnumerator(token);
var nextMessage = shardMessages.MoveNextAsync().AsTask(); // Starts SSUBSCRIBE.
while (!nextMessage.IsCompleted)
{
await redis.PublishShardedAsync("orders:europe", "ready", token);
await Task.WhenAny(nextMessage, Task.Delay(10, token));
}
if (await nextMessage.WaitAsync(token))
{
Console.WriteLine(shardMessages.Current.Text);
}
Batches and transactions
Batch commands share one flush. Transactions use one connection and return typed pending results.
var batch = redis.CreateBatch();
var name = batch.GetStringAsync("name");
var visits = batch.IncrementAsync("visits");
await batch.SendAsync();
Console.WriteLine($"{name.Result}: {visits.Result}");
var transaction = redis.CreateTransaction();
var balance = transaction.IncrementAsync("balance", -100);
transaction.ListRightPushAsync("audit", "withdraw:100");
bool committed = await transaction.CommitAsync();
Use CreateTransactionAsync(["balance"]) for optimistic concurrency with WATCH. Read the
current value, queue the conditional update, then retry when CommitAsync returns false:
bool applied;
do
{
await using var watched = await redis.CreateTransactionAsync(["balance"]);
long current = long.Parse((await redis.GetStringAsync("balance"))!);
watched.SetAsync("balance", current - 100);
applied = await watched.CommitAsync();
}
while (!applied);
Redis Cluster
Enable cluster routing and provide one or more seed nodes. Respire loads CLUSTER SLOTS, follows
MOVED/ASK redirects, and caches learned routes. Batches may span nodes; transactions must keep
all keys in one slot, so use Redis hash tags for related keys. WATCH transactions are not
supported in cluster mode—use a same-slot Lua script instead. Sharded pub/sub is also unavailable
in cluster mode; SSUBSCRIBE subscriptions require a non-cluster client.
await using var cluster = await RespireClient.ConnectAsync(new RespireOptions
{
Cluster = true,
Endpoints =
{
new("redis-1", 6379),
new("redis-2", 6379),
},
});
await cluster.SetAsync("{account:42}:name", "Ada");
await cluster.SetAsync("{account:42}:balance", 100);
A single seed can also be enabled with redis://redis-1?cluster=true.
Zero-copy reads and custom commands
Normal reads favor convenient .NET values. For large payloads, opt into a disposable lease:
using RespireLease blob = await redis.Strings.GetLeaseAsync("blob:4mb");
Process(blob.Span);
Every command in the Redis 8.10 and Valkey 9.1 references is available through the generated,
discoverable RespireCommands catalog. It also includes Redis's integrated JSON, Search,
probabilistic, time-series, and vector commands, Valkey modules, and documented KeyDB and
Dragonfly extensions. Command words are pre-encoded once; only arguments are written per call:
using var document = await redis.ExecuteAsync(
RespireCommands.Json.JSON_SET, "user:1", "$", payload);
using var encoding = await redis.ExecuteAsync(
RespireCommands.Key.OBJECT_ENCODING, "user:1");
Catalog descriptors do not encode key positions, so catalog execution is rejected on
WithKeyPrefix views; use the typed facets there to preserve key isolation.
The string and interpolated overloads remain available for experimental or server-specific commands. Interpolated values are encoded as single arguments, so spaces stay safe.
App integration
Dependency injection
builder.Services.AddRespire(builder.Configuration.GetConnectionString("redis")!);
// Named clients are supported too.
builder.Services.AddRespire("sessions", "redis://sessions-host");
public sealed class CartService(
[FromKeyedServices("sessions")] IRespireClient redis);
Registration is lazy, so Redis availability never blocks application startup.
IDistributedCache and HybridCache
Respire.Extensions.Caching provides IDistributedCache and IBufferDistributedCache.
Respire.Extensions.Caching.Hybrid adds Respire as the L2 backend for HybridCache.
builder.Services.AddRespireDistributedCache(
"redis://localhost",
instanceName: "myapp:");
// L1 memory + L2 Redis
builder.Services.AddRespireHybridCache(
"redis://localhost",
instanceName: "myapp:");
Cache entries use the same layout as Microsoft.Extensions.Caching.StackExchangeRedis, so you
can switch without flushing existing entries. Sliding-expiration reads also refresh their TTL
atomically in the same round trip.
Redis ACL note: Cache users need
EVALSHA,EVAL,SET,UNLINK,HSET,HMGET,PTTL,PEXPIRE,PERSIST, andEXISTS. Timeout- or cancellation-safe calls also requireCLIENT IDandCLIENT KILL.
More capabilities
- Lua scripts with automatic
EVALSHAtoEVALfallback - Streams and consumer groups with per-entry acknowledgement
- Key-prefixed client views for multi-tenant applications
- Sharded pub/sub for Redis 7
- Automatic reconnect and pub/sub resubscribe
- OpenTelemetry spans and metrics through
ActivitySourceandMeter, both namedRespire - Custom
IRespireSerializersupport with a System.Text.Json default IRespireClientand per-feature interfaces for straightforward testing
Redis telemetry follows OpenTelemetry database semantic conventions. db.namespace reports
the database index configured when the connection was established; raw SELECT commands are
not tracked. Query text is not collected because arbitrary Redis command values cannot be
reliably sanitized. Operation latency uses the stable db.client.operation.duration histogram
in seconds; pipelines and transactions are recorded as single operations.
See command coverage for audited sources and regeneration details,
and API design for design decisions, wire architecture, and roadmap.
Reproducible comparisons with StackExchange.Redis live in
benchmarks/.
Documentation
Read the Respire documentation or run it locally:
cd website
npm install
npm start
Build and test
dotnet build Respire.slnx
dotnet test tests/Respire.Tests
dotnet test tests/Respire.IntegrationTests # Requires Docker
License
| 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 is compatible. 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. |
-
net10.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.10)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.10)
- Respire (>= 0.3.0)
-
net8.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.10)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.10)
- Respire (>= 0.3.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.