diff --git a/docs/en/Distributed-Locking.md b/docs/en/Distributed-Locking.md index d29b60ad04a..a1e653a6a61 100644 --- a/docs/en/Distributed-Locking.md +++ b/docs/en/Distributed-Locking.md @@ -101,6 +101,25 @@ namespace AbpDemo * `timeout` (`TimeSpan`): A timeout value to wait to obtain the lock. Default value is `TimeSpan.Zero`, which means it doesn't wait if the lock is already owned by another application. * `cancellationToken`: A cancellation token that can be triggered later to cancel the operation. +### Configuration + +#### AbpDistributedLockOptions + +`AbpDistributedLockOptions` is the main options class to configure the distributed locking. + +**Example: Set the distributed lock key prefix for the application** + +Configure(options => +{ + options.KeyPrefix = "MyApp1"; +}); + +> Write that code inside the `ConfigureServices` method of your [module class](Module-Development-Basics.md). + +##### Available Options + +* KeyPrefix (string, default: null): Specify the lock name prefix. + ### Using DistributedLock Library's API ABP's `IAbpDistributedLock` service is very limited and mainly designed to be internally used by the ABP Framework. For your own applications, you can use the DistributedLock library's own API. See its [own documentation](https://github.com/madelson/DistributedLock) for details. diff --git a/docs/zh-Hans/Distributed-Locking.md b/docs/zh-Hans/Distributed-Locking.md index 2176230403c..a570f598af9 100644 --- a/docs/zh-Hans/Distributed-Locking.md +++ b/docs/zh-Hans/Distributed-Locking.md @@ -101,6 +101,25 @@ namespace AbpDemo * `timeout` (`TimeSpan`): 等待获取锁的超时值. 默认值为`TimeSpan.Zero`, 这意味着如果锁已经被另一个应用程序拥有, 它不会等待. * `cancellationToken`: 取消令牌可在触发后取消操作. +### 配置 + +#### AbpDistributedLockOptions + +`AbpDistributedLockOptions` 是配置分布式锁的主要选项类. + +**示例: 设置应用程序的分布式锁Key前缀** + +Configure(options => +{ + options.KeyPrefix = "MyApp1"; +}); + +> 在你的[模块类](Module-Development-Basics.md)中的 `ConfigureServices` 方法进行配置. + +##### 可用选项 + +* KeyPrefix (string, 默认值: null): 指定分布式锁名称前缀. + ### 使用DistributedLock库的API ABP的`IAbpDistributedLock`服务非常有限, 主要用于ABP框架的内部使用. 对于你自己的应用程序, 可以使用DistributedLock库自己的API. 参见[文档](https://github.com/madelson/DistributedLock)详细信息. diff --git a/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo/Abp/DistributedLocking/AbpDistributedLockOptions.cs b/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo/Abp/DistributedLocking/AbpDistributedLockOptions.cs new file mode 100644 index 00000000000..8a885ae877b --- /dev/null +++ b/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo/Abp/DistributedLocking/AbpDistributedLockOptions.cs @@ -0,0 +1,14 @@ +namespace Volo.Abp.DistributedLocking; + +public class AbpDistributedLockOptions +{ + /// + /// DistributedLock key prefix. + /// + public string KeyPrefix { get; set; } + + public AbpDistributedLockOptions() + { + KeyPrefix = ""; + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo/Abp/DistributedLocking/DistributedLockKeyNormalizer.cs b/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo/Abp/DistributedLocking/DistributedLockKeyNormalizer.cs new file mode 100644 index 00000000000..bce237c5e33 --- /dev/null +++ b/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo/Abp/DistributedLocking/DistributedLockKeyNormalizer.cs @@ -0,0 +1,19 @@ +using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.DistributedLocking; + +public class DistributedLockKeyNormalizer : IDistributedLockKeyNormalizer, ITransientDependency +{ + protected AbpDistributedLockOptions Options { get; } + + public DistributedLockKeyNormalizer(IOptions options) + { + Options = options.Value; + } + + public virtual string NormalizeKey(string name) + { + return $"{Options.KeyPrefix}{name}"; + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo/Abp/DistributedLocking/IDistributedLockKeyNormalizer.cs b/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo/Abp/DistributedLocking/IDistributedLockKeyNormalizer.cs new file mode 100644 index 00000000000..13f30cca28c --- /dev/null +++ b/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo/Abp/DistributedLocking/IDistributedLockKeyNormalizer.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.DistributedLocking; + +public interface IDistributedLockKeyNormalizer +{ + string NormalizeKey(string name); + +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo/Abp/DistributedLocking/LocalAbpDistributedLock.cs b/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo/Abp/DistributedLocking/LocalAbpDistributedLock.cs index 9eb7a76b9dd..fdec4f1d3f4 100644 --- a/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo/Abp/DistributedLocking/LocalAbpDistributedLock.cs +++ b/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo/Abp/DistributedLocking/LocalAbpDistributedLock.cs @@ -9,15 +9,22 @@ namespace Volo.Abp.DistributedLocking; public class LocalAbpDistributedLock : IAbpDistributedLock, ISingletonDependency { private readonly ConcurrentDictionary _localSyncObjects = new(); + protected IDistributedLockKeyNormalizer DistributedLockKeyNormalizer { get; } + public LocalAbpDistributedLock(IDistributedLockKeyNormalizer distributedLockKeyNormalizer) + { + DistributedLockKeyNormalizer = distributedLockKeyNormalizer; + } + public async Task TryAcquireAsync( string name, TimeSpan timeout = default, CancellationToken cancellationToken = default) { Check.NotNullOrWhiteSpace(name, nameof(name)); - - var semaphore = _localSyncObjects.GetOrAdd(name, _ => new SemaphoreSlim(1, 1)); + var key = DistributedLockKeyNormalizer.NormalizeKey(name); + + var semaphore = _localSyncObjects.GetOrAdd(key, _ => new SemaphoreSlim(1, 1)); if (!await semaphore.WaitAsync(timeout, cancellationToken)) { diff --git a/framework/src/Volo.Abp.DistributedLocking.Dapr/Volo/Abp/DistributedLocking/Dapr/DaprAbpDistributedLock.cs b/framework/src/Volo.Abp.DistributedLocking.Dapr/Volo/Abp/DistributedLocking/Dapr/DaprAbpDistributedLock.cs index 7f95a565420..b4116c105c8 100644 --- a/framework/src/Volo.Abp.DistributedLocking.Dapr/Volo/Abp/DistributedLocking/Dapr/DaprAbpDistributedLock.cs +++ b/framework/src/Volo.Abp.DistributedLocking.Dapr/Volo/Abp/DistributedLocking/Dapr/DaprAbpDistributedLock.cs @@ -10,13 +10,16 @@ public class DaprAbpDistributedLock : IAbpDistributedLock, ITransientDependency protected AbpDaprClientFactory DaprClientFactory { get; } protected AbpDistributedLockDaprOptions DistributedLockDaprOptions { get; } protected AbpDaprOptions DaprOptions { get; } + protected IDistributedLockKeyNormalizer DistributedLockKeyNormalizer { get; } public DaprAbpDistributedLock( AbpDaprClientFactory daprClientFactory, IOptions distributedLockDaprOptions, - IOptions daprOptions) + IOptions daprOptions, + IDistributedLockKeyNormalizer distributedLockKeyNormalizer) { DaprClientFactory = daprClientFactory; + DistributedLockKeyNormalizer = distributedLockKeyNormalizer; DaprOptions = daprOptions.Value; DistributedLockDaprOptions = distributedLockDaprOptions.Value; } @@ -32,10 +35,11 @@ public async Task TryAcquireAsync( } var daprClient = await DaprClientFactory.CreateAsync(); + var key = DistributedLockKeyNormalizer.NormalizeKey(name); var lockResponse = await daprClient.Lock( DistributedLockDaprOptions.StoreName, - name, + key, DaprOptions.AppId, (int)timeout.TotalSeconds, cancellationToken); diff --git a/framework/src/Volo.Abp.DistributedLocking/Volo/Abp/DistributedLocking/MedallionAbpDistributedLock.cs b/framework/src/Volo.Abp.DistributedLocking/Volo/Abp/DistributedLocking/MedallionAbpDistributedLock.cs index 769303a348e..0defc5a75f4 100644 --- a/framework/src/Volo.Abp.DistributedLocking/Volo/Abp/DistributedLocking/MedallionAbpDistributedLock.cs +++ b/framework/src/Volo.Abp.DistributedLocking/Volo/Abp/DistributedLocking/MedallionAbpDistributedLock.cs @@ -12,13 +12,17 @@ public class MedallionAbpDistributedLock : IAbpDistributedLock, ITransientDepend { protected IDistributedLockProvider DistributedLockProvider { get; } protected ICancellationTokenProvider CancellationTokenProvider { get; } + + protected IDistributedLockKeyNormalizer DistributedLockKeyNormalizer { get; } public MedallionAbpDistributedLock( IDistributedLockProvider distributedLockProvider, - ICancellationTokenProvider cancellationTokenProvider) + ICancellationTokenProvider cancellationTokenProvider, + IDistributedLockKeyNormalizer distributedLockKeyNormalizer) { DistributedLockProvider = distributedLockProvider; CancellationTokenProvider = cancellationTokenProvider; + DistributedLockKeyNormalizer = distributedLockKeyNormalizer; } public async Task TryAcquireAsync( @@ -27,11 +31,12 @@ public async Task TryAcquireAsync( CancellationToken cancellationToken = default) { Check.NotNullOrWhiteSpace(name, nameof(name)); - + var key = DistributedLockKeyNormalizer.NormalizeKey(name); + CancellationTokenProvider.FallbackToProvider(cancellationToken); var handle = await DistributedLockProvider.TryAcquireLockAsync( - name, + key, timeout, CancellationTokenProvider.FallbackToProvider(cancellationToken) );