OrionLock.Postgres
0.5.0
See the version list below for details.
dotnet add package OrionLock.Postgres --version 0.5.0
NuGet\Install-Package OrionLock.Postgres -Version 0.5.0
<PackageReference Include="OrionLock.Postgres" Version="0.5.0" />
<PackageVersion Include="OrionLock.Postgres" Version="0.5.0" />
<PackageReference Include="OrionLock.Postgres" />
paket add OrionLock.Postgres --version 0.5.0
#r "nuget: OrionLock.Postgres, 0.5.0"
#:package OrionLock.Postgres@0.5.0
#addin nuget:?package=OrionLock.Postgres&version=0.5.0
#tool nuget:?package=OrionLock.Postgres&version=0.5.0
OrionLock.Postgres
PostgreSQL pg_try_advisory_lock backend for OrionLock distributed locking.
Lock lifetime is the PostgreSQL session lifetime: a crashed process releases its locks automatically with no clock-based expiry.
services.AddOrionLock()
.UsePostgres("Host=localhost;Database=app;Username=...;Password=...", o =>
{
o.KeyPrefix = "app:";
o.CommandTimeout = TimeSpan.FromSeconds(30);
});
Notes
- 64-bit integer keys. Postgres advisory locks are keyed by
bigint. The provider hashesKeyPrefix + keywith SHA-256 and takes the first 8 bytes as a little-endianint64. Collision risk is negligible for realistic key counts; useKeyPrefixto namespace if you also share the database withpg_advisory_lockfrom other code paths. - Session-scoped, no clock expiry. A crashed process releases its locks the moment the database session terminates. There is no lease timer in Postgres itself; OrionLock's renewal watchdog only probes the connection liveness.
- Connection pooling. The provider holds each dedicated
NpgsqlConnectionopen for the lifetime of the lock and disposes it on release, returning it to the Npgsql pool only afterpg_advisory_unlockhas run.
Reader-writer (shared/exclusive) lock
services.AddOrionLock()
.UsePostgresSharedExclusive("Host=localhost;Database=app;Username=...;Password=...", o =>
{
o.TableName = "orionlock_rw_holds"; // default; idempotently created on first use
o.AutoCreateTable = true; // set false to manage the schema out of band
});
// resolve ISharedExclusiveLock and acquire shared/exclusive holds
For a given key, any number of Shared (read) holders coexist, OR exactly one Exclusive (write) holder owns it.
- Clock-leased table, not advisory locks. Unlike the exclusive-only backend, the reader-writer provider models each hold as a row (reader, writer, or pending-writer) in a table with an explicit
expires_at, so it can track readers individually with their own fencing token and reclaim a dead reader at its own expiry. Lease durations are therefore honoured as a wall-clock TTL against the PostgreSQL server clock (now()). - Atomic transitions. Every acquire / renew / release runs in a transaction that first serializes all transitions for the key with
pg_advisory_xact_lock(auto-released at commit), then prunes expired rows, evaluates, and writes. There is no read-then-write race. - Per-reader fencing. The caller's owner token is the fencing token. Renew and release affect only the caller's own share; releasing an already-expired share is a no-op.
- Writer fairness. A blocked writer plants a lease-bounded pending-writer marker that holds off NEW readers (an existing reader may still refresh) so in-flight readers drain and the writer proceeds. The marker carries the writer's own lease, so a crashed writer cannot block readers past that TTL. This is writer-preference, not strict FIFO among writers.
Acquire-or-give-up-by-deadline
ISharedExclusiveLock also exposes deadline overloads that poll until a deadline and return null on expiry instead of throwing LockAcquisitionTimeoutException:
var handle = await rwLock.TryAcquireExclusiveAsync("k", deadline: TimeSpan.FromSeconds(2));
if (handle is null) { /* could not acquire in time - ordinary control flow */ }
Requires the OrionLock package. See https://github.com/tunahanaliozturk/OrionLock.
| 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
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.0)
- Npgsql (>= 8.0.5)
- OrionLock (>= 0.5.0)
-
net8.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.0)
- Npgsql (>= 8.0.5)
- OrionLock (>= 0.5.0)
-
net9.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.0)
- Npgsql (>= 8.0.5)
- OrionLock (>= 0.5.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 |
|---|---|---|
| 2.0.0 | 43 | 7/29/2026 |
| 1.0.1 | 86 | 7/27/2026 |
| 1.0.0 | 110 | 6/30/2026 |
| 0.6.0 | 99 | 6/27/2026 |
| 0.5.0 | 122 | 6/26/2026 |
| 0.4.1 | 148 | 6/20/2026 |
| 0.4.0 | 114 | 6/19/2026 |
| 0.3.32 | 123 | 6/17/2026 |
| 0.3.31 | 117 | 6/16/2026 |
| 0.3.30 | 122 | 6/16/2026 |
| 0.3.28 | 102 | 6/15/2026 |
| 0.3.27 | 105 | 6/15/2026 |
| 0.3.26 | 109 | 6/13/2026 |
| 0.3.25 | 102 | 6/13/2026 |
| 0.3.24 | 107 | 6/12/2026 |
| 0.3.23 | 105 | 6/12/2026 |
| 0.3.22 | 106 | 6/11/2026 |
| 0.3.21 | 114 | 6/11/2026 |
| 0.3.20 | 104 | 6/11/2026 |
| 0.3.19 | 111 | 6/11/2026 |