Introduce Volo.Abp.DistributedLocking.Abstractions package #10032

pull/10325/head
Halil İbrahim Kalkan 4 years ago
parent 92c8aa56a8
commit 22d7408c09

@ -372,6 +372,7 @@ EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.AzureServiceBus", "src\Volo.Abp.AzureServiceBus\Volo.Abp.AzureServiceBus.csproj", "{808EC18E-C8CC-4F5C-82B6-984EADBBF85D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.EventBus.Azure", "src\Volo.Abp.EventBus.Azure\Volo.Abp.EventBus.Azure.csproj", "{FB27F78E-F10E-4810-9B8E-BCD67DCFC8A2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Authorization.Abstractions", "src\Volo.Abp.Authorization.Abstractions\Volo.Abp.Authorization.Abstractions.csproj", "{87B0C2A8-FE95-4779-8B9C-2181AA52B3FA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.TextTemplating.Core", "src\Volo.Abp.TextTemplating.Core\Volo.Abp.TextTemplating.Core.csproj", "{184E859A-282D-44D7-B8E9-FEA874644013}"
@ -393,10 +394,15 @@ EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.EventBus.Boxes", "src\Volo.Abp.EventBus.Boxes\Volo.Abp.EventBus.Boxes.csproj", "{6E289F31-7924-418B-9DAC-62A7CFADF916}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.DistributedLocking", "src\Volo.Abp.DistributedLocking\Volo.Abp.DistributedLocking.csproj", "{9A7EEA08-15BE-476D-8168-53039867038E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Auditing.Contracts", "src\Volo.Abp.Auditing.Contracts\Volo.Abp.Auditing.Contracts.csproj", "{508B6355-AD28-4E60-8549-266D21DBF2CF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Http.Client.Web", "src\Volo.Abp.Http.Client.Web\Volo.Abp.Http.Client.Web.csproj", "{F7407459-8AFA-45E4-83E9-9BB01412CC08}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.DistributedLocking.Abstractions", "src\Volo.Abp.DistributedLocking.Abstractions\Volo.Abp.DistributedLocking.Abstractions.csproj", "{CA805B77-D50C-431F-B3CB-1111C9C6E807}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.DistributedLocking.Abstractions.Tests", "test\Volo.Abp.DistributedLocking.Abstractions.Tests\Volo.Abp.DistributedLocking.Abstractions.Tests.csproj", "{C4F54FB5-C828-414D-BA03-E8E7A10C784D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -1187,6 +1193,14 @@ Global
{F7407459-8AFA-45E4-83E9-9BB01412CC08}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F7407459-8AFA-45E4-83E9-9BB01412CC08}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F7407459-8AFA-45E4-83E9-9BB01412CC08}.Release|Any CPU.Build.0 = Release|Any CPU
{CA805B77-D50C-431F-B3CB-1111C9C6E807}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CA805B77-D50C-431F-B3CB-1111C9C6E807}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CA805B77-D50C-431F-B3CB-1111C9C6E807}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CA805B77-D50C-431F-B3CB-1111C9C6E807}.Release|Any CPU.Build.0 = Release|Any CPU
{C4F54FB5-C828-414D-BA03-E8E7A10C784D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C4F54FB5-C828-414D-BA03-E8E7A10C784D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C4F54FB5-C828-414D-BA03-E8E7A10C784D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C4F54FB5-C828-414D-BA03-E8E7A10C784D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -1388,6 +1402,8 @@ Global
{9A7EEA08-15BE-476D-8168-53039867038E} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{508B6355-AD28-4E60-8549-266D21DBF2CF} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{F7407459-8AFA-45E4-83E9-9BB01412CC08} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{CA805B77-D50C-431F-B3CB-1111C9C6E807} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{C4F54FB5-C828-414D-BA03-E8E7A10C784D} = {447C8A77-E5F0-4538-8687-7383196D04EA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.DistributedLocking.Abstractions</AssemblyName>
<PackageId>Volo.Abp.DistributedLocking.Abstractions</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Core\Volo.Abp.Core.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,9 @@
using Volo.Abp.Modularity;
namespace Volo.Abp.DistributedLocking
{
public class AbpDistributedLockingAbstractionsModule : AbpModule
{
}
}

@ -0,0 +1,26 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
namespace Volo.Abp.DistributedLocking
{
public interface IAbpDistributedLock
{
/// <summary>
/// Tries to acquire a named lock.
/// Returns a disposable object to release the lock.
/// It is suggested to use this method within a using block.
/// Returns null if the lock could not be handled.
/// </summary>
/// <param name="name">The name of the lock</param>
/// <param name="timeout">Timeout value</param>
/// <param name="cancellationToken">Cancellation token</param>
[ItemCanBeNull]
Task<IAbpDistributedLockHandle> TryAcquireAsync(
string name,
TimeSpan timeout = default,
CancellationToken cancellationToken = default
);
}
}

@ -0,0 +1,9 @@
using System;
namespace Volo.Abp.DistributedLocking
{
public interface IAbpDistributedLockHandle : IAsyncDisposable
{
}
}

@ -0,0 +1,28 @@
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.DistributedLocking
{
public class LocalAbpDistributedLock : IAbpDistributedLock, ISingletonDependency
{
private readonly ConcurrentDictionary<string, SemaphoreSlim> _localSyncObjects = new();
public async Task<IAbpDistributedLockHandle> TryAcquireAsync(
string name,
TimeSpan timeout = default,
CancellationToken cancellationToken = default)
{
var semaphore = _localSyncObjects.GetOrAdd(name, _ => new SemaphoreSlim(1, 1));
if (!await semaphore.WaitAsync(timeout, cancellationToken))
{
return null;
}
return new LocalAbpDistributedLockHandle(semaphore);
}
}
}

@ -0,0 +1,21 @@
using System.Threading;
using System.Threading.Tasks;
namespace Volo.Abp.DistributedLocking
{
public class LocalAbpDistributedLockHandle : IAbpDistributedLockHandle
{
private readonly SemaphoreSlim _semaphore;
public LocalAbpDistributedLockHandle(SemaphoreSlim semaphore)
{
_semaphore = semaphore;
}
public ValueTask DisposeAsync()
{
_semaphore.Release();
return default;
}
}
}

@ -15,7 +15,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Core\Volo.Abp.Core.csproj" />
<ProjectReference Include="..\Volo.Abp.DistributedLocking.Abstractions\Volo.Abp.DistributedLocking.Abstractions.csproj" />
</ItemGroup>
<ItemGroup>

@ -2,6 +2,9 @@
namespace Volo.Abp.DistributedLocking
{
[DependsOn(
typeof(AbpDistributedLockingAbstractionsModule)
)]
public class AbpDistributedLockingModule : AbpModule
{

@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.test.props" />
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Volo.Abp.DistributedLocking.Abstractions\Volo.Abp.DistributedLocking.Abstractions.csproj" />
<ProjectReference Include="..\AbpTestBase\AbpTestBase.csproj" />
<ProjectReference Include="..\..\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkPackageVersion)" />
</ItemGroup>
</Project>

@ -0,0 +1,12 @@
using Volo.Abp.Testing;
namespace Volo.Abp.DistributedLocking
{
public class AbpDistributedLockingAbstractionsTestBase : AbpIntegratedTest<AbpDistributedLockingAbstractionsTestModule>
{
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
{
options.UseAutofac();
}
}
}

@ -0,0 +1,15 @@
using Volo.Abp.Autofac;
using Volo.Abp.Modularity;
namespace Volo.Abp.DistributedLocking
{
[DependsOn(
typeof(AbpTestBaseModule),
typeof(AbpDistributedLockingAbstractionsModule),
typeof(AbpAutofacModule)
)]
public class AbpDistributedLockingAbstractionsTestModule : AbpModule
{
}
}

@ -0,0 +1,73 @@
using System.Threading.Tasks;
using Shouldly;
using Xunit;
namespace Volo.Abp.DistributedLocking
{
public class LocalDistributedLock_Tests : AbpDistributedLockingAbstractionsTestBase
{
private readonly IAbpDistributedLock _distributedLock;
public LocalDistributedLock_Tests()
{
_distributedLock = GetRequiredService<IAbpDistributedLock>();
}
[Fact]
public void Should_Be_Instance_Of_LocalAbpDistributedLock()
{
_distributedLock.ShouldBeOfType<LocalAbpDistributedLock>();
}
[Fact]
public async Task Should_Lock_With_TryAcquire()
{
await using (var handle = await _distributedLock.TryAcquireAsync("lock1"))
{
handle.ShouldNotBeNull();
}
}
[Fact]
public async Task Should_Not_Acquire_If_Already_Locked()
{
await using (var handle = await _distributedLock.TryAcquireAsync("lock1"))
{
handle.ShouldNotBeNull();
await Task.Run(async () =>
{
await using (var handle2 = await _distributedLock.TryAcquireAsync("lock1"))
{
handle2.ShouldBeNull();
}
});
}
await Task.Run(async () =>
{
await using (var handle = await _distributedLock.TryAcquireAsync("lock1"))
{
handle.ShouldNotBeNull();
}
});
}
[Fact]
public async Task Should_Obtain_Multiple_Locks()
{
await using (var handle = await _distributedLock.TryAcquireAsync("lock1"))
{
handle.ShouldNotBeNull();
await Task.Run(async () =>
{
await using (var handle2 = await _distributedLock.TryAcquireAsync("lock2"))
{
handle2.ShouldNotBeNull();
}
});
}
}
}
}

@ -92,6 +92,7 @@ $projects = (
"framework/src/Volo.Abp.Ddd.Application",
"framework/src/Volo.Abp.Ddd.Application.Contracts",
"framework/src/Volo.Abp.Ddd.Domain",
"framework/src/Volo.Abp.DistributedLocking.Abstractions",
"framework/src/Volo.Abp.DistributedLocking",
"framework/src/Volo.Abp.Emailing",
"framework/src/Volo.Abp.EntityFrameworkCore",

Loading…
Cancel
Save