diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln
index 309be85ea1..1a4229ea34 100644
--- a/framework/Volo.Abp.sln
+++ b/framework/Volo.Abp.sln
@@ -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}
diff --git a/framework/src/Volo.Abp.DistributedLocking.Abstractions/FodyWeavers.xml b/framework/src/Volo.Abp.DistributedLocking.Abstractions/FodyWeavers.xml
new file mode 100644
index 0000000000..be0de3a908
--- /dev/null
+++ b/framework/src/Volo.Abp.DistributedLocking.Abstractions/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.DistributedLocking.Abstractions/FodyWeavers.xsd b/framework/src/Volo.Abp.DistributedLocking.Abstractions/FodyWeavers.xsd
new file mode 100644
index 0000000000..3f3946e282
--- /dev/null
+++ b/framework/src/Volo.Abp.DistributedLocking.Abstractions/FodyWeavers.xsd
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
+
+
+
+
+ A comma-separated list of error codes that can be safely ignored in assembly verification.
+
+
+
+
+ 'false' to turn off automatic generation of the XML Schema file.
+
+
+
+
+
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo.Abp.DistributedLocking.Abstractions.csproj b/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo.Abp.DistributedLocking.Abstractions.csproj
new file mode 100644
index 0000000000..ab828ee9d3
--- /dev/null
+++ b/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo.Abp.DistributedLocking.Abstractions.csproj
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+ netstandard2.0
+ Volo.Abp.DistributedLocking.Abstractions
+ Volo.Abp.DistributedLocking.Abstractions
+ $(AssetTargetFallback);portable-net45+win8+wp8+wpa81;
+ false
+ false
+ false
+
+
+
+
+
+
+
+
diff --git a/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo/Abp/DistributedLocking/AbpDistributedLockingAbstractionsModule.cs b/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo/Abp/DistributedLocking/AbpDistributedLockingAbstractionsModule.cs
new file mode 100644
index 0000000000..9c3832e49b
--- /dev/null
+++ b/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo/Abp/DistributedLocking/AbpDistributedLockingAbstractionsModule.cs
@@ -0,0 +1,9 @@
+using Volo.Abp.Modularity;
+
+namespace Volo.Abp.DistributedLocking
+{
+ public class AbpDistributedLockingAbstractionsModule : AbpModule
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo/Abp/DistributedLocking/IAbpDistributedLock.cs b/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo/Abp/DistributedLocking/IAbpDistributedLock.cs
new file mode 100644
index 0000000000..15f8921577
--- /dev/null
+++ b/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo/Abp/DistributedLocking/IAbpDistributedLock.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using JetBrains.Annotations;
+
+namespace Volo.Abp.DistributedLocking
+{
+ public interface IAbpDistributedLock
+ {
+ ///
+ /// 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.
+ ///
+ /// The name of the lock
+ /// Timeout value
+ /// Cancellation token
+ [ItemCanBeNull]
+ Task TryAcquireAsync(
+ string name,
+ TimeSpan timeout = default,
+ CancellationToken cancellationToken = default
+ );
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo/Abp/DistributedLocking/IAbpDistributedLockHandle.cs b/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo/Abp/DistributedLocking/IAbpDistributedLockHandle.cs
new file mode 100644
index 0000000000..baac5296c7
--- /dev/null
+++ b/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo/Abp/DistributedLocking/IAbpDistributedLockHandle.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Volo.Abp.DistributedLocking
+{
+ public interface IAbpDistributedLockHandle : IAsyncDisposable
+ {
+
+ }
+}
\ 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
new file mode 100644
index 0000000000..7a34106b0d
--- /dev/null
+++ b/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo/Abp/DistributedLocking/LocalAbpDistributedLock.cs
@@ -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 _localSyncObjects = new();
+
+ public async Task 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);
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo/Abp/DistributedLocking/LocalAbpDistributedLockHandle.cs b/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo/Abp/DistributedLocking/LocalAbpDistributedLockHandle.cs
new file mode 100644
index 0000000000..da12739311
--- /dev/null
+++ b/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo/Abp/DistributedLocking/LocalAbpDistributedLockHandle.cs
@@ -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;
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.DistributedLocking/Volo.Abp.DistributedLocking.csproj b/framework/src/Volo.Abp.DistributedLocking/Volo.Abp.DistributedLocking.csproj
index c4b590412d..17ad2f02a4 100644
--- a/framework/src/Volo.Abp.DistributedLocking/Volo.Abp.DistributedLocking.csproj
+++ b/framework/src/Volo.Abp.DistributedLocking/Volo.Abp.DistributedLocking.csproj
@@ -15,7 +15,7 @@
-
+
diff --git a/framework/src/Volo.Abp.DistributedLocking/Volo/Abp/DistributedLocking/AbpDistributedLockingModule.cs b/framework/src/Volo.Abp.DistributedLocking/Volo/Abp/DistributedLocking/AbpDistributedLockingModule.cs
index 877ac54244..3bfdbbf3f3 100644
--- a/framework/src/Volo.Abp.DistributedLocking/Volo/Abp/DistributedLocking/AbpDistributedLockingModule.cs
+++ b/framework/src/Volo.Abp.DistributedLocking/Volo/Abp/DistributedLocking/AbpDistributedLockingModule.cs
@@ -2,6 +2,9 @@
namespace Volo.Abp.DistributedLocking
{
+ [DependsOn(
+ typeof(AbpDistributedLockingAbstractionsModule)
+ )]
public class AbpDistributedLockingModule : AbpModule
{
diff --git a/framework/test/Volo.Abp.DistributedLocking.Abstractions.Tests/Volo.Abp.DistributedLocking.Abstractions.Tests.csproj b/framework/test/Volo.Abp.DistributedLocking.Abstractions.Tests/Volo.Abp.DistributedLocking.Abstractions.Tests.csproj
new file mode 100644
index 0000000000..8194846f0c
--- /dev/null
+++ b/framework/test/Volo.Abp.DistributedLocking.Abstractions.Tests/Volo.Abp.DistributedLocking.Abstractions.Tests.csproj
@@ -0,0 +1,18 @@
+
+
+
+
+
+ net6.0
+ true
+
+
+
+
+
+
+
+
+
+
+
diff --git a/framework/test/Volo.Abp.DistributedLocking.Abstractions.Tests/Volo/Abp/DistributedLocking/AbpDistributedLockingAbstractionsTestBase.cs b/framework/test/Volo.Abp.DistributedLocking.Abstractions.Tests/Volo/Abp/DistributedLocking/AbpDistributedLockingAbstractionsTestBase.cs
new file mode 100644
index 0000000000..074bd342d2
--- /dev/null
+++ b/framework/test/Volo.Abp.DistributedLocking.Abstractions.Tests/Volo/Abp/DistributedLocking/AbpDistributedLockingAbstractionsTestBase.cs
@@ -0,0 +1,12 @@
+using Volo.Abp.Testing;
+
+namespace Volo.Abp.DistributedLocking
+{
+ public class AbpDistributedLockingAbstractionsTestBase : AbpIntegratedTest
+ {
+ protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
+ {
+ options.UseAutofac();
+ }
+ }
+}
diff --git a/framework/test/Volo.Abp.DistributedLocking.Abstractions.Tests/Volo/Abp/DistributedLocking/AbpDistributedLockingAbstractionsTestModule.cs b/framework/test/Volo.Abp.DistributedLocking.Abstractions.Tests/Volo/Abp/DistributedLocking/AbpDistributedLockingAbstractionsTestModule.cs
new file mode 100644
index 0000000000..cfc9278335
--- /dev/null
+++ b/framework/test/Volo.Abp.DistributedLocking.Abstractions.Tests/Volo/Abp/DistributedLocking/AbpDistributedLockingAbstractionsTestModule.cs
@@ -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
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.DistributedLocking.Abstractions.Tests/Volo/Abp/DistributedLocking/LocalDistributedLock_Tests.cs b/framework/test/Volo.Abp.DistributedLocking.Abstractions.Tests/Volo/Abp/DistributedLocking/LocalDistributedLock_Tests.cs
new file mode 100644
index 0000000000..ce7fda009d
--- /dev/null
+++ b/framework/test/Volo.Abp.DistributedLocking.Abstractions.Tests/Volo/Abp/DistributedLocking/LocalDistributedLock_Tests.cs
@@ -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();
+ }
+
+ [Fact]
+ public void Should_Be_Instance_Of_LocalAbpDistributedLock()
+ {
+ _distributedLock.ShouldBeOfType();
+ }
+
+ [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();
+ }
+ });
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/nupkg/common.ps1 b/nupkg/common.ps1
index 7d48c1ac1d..9fae28d572 100644
--- a/nupkg/common.ps1
+++ b/nupkg/common.ps1
@@ -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",