From 82b741075274bb15db99407cfdf760f7952109a2 Mon Sep 17 00:00:00 2001 From: Andrew Moreno Date: Sat, 7 Sep 2024 16:07:57 -0400 Subject: [PATCH] Update ResourceId property of DistributedLease to support string IDs (#8) * Updated resource id property of DistributedLease to support string values instead of only Guid * Specify the string length for EF Core ResourceId * Bump the package version --------- Co-authored-by: Andrew Moreno Co-authored-by: f1x3d <17356460+f1x3d@users.noreply.github.com> --- Directory.Build.props | 4 ++-- .../DistributedLeaseBlobStorage.cs | 4 ++-- .../DistributedLeaseCosmosDb.cs | 14 +++++++------- DistributedLeaseManager.Core/DistributedLease.cs | 2 +- .../DistributedLeaseManager.cs | 7 +++---- .../IDistributedLeaseManager.cs | 4 ++-- .../IDistributedLeaseRepository.cs | 2 +- .../DistributedLeaseConfiguration.cs | 4 ++++ .../DistributedLeaseEfCore.cs | 2 +- DistributedLeaseManager.Example/Program.cs | 16 +++++++++++++--- 10 files changed, 36 insertions(+), 23 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index ab83f74..36bfe96 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -11,8 +11,8 @@ $(AssemblyName) distributed lease lock manager dlm concurrency aspnet - 1.1.0 - 1.0.0 + 2.0.0 + 2.0.0 Oleksandr Manyk https://github.com/f1x3d/DistributedLeaseManager diff --git a/DistributedLeaseManager.AzureBlobStorage/DistributedLeaseBlobStorage.cs b/DistributedLeaseManager.AzureBlobStorage/DistributedLeaseBlobStorage.cs index 5c70439..2935f9c 100644 --- a/DistributedLeaseManager.AzureBlobStorage/DistributedLeaseBlobStorage.cs +++ b/DistributedLeaseManager.AzureBlobStorage/DistributedLeaseBlobStorage.cs @@ -47,7 +47,7 @@ await _blobServiceClient } } - public async Task Find(string resourceCategory, Guid resourceId) + public async Task Find(string resourceCategory, string resourceId) { using var blobStream = new MemoryStream(); @@ -111,6 +111,6 @@ public async Task Remove(DistributedLease lease) private static string GetBlobPath(DistributedLease lease) => GetBlobPath(lease.ResourceCategory, lease.ResourceId); - private static string GetBlobPath(string resourceCategory, Guid resourceId) + private static string GetBlobPath(string resourceCategory, string resourceId) => $"{resourceCategory}/{resourceId}.json"; } diff --git a/DistributedLeaseManager.AzureCosmosDb/DistributedLeaseCosmosDb.cs b/DistributedLeaseManager.AzureCosmosDb/DistributedLeaseCosmosDb.cs index 9d864f4..d55b7d0 100644 --- a/DistributedLeaseManager.AzureCosmosDb/DistributedLeaseCosmosDb.cs +++ b/DistributedLeaseManager.AzureCosmosDb/DistributedLeaseCosmosDb.cs @@ -50,18 +50,18 @@ await _cosmosClient } } - public async Task Find(string resourceCategory, Guid resourceId) + public async Task Find(string resourceCategory, string resourceId) { try { var response = await _cosmosClient .GetDatabase(_options.DatabaseName) .GetContainer(_options.ContainerName) - .ReadItemAsync(resourceId.ToString(), new(GetPartitionKey(resourceCategory, resourceId))); + .ReadItemAsync(resourceId, new(GetPartitionKey(resourceCategory, resourceId))); return new() { - ResourceId = response.Resource["id"].ToObject(), + ResourceId = response.Resource["id"].ToObject(), ResourceCategory = response.Resource["category"].ToObject(), ExpirationTime = response.Resource["expirationTime"].ToObject(), ETag = response.ETag, @@ -102,7 +102,7 @@ public async Task Remove(DistributedLease lease) await _cosmosClient .GetDatabase(_options.DatabaseName) .GetContainer(_options.ContainerName) - .DeleteItemAsync(lease.ResourceId.ToString(), new(GetPartitionKey(lease))); + .DeleteItemAsync(lease.ResourceId, new(GetPartitionKey(lease))); return true; } @@ -110,17 +110,17 @@ await _cosmosClient private static string GetPartitionKey(DistributedLease lease) => GetPartitionKey(lease.ResourceCategory, lease.ResourceId); - private static string GetPartitionKey(string resourceCategory, Guid resourceId) + private static string GetPartitionKey(string resourceCategory, string resourceId) => $"{resourceCategory}/{resourceId}"; private JObject CreateLease(DistributedLease lease) => CreateLease(lease.ResourceId, lease.ResourceCategory, lease.ExpirationTime, GetPartitionKey(lease)); - private JObject CreateLease(Guid resourceId, string category, DateTimeOffset expirationTime, string partitionKey) + private JObject CreateLease(string resourceId, string category, DateTimeOffset expirationTime, string partitionKey) { return new() { - ["id"] = resourceId.ToString(), + ["id"] = resourceId, ["category"] = category, ["expirationTime"] = expirationTime, [_partitionKeyPropertyName] = partitionKey, diff --git a/DistributedLeaseManager.Core/DistributedLease.cs b/DistributedLeaseManager.Core/DistributedLease.cs index 022073e..6414c0e 100644 --- a/DistributedLeaseManager.Core/DistributedLease.cs +++ b/DistributedLeaseManager.Core/DistributedLease.cs @@ -4,7 +4,7 @@ public class DistributedLease { public const string DefaultResourceCategory = "Default"; - public Guid ResourceId { get; set; } + public string ResourceId { get; set; } = string.Empty; public string ResourceCategory { get; set; } = DefaultResourceCategory; public DateTimeOffset ExpirationTime { get; set; } public string ETag { get; set; } = string.Empty; diff --git a/DistributedLeaseManager.Core/DistributedLeaseManager.cs b/DistributedLeaseManager.Core/DistributedLeaseManager.cs index 8487ad1..94dcb57 100644 --- a/DistributedLeaseManager.Core/DistributedLeaseManager.cs +++ b/DistributedLeaseManager.Core/DistributedLeaseManager.cs @@ -10,12 +10,11 @@ public DistributedLeaseManager(IDistributedLeaseRepository repository) ?? throw new ArgumentNullException(nameof(repository)); } - public Task TryAcquireLease(Guid resourceId, TimeSpan duration) + public Task TryAcquireLease(string resourceId, TimeSpan duration) => TryAcquireLease(DistributedLease.DefaultResourceCategory, resourceId, duration); - public async Task TryAcquireLease( - string resourceCategory, - Guid resourceId, + public async Task TryAcquireLease(string resourceCategory, + string resourceId, TimeSpan duration) { await _repository.EnsureCreated(); diff --git a/DistributedLeaseManager.Core/IDistributedLeaseManager.cs b/DistributedLeaseManager.Core/IDistributedLeaseManager.cs index baf6340..af5ae2f 100644 --- a/DistributedLeaseManager.Core/IDistributedLeaseManager.cs +++ b/DistributedLeaseManager.Core/IDistributedLeaseManager.cs @@ -2,6 +2,6 @@ namespace DistributedLeaseManager.Core; public interface IDistributedLeaseManager { - Task TryAcquireLease(Guid resourceId, TimeSpan duration); - Task TryAcquireLease(string resourceCategory, Guid resourceId, TimeSpan duration); + Task TryAcquireLease(string resourceId, TimeSpan duration); + Task TryAcquireLease(string resourceCategory, string resourceId, TimeSpan duration); } diff --git a/DistributedLeaseManager.Core/IDistributedLeaseRepository.cs b/DistributedLeaseManager.Core/IDistributedLeaseRepository.cs index 65f618f..32f06b6 100644 --- a/DistributedLeaseManager.Core/IDistributedLeaseRepository.cs +++ b/DistributedLeaseManager.Core/IDistributedLeaseRepository.cs @@ -3,7 +3,7 @@ namespace DistributedLeaseManager.Core; public interface IDistributedLeaseRepository { Task EnsureCreated(); - Task Find(string resourceCategory, Guid resourceId); + Task Find(string resourceCategory, string resourceId); Task Add(DistributedLease lease); Task Update(DistributedLease lease); Task Remove(DistributedLease lease); diff --git a/DistributedLeaseManager.EntityFrameworkCore/DistributedLeaseConfiguration.cs b/DistributedLeaseManager.EntityFrameworkCore/DistributedLeaseConfiguration.cs index e2c8617..7991a50 100644 --- a/DistributedLeaseManager.EntityFrameworkCore/DistributedLeaseConfiguration.cs +++ b/DistributedLeaseManager.EntityFrameworkCore/DistributedLeaseConfiguration.cs @@ -28,6 +28,10 @@ public void Configure(EntityTypeBuilder builder) .Property(x => x.ResourceCategory) .HasMaxLength(255); + builder + .Property(x => x.ResourceId) + .HasMaxLength(255); + builder .Property(x => x.ETag) .HasMaxLength(36); diff --git a/DistributedLeaseManager.EntityFrameworkCore/DistributedLeaseEfCore.cs b/DistributedLeaseManager.EntityFrameworkCore/DistributedLeaseEfCore.cs index c2051d0..90282f2 100644 --- a/DistributedLeaseManager.EntityFrameworkCore/DistributedLeaseEfCore.cs +++ b/DistributedLeaseManager.EntityFrameworkCore/DistributedLeaseEfCore.cs @@ -31,7 +31,7 @@ public async Task Add(DistributedLease lease) } } - public Task Find(string resourceCategory, Guid resourceId) + public Task Find(string resourceCategory, string resourceId) => _dbContext.Leases.FirstOrDefaultAsync(x => x.ResourceCategory == resourceCategory && x.ResourceId == resourceId); diff --git a/DistributedLeaseManager.Example/Program.cs b/DistributedLeaseManager.Example/Program.cs index a2f6d94..57b1f05 100644 --- a/DistributedLeaseManager.Example/Program.cs +++ b/DistributedLeaseManager.Example/Program.cs @@ -1,13 +1,15 @@ using System.Reflection; using System.Text; using DistributedLeaseManager.Core; +using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; +using Newtonsoft.Json; var builder = WebApplication.CreateBuilder(args); // The following example uses a local Azurite instance // See https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite -//builder.Services.AddDistributedLeaseManager("UseDevelopmentStorage=true", "distributed-leases"); +//builder.Services.AddBlobStorageDistributedLeaseManager("UseDevelopmentStorage=true", "distributed-leases"); // The following example uses a local Azure Cosmos DB emulator // See https://learn.microsoft.com/en-us/azure/cosmos-db/emulator @@ -29,10 +31,18 @@ var app = builder.Build(); +app.MapGet("/distributed-leases/{category}/{resourceId}", async ([FromServices] IDistributedLeaseManager leaseManager, + string category, + string resourceId) => +{ + var leaseResult = await leaseManager.TryAcquireLease(category, resourceId, TimeSpan.FromMinutes(1)); + return JsonConvert.SerializeObject(leaseResult); +}); + app.MapGet("/distributed-leases", async (IServiceProvider serviceProvider) => { const int parallelGroupSize = 5; - var resourceId = Guid.NewGuid(); + var resourceId = Guid.NewGuid().ToString(); var result = new StringBuilder(); var lockObject = new object(); @@ -63,7 +73,7 @@ await Task.WhenAll(Enumerable.Range(2, parallelGroupSize) return result.ToString(); - async Task ProcessResource(Guid resourceId, int invocationNumber, bool simulateFail = false) + async Task ProcessResource(string resourceId, int invocationNumber, bool simulateFail = false) { await using var scope = serviceProvider.CreateAsyncScope(); var leaseManager = scope.ServiceProvider.GetRequiredService();