OrionGuard.Locks.Redis
7.0.0
dotnet add package OrionGuard.Locks.Redis --version 7.0.0
NuGet\Install-Package OrionGuard.Locks.Redis -Version 7.0.0
<PackageReference Include="OrionGuard.Locks.Redis" Version="7.0.0" />
<PackageVersion Include="OrionGuard.Locks.Redis" Version="7.0.0" />
<PackageReference Include="OrionGuard.Locks.Redis" />
paket add OrionGuard.Locks.Redis --version 7.0.0
#r "nuget: OrionGuard.Locks.Redis, 7.0.0"
#:package OrionGuard.Locks.Redis@7.0.0
#addin nuget:?package=OrionGuard.Locks.Redis&version=7.0.0
#tool nuget:?package=OrionGuard.Locks.Redis&version=7.0.0
OrionGuard.Locks.Redis
Moves the outbox dispatcher's leader election off your application database and onto Redis, for deployments where every replica polling a lock table is the write you do not want.
dotnet add package OrionGuard.Locks.Redis
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Moongazing.OrionGuard.EntityFrameworkCore;
using Moongazing.OrionGuard.Locks.Redis;
public sealed class AppDbContext(DbContextOptions<AppDbContext> options) : DbContext(options);
public static class OutboxLocking
{
public static void Add(IServiceCollection services) =>
services.AddOrionGuardEfCore<AppDbContext>(o => o
.UseOutbox()
.UseOrionLockRedis("localhost:6379,abortConnect=false", redis => redis.KeyPrefix = "myapp:outbox:"));
}
The dispatcher and the archival worker now take a Redis lease instead of a row in OrionGuard_OutboxLocks — that table and its migration are no longer needed. OrionGuard.EntityFrameworkCore and OrionLock.Redis come along as dependencies.
If your application already owns a multiplexer, hand the bridge the options only:
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Moongazing.OrionGuard.EntityFrameworkCore;
using Moongazing.OrionGuard.Locks.Redis;
using StackExchange.Redis;
public sealed class AppDbContext(DbContextOptions<AppDbContext> options) : DbContext(options);
public static class SharedMultiplexer
{
public static void Add(IServiceCollection services)
{
services.AddSingleton<IConnectionMultiplexer>(_ =>
ConnectionMultiplexer.Connect("localhost:6379,abortConnect=false"));
services.AddOrionGuardEfCore<AppDbContext>(o => o
.UseOutbox()
.UseOrionLockRedis(redis => redis.KeyPrefix = "myapp:outbox:"));
}
}
IConnectionMultiplexer, RedisLockOptions and IDistributedLockProvider are all registered with TryAdd, so whatever you registered first wins and the matching argument here is ignored — including when you wired Redis through OrionLock's own AddOrionLock(...).UseRedis(...).
How the lease behaves
UseOrionLockRedis replaces the registered IDistributedLock with OrionLockBridgeDistributedLock over OrionLock's RedisLockProvider.
- Acquire is a single
SET key token NX PXwith a fresh owner token. On contention it returnsnullimmediately and the worker retries on its next poll — there is no blocking wait, no reentrancy. - Lease length is
OutboxOptions.LockLeaseDuration(default 30 seconds) for the dispatcher andOutboxArchivalOptions.LockLeaseDuration(default 5 minutes) for archival. - Release is an owner-checked compare-and-delete in Lua, so a lease another replica has already taken over is left alone. A failed release is swallowed and the key expires by itself.
- Keys are
RedisLockOptions.KeyPrefix(defaultorionlock:) plus the lock key, for exampleorionlock:orion_guard_outbox_dispatcher.RedisLockOptions.Databasedefaults to-1, the connection's default database.
When Redis is not there
At startup, the connection-string form calls ConnectionMultiplexer.Connect as the hosted services are created. With StackExchange.Redis's default abortConnect=true, an unreachable server throws and the host does not start — which is why the examples above pass abortConnect=false, so the app starts and the multiplexer reconnects in the background.
At runtime, an unreachable Redis makes the acquire call throw; the worker logs it and retries on the next poll. Outbox rows keep accumulating safely, because they are written in the same transaction as your aggregates, and go out once Redis is back.
What this does not do
- The lease is never renewed. A batch that outruns
LockLeaseDurationcan be joined by another replica dispatching the same rows. Delivery is at least once and handlers must be idempotent — that is true of the database lock as well, but a long batch makes it visible here. - It does not remove the outbox table. Only the lock table goes away;
OrionGuard_Outboxand its migration are still required. - It makes Redis a hard dependency of dispatch. No Redis, no dispatcher and no archival — events queue up in the database instead. Weigh that against the lock-row write you removed.
- It does not lock anything else. This is the outbox dispatcher and archival worker only; it is not a general-purpose lock API for your application.
- No fencing token reaches your handlers. The bridge hands out a lease, not a monotonically increasing token, so a handler cannot detect that it lost the lock mid-batch.
Targets
net8.0, net9.0, net10.0; OrionLock.Redis 2.x, over StackExchange.Redis. Use the OrionGuard.EntityFrameworkCore build that ships with the same OrionGuard release — it targets EF Core 10 on net10.0 and EF Core 9 on net8.0/net9.0.
With the rest of OrionGuard
OrionGuard.EntityFrameworkCore (the outbox and the IDistributedLock contract) · OrionGuard.Outbox.PostgresNotify · OrionGuard.Outbox.SqlServerBroker · OrionLock.Redis
Documentation
License
MIT. See LICENSE.txt.
| 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 is compatible. 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
- OrionGuard.EntityFrameworkCore (>= 7.0.0)
- OrionLock.Redis (>= 2.0.0)
-
net8.0
- OrionGuard.EntityFrameworkCore (>= 7.0.0)
- OrionLock.Redis (>= 2.0.0)
-
net9.0
- OrionGuard.EntityFrameworkCore (>= 7.0.0)
- OrionLock.Redis (>= 2.0.0)
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 |
|---|---|---|
| 7.0.0 | 85 | 9/20/2026 |
| 6.7.0 | 122 | 7/20/2026 |
| 6.6.2 | 137 | 6/20/2026 |
| 6.6.1 | 126 | 6/20/2026 |
| 6.6.0 | 124 | 6/19/2026 |
| 6.5.30 | 138 | 6/17/2026 |
| 6.5.29 | 122 | 6/15/2026 |
| 6.5.28 | 114 | 6/15/2026 |
| 6.5.27 | 114 | 6/15/2026 |
| 6.5.26 | 117 | 6/13/2026 |
| 6.5.25 | 110 | 6/13/2026 |
| 6.5.24 | 115 | 6/12/2026 |
| 6.5.23 | 123 | 6/12/2026 |
| 6.5.22 | 113 | 6/11/2026 |
| 6.5.21 | 115 | 6/11/2026 |
| 6.5.20 | 112 | 6/11/2026 |
| 6.5.19 | 115 | 6/11/2026 |
| 6.5.18 | 112 | 6/11/2026 |
| 6.5.16 | 113 | 6/11/2026 |
| 6.5.15 | 122 | 6/11/2026 |