Notidar.MongoDB.Lock.Extensions
1.1.0
dotnet add package Notidar.MongoDB.Lock.Extensions --version 1.1.0
NuGet\Install-Package Notidar.MongoDB.Lock.Extensions -Version 1.1.0
<PackageReference Include="Notidar.MongoDB.Lock.Extensions" Version="1.1.0" />
paket add Notidar.MongoDB.Lock.Extensions --version 1.1.0
#r "nuget: Notidar.MongoDB.Lock.Extensions, 1.1.0"
// Install Notidar.MongoDB.Lock.Extensions as a Cake Addin #addin nuget:?package=Notidar.MongoDB.Lock.Extensions&version=1.1.0 // Install Notidar.MongoDB.Lock.Extensions as a Cake Tool #tool nuget:?package=Notidar.MongoDB.Lock.Extensions&version=1.1.0
mongo-lock
Distributed lock library for C#/.NET using MongoDB.
Notidar.MongoDB.Lock is a core library that provides a simple way to create distributed locks for simple apps. LockStore
can be used for direct lock manipulation, while LockService
provides a high level abstraction. Include extensions for creating collection and indexes.
Notidar.MongoDB.Lock.Extensions is a library that provides all required extensions to use the library with Microsoft.Extensions.DependencyInjection
.
Features
- Distributed locks using MongoDB
- Exclusive locks
- Shared locks
- Semaphore like usage with shared locks
- High level abstraction with
LockService
- Low level manipulation with
LockStore
- Optional MongoDB collection auto cleanup for expired locks based on TTL index
- Flexible lock configuration with
LockOptions
Usage
With IServiceCollection
with high level manipulations
...
services
.AddMongoDb(configuration.GetSection(nameof(DatabaseOptions))) // if MongoDB not registered
.AddMongoLocks(configuration.GetSection(nameof(LockSettings))); // add all required services for locks
...
// resolve lock service
var lockService = sp.GetRequiredService<ILockService>();
await using (var sharedLock1 = await lockService.SharedLockAsync(resourceId, operationCancellationToken))
{
// shared lock1 acquired
await DoSomethingAsync(sharedLock1.HealthToken); // use `sharedLock1.HealthToken` to check if lock is still valid
await using (var sharedLock2 = await lockService.SharedLockAsync(resourceId, operationCancellationToken))
{
// shared lock2 acquired
await DoSomethingAsync2(sharedLock2.HealthToken); // use `sharedLock2.HealthToken` to check if lock is still valid
}
// shared lock2 released
}
// shared lock1 released
await using (var exclusiveLock = await lockService.ExclusiveLockAsync(resourceId, operationCancellationToken))
{
// exclusive lock acquired
await DoSomethingExclusivelyAsync(exclusiveLock.HealthToken); // use `exclusiveLock.HealthToken` to check if lock is still valid
}
// exclusive lock released
Simple console app with low level manipulations
var client = new MongoClient(connectionString);
var database = client.GetDatabase("cli-test");
var lockStore = new LockStore(database.GetCollection<Resource>("locks")); // Resource defined in Notidar.MongoDB.Lock.Stores
var lockService = new LockService(lockStore); // in case you need high level manipulations
// low level manipulation
var resourceResult = await lockStore.ExclusiveLockAsync("resourceId-1", "lockId-1", TimeSpan.FromSeconds(60)); // exlusive lock
if (resource?.ExclusiveLock?.LockId == "lockId-1")
{
// exclusive locked aquired
await lockStore.ExclusiveUnlockAsync("resourceId-1", "lockId-1"); // exlusive release
}
var resourceFirstSharedResult = await lockStore.SharedLockAsync("resourceId-1", "lockId-2", TimeSpan.FromSeconds(60));
var resourceSecondSharedResult = await lockStore.SharedLockAsync("resourceId-1", "lockId-3", TimeSpan.FromSeconds(60), sharedLockLimit: 10);
if (resourceFirstSharedResult?.SharedLocks?.Any(x => x.LockId == "lockId-2") && resourceSecondSharedResult?.SharedLocks?.Any(x => x.LockId == "lockId-3"))
{
// both shared locked aquired
await lockStore.SharedUnlockAsync("resourceId-1", "lockId-2"); // shared release
await lockStore.SharedUnlockAsync("resourceId-1", "lockId-3"); // shared release
}
See samples folder for more examples.
Roadmap (Contributions are welcome)
Contributions are welcome! If you are interested in contributing towards a new or existing issue, please let me know via comments on the issue so that I can help you get started and avoid wasted effort on your part.
- Add support auto cleanup for expired locks
- Add support for infinite locks (locks that never expire)
- Add support for optional lock re-entry
- Add logging support
- Add CLI for managing locks. (e.g.
mongo-lock --list
,mongo-lock --delete <lockId>
) - Add support for MongoDB unlock detection. Based either MongoDB Capped Collections with signals or on MongoDB Change Streams (e.g.
LockService.WaitForUnlockAsync(lockId, timeout)
) - Improve unit test coverage
License
MIT License
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. 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. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 is compatible. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Hosting.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Options (>= 8.0.2)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 8.0.0)
- Notidar.MongoDB.Lock (>= 1.1.0)
-
.NETStandard 2.1
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Hosting.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Options (>= 8.0.2)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 8.0.0)
- Notidar.MongoDB.Lock (>= 1.1.0)
-
net8.0
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Hosting.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Options (>= 8.0.2)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 8.0.0)
- Notidar.MongoDB.Lock (>= 1.1.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.