@@ -12,16 +12,11 @@ namespace NHibernate.Caches.StackExRedis
1212 /// </summary>
1313 internal partial class RedisKeyLocker
1414 {
15- private readonly string _regionName ;
1615 private readonly string _lockKeySuffix ;
1716 private readonly TimeSpan _lockTimeout ;
18- private readonly double _acquireLockTimeout ;
19- private readonly int _retryTimes ;
20- private readonly TimeSpan _maxRetryDelay ;
21- private readonly TimeSpan _minRetryDelay ;
22- private readonly ICacheLockRetryDelayProvider _lockRetryDelayProvider ;
2317 private readonly ICacheLockValueProvider _lockValueProvider ;
2418 private readonly IDatabase _database ;
19+ private readonly RetryPolicy < string , Func < string > > _retryPolicy ;
2520
2621 /// <summary>
2722 /// Default constructor.
@@ -34,16 +29,29 @@ public RedisKeyLocker(
3429 IDatabase database ,
3530 RedisCacheLockConfiguration configuration )
3631 {
37- _regionName = regionName ;
3832 _database = database ;
3933 _lockKeySuffix = configuration . KeySuffix ;
4034 _lockTimeout = configuration . KeyTimeout ;
41- _acquireLockTimeout = configuration . AcquireTimeout . TotalMilliseconds ;
42- _retryTimes = configuration . RetryTimes ;
43- _maxRetryDelay = configuration . MaxRetryDelay ;
44- _minRetryDelay = configuration . MinRetryDelay ;
45- _lockRetryDelayProvider = configuration . RetryDelayProvider ;
4635 _lockValueProvider = configuration . ValueProvider ;
36+
37+ var acquireTimeout = configuration . AcquireTimeout ;
38+ var retryTimes = configuration . RetryTimes ;
39+ var maxRetryDelay = configuration . MaxRetryDelay ;
40+ var minRetryDelay = configuration . MinRetryDelay ;
41+ var lockRetryDelayProvider = configuration . RetryDelayProvider ;
42+
43+ _retryPolicy = new RetryPolicy < string , Func < string > > (
44+ retryTimes ,
45+ acquireTimeout ,
46+ ( ) => lockRetryDelayProvider . GetValue ( minRetryDelay , maxRetryDelay )
47+ )
48+ . ShouldRetry ( s => s == null )
49+ . OnFaliure ( ( totalAttempts , elapsedMs , getKeysFn ) =>
50+ throw new CacheException ( "Unable to acquire cache lock: " +
51+ $ "region='{ regionName } ', " +
52+ $ "keys='{ getKeysFn ( ) } ', " +
53+ $ "total attempts='{ totalAttempts } ', " +
54+ $ "total acquiring time= '{ elapsedMs } ms'") ) ;
4755 }
4856
4957 /// <summary>
@@ -62,16 +70,10 @@ public string Lock(string key, string luaScript, RedisKey[] extraKeys, RedisValu
6270 throw new ArgumentNullException ( nameof ( key ) ) ;
6371 }
6472 var lockKey = $ "{ key } { _lockKeySuffix } ";
65- var totalAttempts = 0 ;
66- var lockTimer = new Stopwatch ( ) ;
67- lockTimer . Restart ( ) ;
68- do
73+ string Context ( ) => lockKey ;
74+
75+ return _retryPolicy . Execute ( ( ) =>
6976 {
70- if ( totalAttempts > 0 )
71- {
72- var retryDelay = _lockRetryDelayProvider . GetValue ( _minRetryDelay , _maxRetryDelay ) ;
73- Thread . Sleep ( retryDelay ) ;
74- }
7577 var lockValue = _lockValueProvider . GetValue ( ) ;
7678 if ( ! string . IsNullOrEmpty ( luaScript ) )
7779 {
@@ -80,7 +82,7 @@ public string Lock(string key, string luaScript, RedisKey[] extraKeys, RedisValu
8082 {
8183 keys = keys . Concat ( extraKeys ) . ToArray ( ) ;
8284 }
83- var values = new RedisValue [ ] { lockValue , ( long ) _lockTimeout . TotalMilliseconds } ;
85+ var values = new RedisValue [ ] { lockValue , ( long ) _lockTimeout . TotalMilliseconds } ;
8486 if ( extraValues != null )
8587 {
8688 values = values . Concat ( extraValues ) . ToArray ( ) ;
@@ -95,15 +97,9 @@ public string Lock(string key, string luaScript, RedisKey[] extraKeys, RedisValu
9597 {
9698 return lockValue ;
9799 }
98- totalAttempts ++ ;
99-
100- } while ( _retryTimes > totalAttempts - 1 && lockTimer . ElapsedMilliseconds < _acquireLockTimeout ) ;
101100
102- throw new CacheException ( "Unable to acquire cache lock: " +
103- $ "region='{ _regionName } ', " +
104- $ "key='{ key } ', " +
105- $ "total attempts='{ totalAttempts } ', " +
106- $ "total acquiring time= '{ lockTimer . ElapsedMilliseconds } ms'") ;
101+ return null ; // retry
102+ } , Context ) ;
107103 }
108104
109105 /// <summary>
@@ -125,21 +121,14 @@ public string LockMany(string[] keys, string luaScript, RedisKey[] extraKeys, Re
125121 {
126122 throw new ArgumentNullException ( nameof ( luaScript ) ) ;
127123 }
124+ string Context ( ) => string . Join ( "," , keys . Select ( o => $ "{ o } { _lockKeySuffix } ") ) ;
128125
129- var lockKeys = new RedisKey [ keys . Length ] ;
130- for ( var i = 0 ; i < keys . Length ; i ++ )
131- {
132- lockKeys [ i ] = $ "{ keys [ i ] } { _lockKeySuffix } ";
133- }
134- var totalAttempts = 0 ;
135- var lockTimer = new Stopwatch ( ) ;
136- lockTimer . Restart ( ) ;
137- do
126+ return _retryPolicy . Execute ( ( ) =>
138127 {
139- if ( totalAttempts > 0 )
128+ var lockKeys = new RedisKey [ keys . Length ] ;
129+ for ( var i = 0 ; i < keys . Length ; i ++ )
140130 {
141- var retryDelay = _lockRetryDelayProvider . GetValue ( _minRetryDelay , _maxRetryDelay ) ;
142- Thread . Sleep ( retryDelay ) ;
131+ lockKeys [ i ] = $ "{ keys [ i ] } { _lockKeySuffix } ";
143132 }
144133 var lockValue = _lockValueProvider . GetValue ( ) ;
145134 if ( extraKeys != null )
@@ -156,15 +145,9 @@ public string LockMany(string[] keys, string luaScript, RedisKey[] extraKeys, Re
156145 {
157146 return lockValue ;
158147 }
159- totalAttempts ++ ;
160-
161- } while ( _retryTimes > totalAttempts - 1 && lockTimer . ElapsedMilliseconds < _acquireLockTimeout ) ;
162148
163- throw new CacheException ( "Unable to acquire cache lock: " +
164- $ "region='{ _regionName } ', " +
165- $ "keys='{ string . Join ( "," , lockKeys ) } ', " +
166- $ "total attempts='{ totalAttempts } ', " +
167- $ "total acquiring time= '{ lockTimer . ElapsedMilliseconds } ms'") ;
149+ return null ; // retry
150+ } , Context ) ;
168151 }
169152
170153 /// <summary>
0 commit comments