Skip to content

Commit

Permalink
Merge pull request #13972 from abpframework/liangshiwei/distributedlock
Browse files Browse the repository at this point in the history
  • Loading branch information
maliming authored Sep 8, 2022
2 parents 3490a50 + d37daa5 commit 6514385
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 7 deletions.
19 changes: 19 additions & 0 deletions docs/en/Distributed-Locking.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<AbpDistributedLockOptions>(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.
Expand Down
19 changes: 19 additions & 0 deletions docs/zh-Hans/Distributed-Locking.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,25 @@ namespace AbpDemo
* `timeout` (`TimeSpan`): 等待获取锁的超时值. 默认值为`TimeSpan.Zero`, 这意味着如果锁已经被另一个应用程序拥有, 它不会等待.
* `cancellationToken`: 取消令牌可在触发后取消操作.

### 配置

#### AbpDistributedLockOptions

`AbpDistributedLockOptions` 是配置分布式锁的主要选项类.

**示例: 设置应用程序的分布式锁Key前缀**

Configure<AbpDistributedLockOptions>(options =>
{
options.KeyPrefix = "MyApp1";
});

> 在你的[模块类](Module-Development-Basics.md)中的 `ConfigureServices` 方法进行配置.

##### 可用选项

* KeyPrefix (string, 默认值: null): 指定分布式锁名称前缀.

### 使用DistributedLock库的API

ABP的`IAbpDistributedLock`服务非常有限, 主要用于ABP框架的内部使用. 对于你自己的应用程序, 可以使用DistributedLock库自己的API. 参见[文档](https://github.com/madelson/DistributedLock)详细信息.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace Volo.Abp.DistributedLocking;

public class AbpDistributedLockOptions
{
/// <summary>
/// DistributedLock key prefix.
/// </summary>
public string KeyPrefix { get; set; }

public AbpDistributedLockOptions()
{
KeyPrefix = "";
}
}
Original file line number Diff line number Diff line change
@@ -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<AbpDistributedLockOptions> options)
{
Options = options.Value;
}

public virtual string NormalizeKey(string name)
{
return $"{Options.KeyPrefix}{name}";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Volo.Abp.DistributedLocking;

public interface IDistributedLockKeyNormalizer
{
string NormalizeKey(string name);

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,22 @@ namespace Volo.Abp.DistributedLocking;
public class LocalAbpDistributedLock : IAbpDistributedLock, ISingletonDependency
{
private readonly ConcurrentDictionary<string, SemaphoreSlim> _localSyncObjects = new();
protected IDistributedLockKeyNormalizer DistributedLockKeyNormalizer { get; }

public LocalAbpDistributedLock(IDistributedLockKeyNormalizer distributedLockKeyNormalizer)
{
DistributedLockKeyNormalizer = distributedLockKeyNormalizer;
}

public async Task<IAbpDistributedLockHandle> 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))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<AbpDistributedLockDaprOptions> distributedLockDaprOptions,
IOptions<AbpDaprOptions> daprOptions)
IOptions<AbpDaprOptions> daprOptions,
IDistributedLockKeyNormalizer distributedLockKeyNormalizer)
{
DaprClientFactory = daprClientFactory;
DistributedLockKeyNormalizer = distributedLockKeyNormalizer;
DaprOptions = daprOptions.Value;
DistributedLockDaprOptions = distributedLockDaprOptions.Value;
}
Expand All @@ -32,10 +35,11 @@ public async Task<IAbpDistributedLockHandle> 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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<IAbpDistributedLockHandle> TryAcquireAsync(
Expand All @@ -27,11 +31,12 @@ public async Task<IAbpDistributedLockHandle> 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)
);
Expand Down

0 comments on commit 6514385

Please sign in to comment.