-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add couchbase and foundatio lock (#947)
- Loading branch information
Showing
4 changed files
with
220 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
// Copyright (c) 2020 DHGMS Solutions and Contributors. All rights reserved. | ||
// DHGMS Solutions and Contributors licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for full license information. | ||
|
||
using System; | ||
using System.Threading.Tasks; | ||
using Couchbase.Extensions.Locks; | ||
|
||
namespace Whipstaff.Couchbase | ||
{ | ||
/// <summary> | ||
/// Exclusive lock integration for Couchbase. | ||
/// </summary> | ||
public sealed class CouchbaseLock : global::Foundatio.Lock.ILock | ||
{ | ||
private readonly ICouchbaseMutex _mutex; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="CouchbaseLock"/> class. | ||
/// </summary> | ||
/// <param name="mutex"> | ||
/// Couchbase mutex manager. | ||
/// </param> | ||
/// <param name="resource">Name of the resource.</param> | ||
/// <param name="aquiredTimeUtc">The timestamp for when the lock was aquired.</param> | ||
/// <param name="timeWaitedForLock">The time waited for the lock</param> | ||
public CouchbaseLock( | ||
ICouchbaseMutex mutex, | ||
string resource, | ||
DateTime aquiredTimeUtc, | ||
TimeSpan timeWaitedForLock) | ||
{ | ||
_mutex = mutex ?? throw new ArgumentNullException(nameof(mutex)); | ||
Resource = resource ?? throw new ArgumentNullException(nameof(resource)); | ||
AcquiredTimeUtc = aquiredTimeUtc; | ||
TimeWaitedForLock = timeWaitedForLock; | ||
RenewalCount = 0; | ||
} | ||
|
||
/// <inheritdoc/> | ||
public string LockId => _mutex.Name; | ||
|
||
/// <inheritdoc/> | ||
public string Resource { get; } | ||
|
||
/// <inheritdoc/> | ||
public DateTime AcquiredTimeUtc { get; } | ||
|
||
/// <inheritdoc/> | ||
public TimeSpan TimeWaitedForLock { get; } | ||
|
||
/// <inheritdoc/> | ||
public int RenewalCount { get; private set; } | ||
|
||
/// <inheritdoc/> | ||
public ValueTask DisposeAsync() | ||
{ | ||
return default(ValueTask); | ||
} | ||
|
||
/// <inheritdoc/> | ||
public async Task RenewAsync(TimeSpan? timeUntilExpires = null) | ||
{ | ||
await _mutex.Renew(timeUntilExpires ?? TimeSpan.FromMinutes(1)) | ||
.ConfigureAwait(false); | ||
RenewalCount++; | ||
} | ||
|
||
/// <inheritdoc/> | ||
public Task ReleaseAsync() | ||
{ | ||
_mutex.Dispose(); | ||
return Task.CompletedTask; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
// Copyright (c) 2020 DHGMS Solutions and Contributors. All rights reserved. | ||
// DHGMS Solutions and Contributors licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for full license information. | ||
|
||
using System; | ||
using System.Collections.Concurrent; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Couchbase; | ||
using Couchbase.Extensions.DependencyInjection; | ||
using Couchbase.Extensions.Locks; | ||
using Couchbase.KeyValue; | ||
using Foundatio.Lock; | ||
using Whipstaff.Couchbase; | ||
|
||
namespace Dhgms.NetContrib.Playground.Features.Couchbase.Foundatio | ||
{ | ||
/// <summary> | ||
/// A Couchbase Lock Distributed Log Provider. | ||
/// </summary> | ||
public sealed class CouchbaseLockProvider : global::Foundatio.Lock.ILockProvider | ||
{ | ||
private readonly ConcurrentDictionary<string, ICouchbaseMutex> _mutexDictionary = new ConcurrentDictionary<string, ICouchbaseMutex>(); | ||
private readonly ICouchbaseCollection _couchbaseCollection; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="CouchbaseLockProvider"/> class. | ||
/// </summary> | ||
/// <param name="couchbaseCollection">The couchbase collection.</param> | ||
public CouchbaseLockProvider(ICouchbaseCollection couchbaseCollection) | ||
{ | ||
_couchbaseCollection = couchbaseCollection ?? throw new ArgumentNullException(nameof(couchbaseCollection)); | ||
} | ||
|
||
/// <summary> | ||
/// Gets a Couchbase Lock Provider using a bucket provider. | ||
/// </summary> | ||
/// <param name="bucketProvider">Bucket Provider Instance to use.</param> | ||
/// <returns>Instance of <see cref="CouchbaseLockProvider"/>.</returns> | ||
public static async Task<CouchbaseLockProvider> GetInstance(IBucketProvider bucketProvider) | ||
{ | ||
if (bucketProvider == null) | ||
{ | ||
throw new ArgumentNullException(nameof(bucketProvider)); | ||
} | ||
|
||
var bucket = await bucketProvider.GetBucketAsync("default") | ||
.ConfigureAwait(false); | ||
|
||
return GetInstance(bucket); | ||
} | ||
|
||
/// <summary> | ||
/// Gets a Couchbase Lock Provider using a bucket provider. | ||
/// </summary> | ||
/// <param name="bucket">Couchbase Bucket to use.</param> | ||
/// <returns>Instance of <see cref="CouchbaseLockProvider"/>.</returns> | ||
public static CouchbaseLockProvider GetInstance(IBucket bucket) | ||
{ | ||
if (bucket == null) | ||
{ | ||
throw new ArgumentNullException(nameof(bucket)); | ||
} | ||
|
||
var collection = bucket.DefaultCollection(); | ||
|
||
return new CouchbaseLockProvider(collection); | ||
} | ||
|
||
/// <inheritdoc/> | ||
public async Task<ILock> AcquireAsync( | ||
string resource, | ||
TimeSpan? timeUntilExpires, | ||
bool releaseOnDispose, | ||
CancellationToken cancellationToken) | ||
{ | ||
var attemptStarted = DateTime.UtcNow; | ||
|
||
var mutex = await _couchbaseCollection.RequestMutexAsync( | ||
resource, | ||
timeUntilExpires ?? TimeSpan.FromMinutes(1), | ||
cancellationToken) | ||
.ConfigureAwait(false); | ||
|
||
var dateTimeAquired = DateTime.UtcNow; | ||
var timeWaited = dateTimeAquired - attemptStarted; | ||
|
||
_ = _mutexDictionary.TryAdd(resource, mutex); | ||
|
||
return new CouchbaseLock(mutex, resource, dateTimeAquired, timeWaited); | ||
} | ||
|
||
/// <inheritdoc/> | ||
public async Task<bool> IsLockedAsync(string resource) | ||
{ | ||
var existsResult = await _couchbaseCollection.ExistsAsync(resource) | ||
.ConfigureAwait(false); | ||
|
||
return existsResult.Exists; | ||
} | ||
|
||
/// <inheritdoc/> | ||
public Task ReleaseAsync(string resource, string lockId) | ||
{ | ||
if (_mutexDictionary.TryGetValue(resource, out var mutex)) | ||
{ | ||
mutex.Dispose(); | ||
} | ||
|
||
return Task.CompletedTask; | ||
} | ||
|
||
/// <inheritdoc/> | ||
public async Task RenewAsync(string resource, string lockId, TimeSpan? timeUntilExpires = null) | ||
{ | ||
if (!_mutexDictionary.TryGetValue(resource, out var mutex)) | ||
{ | ||
return; | ||
} | ||
|
||
await mutex.Renew(timeUntilExpires ?? TimeSpan.FromMinutes(1)) | ||
.ConfigureAwait(false); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net6.0</TargetFramework> | ||
<Nullable>enable</Nullable> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Couchbase.Extensions.Locks" Version="2.0.0" /> | ||
<PackageReference Include="Foundatio" Version="10.2.4" /> | ||
</ItemGroup> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters