diff --git a/Directory.Packages.props b/Directory.Packages.props index 416a91cec339..59cb1476c215 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -43,6 +43,7 @@ + diff --git a/src/Umbraco.PublishedCache.HybridCache/Extensions/HybridCacheExtensions.cs b/src/Umbraco.PublishedCache.HybridCache/Extensions/HybridCacheExtensions.cs index ccd5897494eb..0fb86bf63019 100644 --- a/src/Umbraco.PublishedCache.HybridCache/Extensions/HybridCacheExtensions.cs +++ b/src/Umbraco.PublishedCache.HybridCache/Extensions/HybridCacheExtensions.cs @@ -1,4 +1,5 @@ using System.Collections.Concurrent; +using AsyncKeyedLock; using Microsoft.Extensions.Caching.Hybrid; namespace Umbraco.Cms.Infrastructure.HybridCache.Extensions; @@ -10,7 +11,7 @@ internal static class HybridCacheExtensions { // Per-key semaphores to ensure the GetOrCreateAsync + RemoveAsync sequence // executes atomically for a given cache key. - private static readonly ConcurrentDictionary _keyLocks = new(); + private static readonly AsyncKeyedLocker _keyLocks = new(); /// /// Returns true if the cache contains an item with a matching key. @@ -45,13 +46,7 @@ public static async Task ExistsAsync(this Microsoft.Extensions.Caching. { var exists = true; - // Acquire a per-key semaphore so that GetOrCreateAsync and the possible RemoveAsync - // complete without another thread retrieving/creating the same key in-between. - SemaphoreSlim sem = _keyLocks.GetOrAdd(key, _ => new SemaphoreSlim(1, 1)); - - await sem.WaitAsync().ConfigureAwait(false); - - try + using (await _keyLocks.LockAsync(key, token)) { T? result = await cache.GetOrCreateAsync( key, @@ -74,16 +69,5 @@ public static async Task ExistsAsync(this Microsoft.Extensions.Caching. return (exists, result); } - finally - { - sem.Release(); - - // Only remove the semaphore mapping if it still points to the same instance we used. - // This avoids removing another thread's semaphore or corrupting the map. - if (_keyLocks.TryGetValue(key, out SemaphoreSlim? current) && ReferenceEquals(current, sem)) - { - _keyLocks.TryRemove(key, out _); - } - } } } diff --git a/src/Umbraco.PublishedCache.HybridCache/Umbraco.PublishedCache.HybridCache.csproj b/src/Umbraco.PublishedCache.HybridCache/Umbraco.PublishedCache.HybridCache.csproj index da5227544d56..2487466d49dd 100644 --- a/src/Umbraco.PublishedCache.HybridCache/Umbraco.PublishedCache.HybridCache.csproj +++ b/src/Umbraco.PublishedCache.HybridCache/Umbraco.PublishedCache.HybridCache.csproj @@ -12,6 +12,7 @@ +