1- using DistributedCache . Helpers ;
1+ using DistributedCache . Dtos ;
2+ using DistributedCache . Helpers ;
23using DistributedCache . Options ;
34using DistributedCache . Services . Interfaces ;
45using Microsoft . Extensions . Options ;
78
89namespace DistributedCache . Services . Implementations ;
910
10- internal class RedisCacheService < T > ( IRedisClient redisClient , IOptions < CacheConfigurationOptions > options )
11+ internal class RedisCacheService < T > (
12+ IRedisClient redisClient ,
13+ IOptions < CacheConfigurationOptions > options ,
14+ RedisLockService lockService )
1115 : ICacheService < T >
1216 where T : class , ICacheEntity
1317{
1418 private readonly IRedisDatabase _redisDatabase = redisClient . GetDefaultDatabase ( ) ;
1519 private readonly CacheConfigurationOptions _config = options . Value ;
1620 private readonly string _moduleName = typeof ( T ) . Assembly . GetName ( ) . Name ! ;
17- private readonly TimeSpan _lockExpiry = options . Value . DistributedLockDuration ;
18- private readonly TimeSpan _lockRetryDelay = TimeSpan . FromMilliseconds ( 10 ) ;
1921
2022 public async ValueTask < T > GetOrCreateAsync ( string key , Func < CancellationToken , ValueTask < T > > factory ,
2123 TimeSpan ? expiration = null , IReadOnlyCollection < string > ? tags = null , CancellationToken token = default )
@@ -24,18 +26,18 @@ public async ValueTask<T> GetOrCreateAsync(string key, Func<CancellationToken, V
2426 ? KeyFormatHelper . GetPrefixedKey ( key )
2527 : KeyFormatHelper . GetPrefixedKey ( key , _moduleName ) ;
2628
27- var lockKey = KeyFormatHelper . GetLockKey ( prefixedKey ) ;
29+
2830 var lockValue = Guid . NewGuid ( ) . ToString ( ) ;
2931
3032 while ( true )
3133 {
3234 token . ThrowIfCancellationRequested ( ) ;
3335
34- var isLocked = await _redisDatabase . Database . KeyExistsAsync ( lockKey ) ;
36+ var isLocked = await lockService . CheckForLockAsync ( prefixedKey ) ;
3537
3638 if ( isLocked )
3739 {
38- await WaitForLockReleaseAsync ( lockKey , token ) ;
40+ await lockService . WaitForLockReleaseAsync ( prefixedKey , token ) ;
3941 continue ;
4042 }
4143
@@ -45,11 +47,11 @@ public async ValueTask<T> GetOrCreateAsync(string key, Func<CancellationToken, V
4547 return cachedValue ;
4648 }
4749
48- var lockAcquired = await AcquireLockAsync ( lockKey , lockValue ) ;
50+ var lockAcquired = await lockService . AcquireLockAsync ( prefixedKey , lockValue ) ;
4951
5052 if ( ! lockAcquired )
5153 {
52- await WaitForLockReleaseAsync ( lockKey , token ) ;
54+ await lockService . WaitForLockReleaseAsync ( prefixedKey , token ) ;
5355 continue ;
5456 }
5557
@@ -64,7 +66,7 @@ public async ValueTask<T> GetOrCreateAsync(string key, Func<CancellationToken, V
6466 }
6567 finally
6668 {
67- await ReleaseLockAsync ( lockKey , lockValue ) ;
69+ await lockService . ReleaseLockAsync ( prefixedKey , lockValue ) ;
6870 }
6971 }
7072
@@ -139,30 +141,4 @@ public async ValueTask RemoveByTagsAsync(IEnumerable<string> tags, CancellationT
139141 var tasks = tags . Select ( tag => RemoveByTagAsync ( tag , token ) . AsTask ( ) ) ;
140142 await Task . WhenAll ( tasks ) ;
141143 }
142-
143- private async Task < bool > AcquireLockAsync ( string lockKey , string lockValue )
144- {
145- return await _redisDatabase . Database . StringSetAsync ( lockKey , lockValue , _lockExpiry , When . NotExists ) ;
146- }
147-
148- private async Task WaitForLockReleaseAsync ( string lockKey , CancellationToken token )
149- {
150- while ( await _redisDatabase . Database . KeyExistsAsync ( lockKey ) && ! token . IsCancellationRequested )
151- {
152- await Task . Delay ( _lockRetryDelay , token ) ;
153- }
154- }
155-
156- private async Task ReleaseLockAsync ( string lockKey , string lockValue )
157- {
158- // Check if the current instance owns the lock before releasing it
159- const string script = @"
160- if redis.call('GET', KEYS[1]) == ARGV[1] then
161- return redis.call('DEL', KEYS[1])
162- else
163- return 0
164- end" ;
165-
166- await _redisDatabase . Database . ScriptEvaluateAsync ( script , [ lockKey ] , [ lockValue ] ) ;
167- }
168144}
0 commit comments