@@ -5,20 +5,20 @@ namespace EasyCaching.Core
5
5
using System ;
6
6
using System . Collections . Generic ;
7
7
using System . Diagnostics ;
8
- using System . Linq ;
9
- using System . Threading ;
10
- using System . Threading . Tasks ;
11
- using EasyCaching . Core . Configurations ;
8
+ using System . Linq ;
9
+ using System . Threading ;
10
+ using System . Threading . Tasks ;
11
+ using EasyCaching . Core . Configurations ;
12
12
using EasyCaching . Core . Diagnostics ;
13
13
14
14
public abstract class EasyCachingAbstractProvider : IEasyCachingProvider
15
15
{
16
16
protected static readonly DiagnosticListener s_diagnosticListener =
17
- new DiagnosticListener ( EasyCachingDiagnosticListenerExtensions . DiagnosticListenerName ) ;
18
-
19
- private readonly IDistributedLockFactory _lockFactory ;
20
- private readonly BaseProviderOptions _options ;
21
-
17
+ new DiagnosticListener ( EasyCachingDiagnosticListenerExtensions . DiagnosticListenerName ) ;
18
+
19
+ private readonly IDistributedLockFactory _lockFactory ;
20
+ private readonly BaseProviderOptions _options ;
21
+
22
22
protected string ProviderName { get ; set ; }
23
23
protected bool IsDistributedProvider { get ; set ; }
24
24
protected int ProviderMaxRdSecond { get ; set ; }
@@ -36,13 +36,13 @@ public abstract class EasyCachingAbstractProvider : IEasyCachingProvider
36
36
37
37
protected EasyCachingAbstractProvider ( ) { }
38
38
39
- protected EasyCachingAbstractProvider ( IDistributedLockFactory lockFactory , BaseProviderOptions options )
40
- {
41
- _lockFactory = lockFactory ;
42
- _options = options ;
43
- }
44
-
45
- public abstract object BaseGetDatabse ( ) ;
39
+ protected EasyCachingAbstractProvider ( IDistributedLockFactory lockFactory , BaseProviderOptions options )
40
+ {
41
+ _lockFactory = lockFactory ;
42
+ _options = options ;
43
+ }
44
+
45
+ public abstract object BaseGetDatabse ( ) ;
46
46
public abstract bool BaseExists ( string cacheKey ) ;
47
47
public abstract Task < bool > BaseExistsAsync ( string cacheKey , CancellationToken cancellationToken = default ) ;
48
48
public abstract void BaseFlush ( ) ;
@@ -64,6 +64,8 @@ protected EasyCachingAbstractProvider(IDistributedLockFactory lockFactory, BaseP
64
64
public abstract Task BaseRemoveAsync ( string cacheKey , CancellationToken cancellationToken = default ) ;
65
65
public abstract void BaseRemoveByPrefix ( string prefix ) ;
66
66
public abstract Task BaseRemoveByPrefixAsync ( string prefix , CancellationToken cancellationToken = default ) ;
67
+ public abstract void BaseRemoveByPattern ( string pattern ) ;
68
+ public abstract Task BaseRemoveByPatternAsync ( string pattern , CancellationToken cancellationToken = default ) ;
67
69
public abstract void BaseSet < T > ( string cacheKey , T cacheValue , TimeSpan expiration ) ;
68
70
public abstract void BaseSetAll < T > ( IDictionary < string , T > values , TimeSpan expiration ) ;
69
71
public abstract Task BaseSetAllAsync < T > ( IDictionary < string , T > values , TimeSpan expiration , CancellationToken cancellationToken = default ) ;
@@ -185,30 +187,30 @@ public CacheValue<T> Get<T>(string cacheKey, Func<T> dataRetriever, TimeSpan exp
185
187
var operationId = s_diagnosticListener . WriteGetCacheBefore ( new BeforeGetRequestEventData ( CachingProviderType . ToString ( ) , Name , nameof ( Get ) , new [ ] { cacheKey } , expiration ) ) ;
186
188
Exception e = null ;
187
189
try
188
- {
190
+ {
189
191
if ( _lockFactory == null ) return BaseGet < T > ( cacheKey , dataRetriever , expiration ) ;
190
192
191
193
var value = BaseGet < T > ( cacheKey ) ;
192
- if ( value . HasValue ) return value ;
193
-
194
- using ( var @lock = _lockFactory . CreateLock ( Name , $ "{ cacheKey } _Lock") )
195
- {
194
+ if ( value . HasValue ) return value ;
195
+
196
+ using ( var @lock = _lockFactory . CreateLock ( Name , $ "{ cacheKey } _Lock") )
197
+ {
196
198
if ( ! @lock . Lock ( _options . SleepMs ) ) throw new TimeoutException ( ) ;
197
199
198
200
value = BaseGet < T > ( cacheKey ) ;
199
- if ( value . HasValue ) return value ;
200
-
201
- var item = dataRetriever ( ) ;
202
- if ( item != null || _options . CacheNulls )
203
- {
204
- BaseSet ( cacheKey , item , expiration ) ;
205
-
206
- return new CacheValue < T > ( item , true ) ;
207
- }
208
- else
209
- {
210
- return CacheValue < T > . NoValue ;
211
- }
201
+ if ( value . HasValue ) return value ;
202
+
203
+ var item = dataRetriever ( ) ;
204
+ if ( item != null || _options . CacheNulls )
205
+ {
206
+ BaseSet ( cacheKey , item , expiration ) ;
207
+
208
+ return new CacheValue < T > ( item , true ) ;
209
+ }
210
+ else
211
+ {
212
+ return CacheValue < T > . NoValue ;
213
+ }
212
214
}
213
215
}
214
216
catch ( Exception ex )
@@ -316,36 +318,36 @@ public async Task<CacheValue<T>> GetAsync<T>(string cacheKey, Func<Task<T>> data
316
318
if ( _lockFactory == null ) return await BaseGetAsync < T > ( cacheKey , dataRetriever , expiration , cancellationToken ) ;
317
319
318
320
var value = await BaseGetAsync < T > ( cacheKey ) ;
319
- if ( value . HasValue ) return value ;
320
-
321
- var @lock = _lockFactory . CreateLock ( Name , $ "{ cacheKey } _Lock") ;
322
- try
323
- {
321
+ if ( value . HasValue ) return value ;
322
+
323
+ var @lock = _lockFactory . CreateLock ( Name , $ "{ cacheKey } _Lock") ;
324
+ try
325
+ {
324
326
if ( ! await @lock . LockAsync ( _options . SleepMs ) ) throw new TimeoutException ( ) ;
325
327
326
328
value = await BaseGetAsync < T > ( cacheKey , cancellationToken ) ;
327
- if ( value . HasValue ) return value ;
328
-
329
- var task = dataRetriever ( ) ;
330
- if ( ! task . IsCompleted &&
331
- await Task . WhenAny ( task , Task . Delay ( _options . LockMs ) ) != task )
332
- throw new TimeoutException ( ) ;
333
-
334
- var item = await task ;
335
- if ( item != null || _options . CacheNulls )
336
- {
337
- await BaseSetAsync ( cacheKey , item , expiration , cancellationToken ) ;
338
-
339
- return new CacheValue < T > ( item , true ) ;
340
- }
341
- else
342
- {
343
- return CacheValue < T > . NoValue ;
344
- }
345
- }
346
- finally
347
- {
348
- await @lock . DisposeAsync ( ) ;
329
+ if ( value . HasValue ) return value ;
330
+
331
+ var task = dataRetriever ( ) ;
332
+ if ( ! task . IsCompleted &&
333
+ await Task . WhenAny ( task , Task . Delay ( _options . LockMs ) ) != task )
334
+ throw new TimeoutException ( ) ;
335
+
336
+ var item = await task ;
337
+ if ( item != null || _options . CacheNulls )
338
+ {
339
+ await BaseSetAsync ( cacheKey , item , expiration , cancellationToken ) ;
340
+
341
+ return new CacheValue < T > ( item , true ) ;
342
+ }
343
+ else
344
+ {
345
+ return CacheValue < T > . NoValue ;
346
+ }
347
+ }
348
+ finally
349
+ {
350
+ await @lock . DisposeAsync ( ) ;
349
351
}
350
352
}
351
353
catch ( Exception ex )
@@ -473,8 +475,8 @@ public async Task<IDictionary<string, CacheValue<T>>> GetByPrefixAsync<T>(string
473
475
public int GetCount ( string prefix = "" )
474
476
{
475
477
return BaseGetCount ( prefix ) ;
476
- }
477
-
478
+ }
479
+
478
480
public async Task < int > GetCountAsync ( string prefix = "" , CancellationToken cancellationToken = default )
479
481
{
480
482
return await BaseGetCountAsync ( prefix , cancellationToken ) ;
@@ -636,6 +638,62 @@ public async Task RemoveByPrefixAsync(string prefix, CancellationToken cancellat
636
638
}
637
639
}
638
640
641
+ public void RemoveByPattern ( string pattern )
642
+ {
643
+ var operationId = s_diagnosticListener . WriteRemoveCacheBefore (
644
+ new BeforeRemoveRequestEventData ( CachingProviderType . ToString ( ) , Name , nameof ( RemoveByPattern ) ,
645
+ new [ ] { pattern } ) ) ;
646
+ Exception e = null ;
647
+ try
648
+ {
649
+ BaseRemoveByPattern ( pattern ) ;
650
+ }
651
+ catch ( Exception ex )
652
+ {
653
+ e = ex ;
654
+ throw ;
655
+ }
656
+ finally
657
+ {
658
+ if ( e != null )
659
+ {
660
+ s_diagnosticListener . WriteRemoveCacheError ( operationId , e ) ;
661
+ }
662
+ else
663
+ {
664
+ s_diagnosticListener . WriteRemoveCacheAfter ( operationId ) ;
665
+ }
666
+ }
667
+ }
668
+
669
+ public async Task RemoveByPatternAsync ( string pattern , CancellationToken cancellationToken = default )
670
+ {
671
+ var operationId = s_diagnosticListener . WriteRemoveCacheBefore (
672
+ new BeforeRemoveRequestEventData ( CachingProviderType . ToString ( ) , Name , nameof ( RemoveByPatternAsync ) ,
673
+ new [ ] { pattern } ) ) ;
674
+ Exception e = null ;
675
+ try
676
+ {
677
+ await BaseRemoveByPatternAsync ( pattern , cancellationToken ) ;
678
+ }
679
+ catch ( Exception ex )
680
+ {
681
+ e = ex ;
682
+ throw ;
683
+ }
684
+ finally
685
+ {
686
+ if ( e != null )
687
+ {
688
+ s_diagnosticListener . WriteRemoveCacheError ( operationId , e ) ;
689
+ }
690
+ else
691
+ {
692
+ s_diagnosticListener . WriteRemoveCacheAfter ( operationId ) ;
693
+ }
694
+ }
695
+ }
696
+
639
697
public void Set < T > ( string cacheKey , T cacheValue , TimeSpan expiration )
640
698
{
641
699
var operationId = s_diagnosticListener . WriteSetCacheBefore ( new BeforeSetRequestEventData ( CachingProviderType . ToString ( ) , Name , nameof ( Set ) , new Dictionary < string , object > { { cacheKey , cacheValue } } , expiration ) ) ;
@@ -804,7 +862,37 @@ public async Task<TimeSpan> GetExpirationAsync(string cacheKey, CancellationToke
804
862
805
863
public ProviderInfo GetProviderInfo ( )
806
864
{
807
- return BaseGetProviderInfo ( ) ;
865
+ return BaseGetProviderInfo ( ) ;
866
+ }
867
+
868
+ protected SearchKeyPattern ProcessSearchKeyPattern ( string pattern )
869
+ {
870
+ var postfix = pattern . StartsWith ( "*" ) ;
871
+ var prefix = pattern . EndsWith ( "*" ) ;
872
+
873
+ var contains = postfix && prefix ;
874
+
875
+ if ( contains )
876
+ {
877
+ return SearchKeyPattern . Contains ;
878
+ }
879
+
880
+ if ( postfix )
881
+ {
882
+ return SearchKeyPattern . Postfix ;
883
+ }
884
+
885
+ if ( prefix )
886
+ {
887
+ return SearchKeyPattern . Prefix ;
888
+ }
889
+
890
+ return SearchKeyPattern . Exact ;
808
891
}
892
+
893
+ protected string HandleSearchKeyPattern ( string pattern )
894
+ {
895
+ return pattern . Replace ( "*" , string . Empty ) ;
896
+ }
809
897
}
810
898
}
0 commit comments