diff --git a/src/abstractions/DarkLoop.Azure.Functions.Authorization.Abstractions.csproj b/src/abstractions/DarkLoop.Azure.Functions.Authorization.Abstractions.csproj
index 9b757d4..ac45516 100644
--- a/src/abstractions/DarkLoop.Azure.Functions.Authorization.Abstractions.csproj
+++ b/src/abstractions/DarkLoop.Azure.Functions.Authorization.Abstractions.csproj
@@ -21,6 +21,7 @@
+
diff --git a/src/abstractions/FunctionsAuthorizationCoreServiceCollectionExtensions.cs b/src/abstractions/FunctionsAuthorizationCoreServiceCollectionExtensions.cs
index 12b2ea8..a2fda38 100644
--- a/src/abstractions/FunctionsAuthorizationCoreServiceCollectionExtensions.cs
+++ b/src/abstractions/FunctionsAuthorizationCoreServiceCollectionExtensions.cs
@@ -2,6 +2,7 @@
// Copyright (c) DarkLoop. All rights reserved.
//
+using AsyncKeyedLock;
using DarkLoop.Azure.Functions.Authorization.Cache;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
@@ -20,7 +21,8 @@ public static IServiceCollection AddFunctionsAuthorizationCore(this IServiceColl
return services
.AddSingleton()
- .AddSingleton(typeof(IFunctionsAuthorizationFilterCache<>), typeof(FunctionsAuthorizationFilterCache<>));
+ .AddSingleton(typeof(IFunctionsAuthorizationFilterCache<>), typeof(FunctionsAuthorizationFilterCache<>))
+ .AddSingleton(new AsyncKeyedLocker(o => { o.PoolSize = 20; o.PoolInitialFill = 1; }));
}
}
}
diff --git a/src/abstractions/FunctionsAuthorizationProvider.cs b/src/abstractions/FunctionsAuthorizationProvider.cs
index 1b380d2..b09ff32 100644
--- a/src/abstractions/FunctionsAuthorizationProvider.cs
+++ b/src/abstractions/FunctionsAuthorizationProvider.cs
@@ -6,6 +6,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
+using AsyncKeyedLock;
using DarkLoop.Azure.Functions.Authorization.Cache;
using DarkLoop.Azure.Functions.Authorization.Internal;
using DarkLoop.Azure.Functions.Authorization.Properties;
@@ -26,6 +27,7 @@ internal class FunctionsAuthorizationProvider : IFunctionsAuthorizationProvider
private readonly IFunctionsAuthorizationFilterCache _filterCache;
private readonly FunctionAuthorizationMetadataCollection _metadataStore;
private readonly IOptionsMonitor _options;
+ private readonly AsyncKeyedLocker _asyncKeyedLocker;
private readonly ILogger _logger;
///
@@ -41,6 +43,7 @@ public FunctionsAuthorizationProvider(
IFunctionsAuthorizationFilterCache cache,
IOptions options,
IOptionsMonitor configOptions,
+ AsyncKeyedLocker asyncKeyedLocker,
ILogger logger)
{
Check.NotNull(schemeProvider, nameof(schemeProvider));
@@ -53,6 +56,7 @@ public FunctionsAuthorizationProvider(
_filterCache = cache;
_metadataStore = options.Value.AuthorizationMetadata;
_options = configOptions;
+ _asyncKeyedLocker = asyncKeyedLocker;
_logger = logger;
}
@@ -71,9 +75,7 @@ public async Task GetAuthorizationAsync(string func
var asyncKey = $"fap:{functionName}";
- await KeyedMonitor.EnterAsync(asyncKey, unblockOnFirstExit: true);
-
- try
+ using (await _asyncKeyedLocker.LockAsync(asyncKey).ConfigureAwait(false))
{
if (_filterCache.TryGetFilter(key, out filter))
{
@@ -110,10 +112,6 @@ public async Task GetAuthorizationAsync(string func
return filter;
}
- finally
- {
- KeyedMonitor.Exit(asyncKey);
- }
}
private async Task GetPolicy(IAuthorizationPolicyProvider policyProvider, IEnumerable authData)
diff --git a/src/abstractions/Internal/KeyedMonitor.cs b/src/abstractions/Internal/KeyedMonitor.cs
deleted file mode 100644
index e6b9bbb..0000000
--- a/src/abstractions/Internal/KeyedMonitor.cs
+++ /dev/null
@@ -1,117 +0,0 @@
-//
-// Copyright (c) DarkLoop. All rights reserved.
-//
-
-using System;
-using System.Collections.Concurrent;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace DarkLoop.Azure.Functions.Authorization.Internal
-{
- ///
- /// Provides a way to monitor a key and block other threads from entering the same key.
- ///
- internal static class KeyedMonitor
- {
- private static readonly ConcurrentDictionary