WopiHost.RedisLockProvider 8.0.0

dotnet add package WopiHost.RedisLockProvider --version 8.0.0
                    
NuGet\Install-Package WopiHost.RedisLockProvider -Version 8.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="WopiHost.RedisLockProvider" Version="8.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="WopiHost.RedisLockProvider" Version="8.0.0" />
                    
Directory.Packages.props
<PackageReference Include="WopiHost.RedisLockProvider" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add WopiHost.RedisLockProvider --version 8.0.0
                    
#r "nuget: WopiHost.RedisLockProvider, 8.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package WopiHost.RedisLockProvider@8.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=WopiHost.RedisLockProvider&version=8.0.0
                    
Install as a Cake Addin
#tool nuget:?package=WopiHost.RedisLockProvider&version=8.0.0
                    
Install as a Cake Tool

WopiHost.RedisLockProvider

IWopiLockProvider implementation backed by Redis, with atomic compare-and-swap via Lua scripts and TTL-driven WOPI expiry.

When to pick this over the other lock providers

Provider Cross-process? Cross-instance? Operational complexity When
MemoryLockProvider None Single-process development; smoke tests.
WopiAzureLockProvider ✅ (Azure-coordinated blob leases) Azure Storage account Multi-region Azure deployments; strongest exclusion.
WopiRedisLockProvider ✅ (best-effort, single Redis) Redis container Most real-world cases — many shops already run Redis for session state / cache and would rather not adopt Azure Blob just for WOPI locks.

Best-effort, not Redlock

This provider deliberately does not implement Redlock (lock acquired against a majority of independent Redis nodes). The reasoning:

  • WOPI lock semantics are advisory — the 30-minute server-side TTL is the safety net, not the lock itself. The spec already expects that a lock can be "lost" via expiry without coordination.
  • Redlock is operationally heavy (independent Redis nodes, clock-skew bounds, fencing tokens) and famously controversial. The cost isn't justified for advisory locks with a known expiry contract.
  • For deployments that need stronger cross-region exclusion, prefer WopiAzureLockProvider.

If your Redis instance fails over to a replica with stale state mid-WOPI-session, the worst-case outcome is the same as any other lock provider after the 30-minute window expires: the editor reports a lock conflict and the user can re-acquire. No data loss.

Atomicity

Each non-trivial operation is a Lua script evaluated on the Redis server with EVAL. Lua scripts run to completion without interleaving with other commands, so the "match-then-mutate" steps land as a single observable transaction. The conformance suite's RefreshLockAsync_ConcurrentSwapBetweenObservationAndCAS_DoesNotRefresh test exercises this path against this provider too — a stale caller's expected lock id no longer matches the Redis-resident value when the script runs.

Registration

services.AddRedisLockProvider(builder.Configuration);

The runnable sample's Sample:LockProvider discriminator (Memory / Azure / Redis) dispatches to the typed extension above — see sample/WopiHost/ServiceCollectionExtensions.cs.

Reads Wopi:LockProvider:ConnectionString for the StackExchange.Redis connection string. If an IConnectionMultiplexer is already registered in DI (e.g. via Aspire's builder.AddRedisClient("wopi-locks")), that wins so a single multiplexer is reused across the process.

// appsettings.json
"Wopi": {
  "LockProvider": {
    "ConnectionString": "localhost:6379",
    "KeyPrefix": "wopi:lock:" // optional; default shown
  }
}

Interface contract

IWopiLockProvider from WopiHost.Abstractions:

Task<WopiLockInfo?> GetLockAsync(string fileId, CancellationToken ct = default);
Task<WopiLockInfo?> AddLockAsync(string fileId, string lockId, CancellationToken ct = default);
Task<bool>          RefreshLockAsync(string fileId, string expectedExistingLockId, CancellationToken ct = default);
Task<bool>          RemoveLockAsync(string fileId, CancellationToken ct = default);
Task<bool>          TryUnlockAndRelockAsync(string fileId, string newLockId, string expectedExistingLockId, CancellationToken ct = default);

Behaviour is validated against the shared LockProviderConformanceTests in WopiHost.Abstractions.Testing — the same harness MemoryLockProvider and WopiAzureLockProvider run through, so all three are bound to the same contract.

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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
8.0.0 93 5/14/2026