|
|
|
@ -1,6 +1,9 @@ |
|
|
|
using System; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.Linq; |
|
|
|
using System.Threading; |
|
|
|
using System.Threading.Tasks; |
|
|
|
using JetBrains.Annotations; |
|
|
|
using Microsoft.Extensions.Caching.Distributed; |
|
|
|
using Microsoft.Extensions.DependencyInjection; |
|
|
|
using Microsoft.Extensions.Logging; |
|
|
|
@ -28,16 +31,16 @@ namespace Volo.Abp.Caching |
|
|
|
IDistributedCacheSerializer serializer, |
|
|
|
IDistributedCacheKeyNormalizer keyNormalizer, |
|
|
|
IHybridServiceScopeFactory serviceScopeFactory) : base( |
|
|
|
distributedCacheOption: distributedCacheOption, |
|
|
|
cache: cache, |
|
|
|
cancellationTokenProvider: cancellationTokenProvider, |
|
|
|
serializer: serializer, |
|
|
|
keyNormalizer: keyNormalizer, |
|
|
|
serviceScopeFactory: serviceScopeFactory) |
|
|
|
distributedCacheOption: distributedCacheOption, |
|
|
|
cache: cache, |
|
|
|
cancellationTokenProvider: cancellationTokenProvider, |
|
|
|
serializer: serializer, |
|
|
|
keyNormalizer: keyNormalizer, |
|
|
|
serviceScopeFactory: serviceScopeFactory) |
|
|
|
{ |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Represents a distributed cache of <typeparamref name="TCacheItem" /> type.
|
|
|
|
/// Uses a generic cache key type of <typeparamref name="TCacheKey" /> type.
|
|
|
|
@ -148,19 +151,151 @@ namespace Volo.Abp.Caching |
|
|
|
{ |
|
|
|
if (hideErrors == true) |
|
|
|
{ |
|
|
|
AsyncHelper.RunSync(() => HandleExceptionAsync(ex)); |
|
|
|
HandleException(ex); |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
throw; |
|
|
|
} |
|
|
|
|
|
|
|
if (cachedBytes == null) |
|
|
|
return ToCacheItem(cachedBytes); |
|
|
|
} |
|
|
|
|
|
|
|
public virtual KeyValuePair<TCacheKey, TCacheItem>[] GetMany( |
|
|
|
IEnumerable<TCacheKey> keys, |
|
|
|
bool? hideErrors = null) |
|
|
|
{ |
|
|
|
var keyArray = keys.ToArray(); |
|
|
|
|
|
|
|
var cacheSupportsMultipleItems = Cache as ICacheSupportsMultipleItems; |
|
|
|
if (cacheSupportsMultipleItems == null) |
|
|
|
{ |
|
|
|
return null; |
|
|
|
return GetManyFallback( |
|
|
|
keyArray, |
|
|
|
hideErrors |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
return Serializer.Deserialize<TCacheItem>(cachedBytes); |
|
|
|
hideErrors = hideErrors ?? _distributedCacheOption.HideErrors; |
|
|
|
byte[][] cachedBytes; |
|
|
|
|
|
|
|
try |
|
|
|
{ |
|
|
|
cachedBytes = cacheSupportsMultipleItems.GetMany(keyArray.Select(NormalizeKey)); |
|
|
|
} |
|
|
|
catch (Exception ex) |
|
|
|
{ |
|
|
|
if (hideErrors == true) |
|
|
|
{ |
|
|
|
HandleException(ex); |
|
|
|
return ToCacheItemsWithDefaultValues(keyArray); |
|
|
|
} |
|
|
|
|
|
|
|
throw; |
|
|
|
} |
|
|
|
|
|
|
|
return ToCacheItems(cachedBytes, keyArray); |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual KeyValuePair<TCacheKey, TCacheItem>[] GetManyFallback( |
|
|
|
TCacheKey[] keys, |
|
|
|
bool? hideErrors = null) |
|
|
|
{ |
|
|
|
hideErrors = hideErrors ?? _distributedCacheOption.HideErrors; |
|
|
|
|
|
|
|
try |
|
|
|
{ |
|
|
|
return keys |
|
|
|
.Select(key => new KeyValuePair<TCacheKey, TCacheItem>( |
|
|
|
key, |
|
|
|
Get(key, hideErrors: false) |
|
|
|
) |
|
|
|
).ToArray(); |
|
|
|
} |
|
|
|
catch (Exception ex) |
|
|
|
{ |
|
|
|
if (hideErrors == true) |
|
|
|
{ |
|
|
|
HandleException(ex); |
|
|
|
return ToCacheItemsWithDefaultValues(keys); |
|
|
|
} |
|
|
|
|
|
|
|
throw; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public virtual async Task<KeyValuePair<TCacheKey, TCacheItem>[]> GetManyAsync( |
|
|
|
IEnumerable<TCacheKey> keys, |
|
|
|
bool? hideErrors = null, |
|
|
|
CancellationToken token = default) |
|
|
|
{ |
|
|
|
var keyArray = keys.ToArray(); |
|
|
|
|
|
|
|
var cacheSupportsMultipleItems = Cache as ICacheSupportsMultipleItems; |
|
|
|
if (cacheSupportsMultipleItems == null) |
|
|
|
{ |
|
|
|
return await GetManyFallbackAsync( |
|
|
|
keyArray, |
|
|
|
hideErrors, |
|
|
|
token |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
hideErrors = hideErrors ?? _distributedCacheOption.HideErrors; |
|
|
|
byte[][] cachedBytes; |
|
|
|
|
|
|
|
try |
|
|
|
{ |
|
|
|
cachedBytes = await cacheSupportsMultipleItems.GetManyAsync( |
|
|
|
keyArray.Select(NormalizeKey), |
|
|
|
CancellationTokenProvider.FallbackToProvider(token) |
|
|
|
); |
|
|
|
} |
|
|
|
catch (Exception ex) |
|
|
|
{ |
|
|
|
if (hideErrors == true) |
|
|
|
{ |
|
|
|
await HandleExceptionAsync(ex); |
|
|
|
return ToCacheItemsWithDefaultValues(keyArray); |
|
|
|
} |
|
|
|
|
|
|
|
throw; |
|
|
|
} |
|
|
|
|
|
|
|
return ToCacheItems(cachedBytes, keyArray); |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual async Task<KeyValuePair<TCacheKey, TCacheItem>[]> GetManyFallbackAsync( |
|
|
|
TCacheKey[] keys, |
|
|
|
bool? hideErrors = null, |
|
|
|
CancellationToken token = default) |
|
|
|
{ |
|
|
|
hideErrors = hideErrors ?? _distributedCacheOption.HideErrors; |
|
|
|
|
|
|
|
try |
|
|
|
{ |
|
|
|
var result = new List<KeyValuePair<TCacheKey, TCacheItem>>(); |
|
|
|
|
|
|
|
foreach (var key in keys) |
|
|
|
{ |
|
|
|
result.Add(new KeyValuePair<TCacheKey, TCacheItem>( |
|
|
|
key, |
|
|
|
await GetAsync(key, false, token)) |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
return result.ToArray(); |
|
|
|
} |
|
|
|
catch (Exception ex) |
|
|
|
{ |
|
|
|
if (hideErrors == true) |
|
|
|
{ |
|
|
|
await HandleExceptionAsync(ex); |
|
|
|
return ToCacheItemsWithDefaultValues(keys); |
|
|
|
} |
|
|
|
|
|
|
|
throw; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
@ -307,7 +442,7 @@ namespace Volo.Abp.Caching |
|
|
|
{ |
|
|
|
if (hideErrors == true) |
|
|
|
{ |
|
|
|
AsyncHelper.RunSync(() => HandleExceptionAsync(ex)); |
|
|
|
HandleException(ex); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
@ -354,14 +489,156 @@ namespace Volo.Abp.Caching |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Refreshes the cache value of the given key, and resets its sliding expiration timeout.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="key">The key of cached item to be retrieved from the cache.</param>
|
|
|
|
/// <param name="hideErrors">Indicates to throw or hide the exceptions for the distributed cache.</param>
|
|
|
|
public void SetMany( |
|
|
|
IEnumerable<KeyValuePair<TCacheKey, TCacheItem>> items, |
|
|
|
DistributedCacheEntryOptions options = null, |
|
|
|
bool? hideErrors = null) |
|
|
|
{ |
|
|
|
var itemsArray = items.ToArray(); |
|
|
|
|
|
|
|
var cacheSupportsMultipleItems = Cache as ICacheSupportsMultipleItems; |
|
|
|
if (cacheSupportsMultipleItems == null) |
|
|
|
{ |
|
|
|
SetManyFallback( |
|
|
|
itemsArray, |
|
|
|
options, |
|
|
|
hideErrors |
|
|
|
); |
|
|
|
|
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
hideErrors = hideErrors ?? _distributedCacheOption.HideErrors; |
|
|
|
|
|
|
|
try |
|
|
|
{ |
|
|
|
cacheSupportsMultipleItems.SetMany( |
|
|
|
ToRawCacheItems(itemsArray), |
|
|
|
options ?? DefaultCacheOptions |
|
|
|
); |
|
|
|
} |
|
|
|
catch (Exception ex) |
|
|
|
{ |
|
|
|
if (hideErrors == true) |
|
|
|
{ |
|
|
|
HandleException(ex); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
throw; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual void SetManyFallback( |
|
|
|
KeyValuePair<TCacheKey, TCacheItem>[] items, |
|
|
|
DistributedCacheEntryOptions options = null, |
|
|
|
bool? hideErrors = null) |
|
|
|
{ |
|
|
|
hideErrors = hideErrors ?? _distributedCacheOption.HideErrors; |
|
|
|
|
|
|
|
try |
|
|
|
{ |
|
|
|
foreach (var item in items) |
|
|
|
{ |
|
|
|
Set( |
|
|
|
item.Key, |
|
|
|
item.Value, |
|
|
|
options: options, |
|
|
|
hideErrors: false |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
catch (Exception ex) |
|
|
|
{ |
|
|
|
if (hideErrors == true) |
|
|
|
{ |
|
|
|
HandleException(ex); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
throw; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public virtual async Task SetManyAsync( |
|
|
|
IEnumerable<KeyValuePair<TCacheKey, TCacheItem>> items, |
|
|
|
DistributedCacheEntryOptions options = null, |
|
|
|
bool? hideErrors = null, |
|
|
|
CancellationToken token = default) |
|
|
|
{ |
|
|
|
var itemsArray = items.ToArray(); |
|
|
|
|
|
|
|
var cacheSupportsMultipleItems = Cache as ICacheSupportsMultipleItems; |
|
|
|
if (cacheSupportsMultipleItems == null) |
|
|
|
{ |
|
|
|
await SetManyFallbackAsync( |
|
|
|
itemsArray, |
|
|
|
options, |
|
|
|
hideErrors, |
|
|
|
token |
|
|
|
); |
|
|
|
|
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
hideErrors = hideErrors ?? _distributedCacheOption.HideErrors; |
|
|
|
|
|
|
|
try |
|
|
|
{ |
|
|
|
await cacheSupportsMultipleItems.SetManyAsync( |
|
|
|
ToRawCacheItems(itemsArray), |
|
|
|
options ?? DefaultCacheOptions, |
|
|
|
CancellationTokenProvider.FallbackToProvider(token) |
|
|
|
); |
|
|
|
} |
|
|
|
catch (Exception ex) |
|
|
|
{ |
|
|
|
if (hideErrors == true) |
|
|
|
{ |
|
|
|
await HandleExceptionAsync(ex); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
throw; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual async Task SetManyFallbackAsync( |
|
|
|
KeyValuePair<TCacheKey, TCacheItem>[] items, |
|
|
|
DistributedCacheEntryOptions options = null, |
|
|
|
bool? hideErrors = null, |
|
|
|
CancellationToken token = default) |
|
|
|
{ |
|
|
|
hideErrors = hideErrors ?? _distributedCacheOption.HideErrors; |
|
|
|
|
|
|
|
try |
|
|
|
{ |
|
|
|
foreach (var item in items) |
|
|
|
{ |
|
|
|
await SetAsync( |
|
|
|
item.Key, |
|
|
|
item.Value, |
|
|
|
options: options, |
|
|
|
hideErrors: false, |
|
|
|
token: token |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
catch (Exception ex) |
|
|
|
{ |
|
|
|
if (hideErrors == true) |
|
|
|
{ |
|
|
|
await HandleExceptionAsync(ex); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
throw; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public virtual void Refresh( |
|
|
|
TCacheKey key, bool? |
|
|
|
hideErrors = null) |
|
|
|
hideErrors = null) |
|
|
|
{ |
|
|
|
hideErrors = hideErrors ?? _distributedCacheOption.HideErrors; |
|
|
|
|
|
|
|
@ -373,20 +650,14 @@ namespace Volo.Abp.Caching |
|
|
|
{ |
|
|
|
if (hideErrors == true) |
|
|
|
{ |
|
|
|
AsyncHelper.RunSync(() => HandleExceptionAsync(ex)); |
|
|
|
HandleException(ex); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
throw; |
|
|
|
} |
|
|
|
} |
|
|
|
/// <summary>
|
|
|
|
/// Refreshes the cache value of the given key, and resets its sliding expiration timeout.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="key">The key of cached item to be retrieved from the cache.</param>
|
|
|
|
/// <param name="hideErrors">Indicates to throw or hide the exceptions for the distributed cache.</param>
|
|
|
|
/// <param name="token">The <see cref="T:System.Threading.CancellationToken" /> for the task.</param>
|
|
|
|
/// <returns>The <see cref="T:System.Threading.Tasks.Task" /> indicating that the operation is asynchronous.</returns>
|
|
|
|
|
|
|
|
public virtual async Task RefreshAsync( |
|
|
|
TCacheKey key, |
|
|
|
bool? hideErrors = null, |
|
|
|
@ -410,11 +681,6 @@ namespace Volo.Abp.Caching |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Removes the cache item for given key from cache.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="key">The key of cached item to be retrieved from the cache.</param>
|
|
|
|
/// <param name="hideErrors">Indicates to throw or hide the exceptions for the distributed cache.</param>
|
|
|
|
public virtual void Remove( |
|
|
|
TCacheKey key, |
|
|
|
bool? hideErrors = null) |
|
|
|
@ -429,7 +695,7 @@ namespace Volo.Abp.Caching |
|
|
|
{ |
|
|
|
if (hideErrors == true) |
|
|
|
{ |
|
|
|
AsyncHelper.RunSync(() => HandleExceptionAsync(ex)); |
|
|
|
HandleException(ex); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
@ -437,13 +703,6 @@ namespace Volo.Abp.Caching |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Removes the cache item for given key from cache.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="key">The key of cached item to be retrieved from the cache.</param>
|
|
|
|
/// <param name="hideErrors">Indicates to throw or hide the exceptions for the distributed cache.</param>
|
|
|
|
/// <param name="token">The <see cref="T:System.Threading.CancellationToken" /> for the task.</param>
|
|
|
|
/// <returns>The <see cref="T:System.Threading.Tasks.Task" /> indicating that the operation is asynchronous.</returns>
|
|
|
|
public virtual async Task RemoveAsync( |
|
|
|
TCacheKey key, |
|
|
|
bool? hideErrors = null, |
|
|
|
@ -467,6 +726,11 @@ namespace Volo.Abp.Caching |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual void HandleException(Exception ex) |
|
|
|
{ |
|
|
|
AsyncHelper.RunSync(() => HandleExceptionAsync(ex)); |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual async Task HandleExceptionAsync(Exception ex) |
|
|
|
{ |
|
|
|
Logger.LogException(ex, LogLevel.Warning); |
|
|
|
@ -478,5 +742,56 @@ namespace Volo.Abp.Caching |
|
|
|
.NotifyAsync(new ExceptionNotificationContext(ex, LogLevel.Warning)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual KeyValuePair<TCacheKey, TCacheItem>[] ToCacheItems(byte[][] itemBytes, TCacheKey[] itemKeys) |
|
|
|
{ |
|
|
|
if (itemBytes.Length != itemKeys.Length) |
|
|
|
{ |
|
|
|
throw new AbpException("count of the item bytes should be same with the count of the given keys"); |
|
|
|
} |
|
|
|
|
|
|
|
var result = new List<KeyValuePair<TCacheKey, TCacheItem>>(); |
|
|
|
|
|
|
|
for (int i = 0; i < itemKeys.Length; i++) |
|
|
|
{ |
|
|
|
result.Add( |
|
|
|
new KeyValuePair<TCacheKey, TCacheItem>( |
|
|
|
itemKeys[i], |
|
|
|
ToCacheItem(itemBytes[i]) |
|
|
|
) |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
return result.ToArray(); |
|
|
|
} |
|
|
|
|
|
|
|
[CanBeNull] |
|
|
|
protected virtual TCacheItem ToCacheItem([CanBeNull] byte[] bytes) |
|
|
|
{ |
|
|
|
if (bytes == null) |
|
|
|
{ |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
return Serializer.Deserialize<TCacheItem>(bytes); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected virtual KeyValuePair<string, byte[]>[] ToRawCacheItems(KeyValuePair<TCacheKey, TCacheItem>[] items) |
|
|
|
{ |
|
|
|
return items |
|
|
|
.Select(i => new KeyValuePair<string, byte[]>( |
|
|
|
NormalizeKey(i.Key), |
|
|
|
Serializer.Serialize(i.Value) |
|
|
|
) |
|
|
|
).ToArray(); |
|
|
|
} |
|
|
|
|
|
|
|
private static KeyValuePair<TCacheKey, TCacheItem>[] ToCacheItemsWithDefaultValues(TCacheKey[] keys) |
|
|
|
{ |
|
|
|
return keys |
|
|
|
.Select(key => new KeyValuePair<TCacheKey, TCacheItem>(key, default)) |
|
|
|
.ToArray(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |