-
Notifications
You must be signed in to change notification settings - Fork 293
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
149 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
133 changes: 133 additions & 0 deletions
133
src/Masuit.MyBlogs.Core/MyEFCacheManagerCoreProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using CacheManager.Core; | ||
using EFCoreSecondLevelCacheInterceptor; | ||
|
||
namespace Masuit.MyBlogs.Core | ||
{ | ||
/// <summary> | ||
/// Using ICacheManager as a cache service. | ||
/// </summary> | ||
public class MyEFCacheManagerCoreProvider : IEFCacheServiceProvider | ||
{ | ||
private readonly IReaderWriterLockProvider _readerWriterLockProvider; | ||
private readonly ICacheManager<ISet<string>> _dependenciesCacheManager; | ||
private readonly ICacheManager<EFCachedData> _valuesCacheManager; | ||
private readonly string _keyPrefix = "EFCache:"; | ||
/// <summary> | ||
/// Using IMemoryCache as a cache service. | ||
/// </summary> | ||
public MyEFCacheManagerCoreProvider(ICacheManager<ISet<string>> dependenciesCacheManager, ICacheManager<EFCachedData> valuesCacheManager, IReaderWriterLockProvider readerWriterLockProvider) | ||
{ | ||
_readerWriterLockProvider = readerWriterLockProvider; | ||
_dependenciesCacheManager = dependenciesCacheManager ?? throw new ArgumentNullException(nameof(dependenciesCacheManager), "Please register the `ICacheManager`."); | ||
_valuesCacheManager = valuesCacheManager ?? throw new ArgumentNullException(nameof(valuesCacheManager), "Please register the `ICacheManager`."); | ||
|
||
// Occurs when an item was removed by the cache handle due to expiration or e.g. memory pressure eviction. | ||
// Without _dependenciesCacheManager items, we can't invalidate cached items on Insert/Update/Delete. | ||
// So to prevent stale reads, we have to clear all cached data in this case. | ||
_dependenciesCacheManager.OnRemoveByHandle += (sender, args) => ClearAllCachedEntries(); | ||
} | ||
|
||
/// <summary> | ||
/// Adds a new item to the cache. | ||
/// </summary> | ||
/// <param name="cacheKey">key</param> | ||
/// <param name="value">value</param> | ||
/// <param name="cachePolicy">Defines the expiration mode of the cache item.</param> | ||
public void InsertValue(EFCacheKey cacheKey, EFCachedData value, EFCachePolicy cachePolicy) | ||
{ | ||
_readerWriterLockProvider.TryWriteLocked(() => | ||
{ | ||
if (value == null) | ||
{ | ||
value = new EFCachedData | ||
{ | ||
IsNull = true | ||
}; | ||
} | ||
|
||
var keyHash = cacheKey.KeyHash; | ||
|
||
foreach (var rootCacheKey in cacheKey.CacheDependencies) | ||
{ | ||
_dependenciesCacheManager.AddOrUpdate(_keyPrefix + rootCacheKey, new HashSet<string>(StringComparer.OrdinalIgnoreCase) | ||
{ | ||
keyHash | ||
}, updateValue: set => | ||
{ | ||
set.Add(keyHash); | ||
return set; | ||
}); | ||
} | ||
|
||
if (cachePolicy == null) | ||
{ | ||
_valuesCacheManager.Add(_keyPrefix + keyHash, value); | ||
} | ||
else | ||
{ | ||
_valuesCacheManager.Add(new CacheItem<EFCachedData>(_keyPrefix + keyHash, value, cachePolicy.CacheExpirationMode == CacheExpirationMode.Absolute ? ExpirationMode.Absolute : ExpirationMode.Sliding, cachePolicy.CacheTimeout)); | ||
} | ||
}); | ||
} | ||
|
||
/// <summary> | ||
/// Removes the cached entries added by this library. | ||
/// </summary> | ||
public void ClearAllCachedEntries() | ||
{ | ||
_readerWriterLockProvider.TryWriteLocked(() => | ||
{ | ||
_valuesCacheManager.Clear(); | ||
_dependenciesCacheManager.Clear(); | ||
}); | ||
} | ||
|
||
/// <summary> | ||
/// Gets a cached entry by key. | ||
/// </summary> | ||
/// <param name="cacheKey">key to find</param> | ||
/// <returns>cached value</returns> | ||
/// <param name="cachePolicy">Defines the expiration mode of the cache item.</param> | ||
public EFCachedData GetValue(EFCacheKey cacheKey, EFCachePolicy cachePolicy) | ||
{ | ||
return _readerWriterLockProvider.TryReadLocked(() => _valuesCacheManager.Get<EFCachedData>(_keyPrefix + cacheKey.KeyHash)); | ||
} | ||
|
||
/// <summary> | ||
/// Invalidates all of the cache entries which are dependent on any of the specified root keys. | ||
/// </summary> | ||
/// <param name="cacheKey">Stores information of the computed key of the input LINQ query.</param> | ||
public void InvalidateCacheDependencies(EFCacheKey cacheKey) | ||
{ | ||
_readerWriterLockProvider.TryWriteLocked(() => | ||
{ | ||
foreach (var rootCacheKey in cacheKey.CacheDependencies) | ||
{ | ||
if (string.IsNullOrWhiteSpace(rootCacheKey)) | ||
{ | ||
continue; | ||
} | ||
|
||
clearDependencyValues(rootCacheKey); | ||
_dependenciesCacheManager.Remove(_keyPrefix + rootCacheKey); | ||
} | ||
}); | ||
} | ||
|
||
private void clearDependencyValues(string rootCacheKey) | ||
{ | ||
var dependencyKeys = _dependenciesCacheManager.Get(_keyPrefix + rootCacheKey); | ||
if (dependencyKeys == null) | ||
{ | ||
return; | ||
} | ||
|
||
foreach (var dependencyKey in dependencyKeys) | ||
{ | ||
_valuesCacheManager.Remove(_keyPrefix + dependencyKey); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters