44 changed files with 1073 additions and 1 deletions
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,24 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<None Remove="LINGYUN\Abp\CachingManagement\Localization\Resources\*.json" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<EmbeddedResource Include="LINGYUN\Abp\CachingManagement\Localization\Resources\*.json" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Volo.Abp.Authorization" Version="$(VoloAbpPackageVersion)" /> |
||||
|
<PackageReference Include="Volo.Abp.Ddd.Application.Contracts" Version="$(VoloAbpPackageVersion)" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,29 @@ |
|||||
|
using LINGYUN.Abp.CachingManagement.Localization; |
||||
|
using Volo.Abp.Application; |
||||
|
using Volo.Abp.Authorization; |
||||
|
using Volo.Abp.Localization; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.VirtualFileSystem; |
||||
|
|
||||
|
namespace LINGYUN.Abp.CachingManagement; |
||||
|
|
||||
|
[DependsOn( |
||||
|
typeof(AbpAuthorizationModule), |
||||
|
typeof(AbpDddApplicationContractsModule))] |
||||
|
public class AbpCachingManagementApplicationContractsModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
Configure<AbpVirtualFileSystemOptions>(options => |
||||
|
{ |
||||
|
options.FileSets.AddEmbedded<AbpCachingManagementApplicationContractsModule>(); |
||||
|
}); |
||||
|
|
||||
|
Configure<AbpLocalizationOptions>(options => |
||||
|
{ |
||||
|
options.Resources |
||||
|
.Add<CacheResource>() |
||||
|
.AddVirtualJson("/LINGYUN/Abp/CachingManagement/Localization/Resources"); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
namespace LINGYUN.Abp.CachingManagement; |
||||
|
|
||||
|
public class AbpCachingManagementRemoteServiceConsts |
||||
|
{ |
||||
|
public const string RemoteServiceName = "CachingManagement"; |
||||
|
|
||||
|
public const string ModuleName = "caching-management"; |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
|
||||
|
namespace LINGYUN.Abp.CachingManagement; |
||||
|
|
||||
|
public class CacheKeyInput |
||||
|
{ |
||||
|
[Required] |
||||
|
public string Key { get; set; } |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace LINGYUN.Abp.CachingManagement; |
||||
|
|
||||
|
public class CacheKeysDto |
||||
|
{ |
||||
|
public string NextMarker { get; set; } |
||||
|
|
||||
|
public List<string> Keys { get; set; } = new List<string>(); |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace LINGYUN.Abp.CachingManagement; |
||||
|
|
||||
|
public class CacheRefreshInput |
||||
|
{ |
||||
|
public string Key { get; set; } |
||||
|
public DateTime? AbsoluteExpiration { get; set; } |
||||
|
public DateTime? SlidingExpiration { get; set; } |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace LINGYUN.Abp.CachingManagement; |
||||
|
|
||||
|
public class CacheValueDto |
||||
|
{ |
||||
|
public string Type { get; set; } |
||||
|
public long Size { get; set; } |
||||
|
public DateTime? Expiration { get; set; } |
||||
|
public IDictionary<string, object> Values { get; set; } = new Dictionary<string, object>(); |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
namespace LINGYUN.Abp.CachingManagement; |
||||
|
|
||||
|
public class GetCacheKeysInput |
||||
|
{ |
||||
|
public string Prefix { get; set; } |
||||
|
public string Marker { get; set; } |
||||
|
public string Filter { get; set; } |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Application.Services; |
||||
|
|
||||
|
namespace LINGYUN.Abp.CachingManagement; |
||||
|
|
||||
|
public interface ICacheAppService : IApplicationService |
||||
|
{ |
||||
|
Task<CacheKeysDto> GetKeysAsync(GetCacheKeysInput input); |
||||
|
|
||||
|
Task<CacheValueDto> GetValueAsync(CacheKeyInput input); |
||||
|
|
||||
|
Task RefreshAsync(CacheRefreshInput input); |
||||
|
|
||||
|
Task RemoveAsync(CacheKeyInput input); |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
using Volo.Abp.Localization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.CachingManagement.Localization; |
||||
|
|
||||
|
[LocalizationResourceName("CachingManagement")] |
||||
|
public class CacheResource |
||||
|
{ |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
{ |
||||
|
"culture": "en", |
||||
|
"texts": { |
||||
|
"Permission:CachingManagement": "Caching Management", |
||||
|
"Permission:Caches": "Manager Cache", |
||||
|
"Permission:Refresh": "Refresh", |
||||
|
"Permission:Delete": "Delete", |
||||
|
"Caches": "Caches", |
||||
|
"DisplayName:Marker": "Marker", |
||||
|
"DisplayName:NextMarker": "Next Marker", |
||||
|
"DisplayName:Type": "Type", |
||||
|
"DisplayName:Size": "Size", |
||||
|
"DisplayName:Ttl": "Ttl", |
||||
|
"DisplayName:Values": "Values", |
||||
|
"DisplayName:Key": "Key", |
||||
|
"DisplayName:Keys": "Keys", |
||||
|
"DisplayName:AbsoluteExpiration": "Absolute Expiration", |
||||
|
"DisplayName:SlidingExpiration": "Sliding Expiration", |
||||
|
"Abp.CachingManagement:01001": "A cache of Type {Type} does not support viewing key values." |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
{ |
||||
|
"culture": "zh-Hans", |
||||
|
"texts": { |
||||
|
"Permission:CachingManagement": "缓存管理", |
||||
|
"Permission:Caches": "管理缓存", |
||||
|
"Permission:Refresh": "刷新", |
||||
|
"Permission:Delete": "删除", |
||||
|
"Caches": "缓存列表", |
||||
|
"DisplayName:Marker": "标记", |
||||
|
"DisplayName:NextMarker": "下一个标记", |
||||
|
"DisplayName:Type": "类型", |
||||
|
"DisplayName:Size": "大小", |
||||
|
"DisplayName:Ttl": "存活时间", |
||||
|
"DisplayName:Values": "缓存值", |
||||
|
"DisplayName:Key": "缓存键", |
||||
|
"DisplayName:Keys": "键列表", |
||||
|
"DisplayName:AbsoluteExpiration": "绝对过期时间", |
||||
|
"DisplayName:SlidingExpiration": "滑动过期时间", |
||||
|
"Abp.CachingManagement:01001": "类型为 {Type} 的缓存暂不支持查看键值." |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,22 @@ |
|||||
|
using LINGYUN.Abp.CachingManagement.Localization; |
||||
|
using Volo.Abp.Authorization.Permissions; |
||||
|
using Volo.Abp.Localization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.CachingManagement.Permissions; |
||||
|
|
||||
|
public class CachingManagemenPermissionDefinitionProvider : PermissionDefinitionProvider |
||||
|
{ |
||||
|
public override void Define(IPermissionDefinitionContext context) |
||||
|
{ |
||||
|
var cachingManagerGroup = context.AddGroup(CachingManagementPermissionNames.GroupName, L("Permission:CachingManagement")); |
||||
|
|
||||
|
var cacheGroup = cachingManagerGroup.AddPermission(CachingManagementPermissionNames.Cache.Default, L("Permission:Caches")); |
||||
|
cacheGroup.AddChild(CachingManagementPermissionNames.Cache.Refresh, L("Permission:Refresh")); |
||||
|
cacheGroup.AddChild(CachingManagementPermissionNames.Cache.Delete, L("Permission:Delete")); |
||||
|
} |
||||
|
|
||||
|
private static LocalizableString L(string name) |
||||
|
{ |
||||
|
return LocalizableString.Create<CacheResource>(name); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
using Volo.Abp.Reflection; |
||||
|
|
||||
|
namespace LINGYUN.Abp.CachingManagement.Permissions; |
||||
|
|
||||
|
public static class CachingManagementPermissionNames |
||||
|
{ |
||||
|
public const string GroupName = "AbpCachingManagement"; |
||||
|
|
||||
|
public static class Cache |
||||
|
{ |
||||
|
public const string Default = GroupName + ".Cache"; |
||||
|
public const string Refresh = Default + ".Refresh"; |
||||
|
public const string Delete = Default + ".Delete"; |
||||
|
} |
||||
|
|
||||
|
public static string[] GetAll() |
||||
|
{ |
||||
|
return ReflectionHelper.GetPublicConstantsRecursively(typeof(CachingManagementPermissionNames)); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,20 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Volo.Abp.Ddd.Application" Version="$(VoloAbpPackageVersion)" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.CachingManagement.Application.Contracts\LINGYUN.Abp.CachingManagement.Application.Contracts.csproj" /> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.CachingManagement.Domain\LINGYUN.Abp.CachingManagement.Domain.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,12 @@ |
|||||
|
using Volo.Abp.Application; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace LINGYUN.Abp.CachingManagement; |
||||
|
|
||||
|
[DependsOn( |
||||
|
typeof(AbpCachingManagementApplicationContractsModule), |
||||
|
typeof(AbpDddApplicationModule))] |
||||
|
public class AbpCachingManagementApplicationModule : AbpModule |
||||
|
{ |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,78 @@ |
|||||
|
using LINGYUN.Abp.CachingManagement.Localization; |
||||
|
using LINGYUN.Abp.CachingManagement.Permissions; |
||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using System; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Application.Services; |
||||
|
|
||||
|
namespace LINGYUN.Abp.CachingManagement; |
||||
|
|
||||
|
[Authorize(CachingManagementPermissionNames.Cache.Default)] |
||||
|
public class CacheAppService : ApplicationService, ICacheAppService |
||||
|
{ |
||||
|
protected ICacheManager CacheManager { get; } |
||||
|
|
||||
|
public CacheAppService(ICacheManager cacheManager) |
||||
|
{ |
||||
|
CacheManager = cacheManager; |
||||
|
|
||||
|
LocalizationResource = typeof(CacheResource); |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<CacheKeysDto> GetKeysAsync(GetCacheKeysInput input) |
||||
|
{ |
||||
|
var res = await CacheManager.GetKeysAsync( |
||||
|
input.Prefix, |
||||
|
input.Filter, |
||||
|
input.Marker); |
||||
|
|
||||
|
return new CacheKeysDto |
||||
|
{ |
||||
|
NextMarker = res.NextMarker, |
||||
|
Keys = res.Keys.ToList(), |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<CacheValueDto> GetValueAsync(CacheKeyInput input) |
||||
|
{ |
||||
|
var res = await CacheManager.GetValueAsync(input.Key); |
||||
|
|
||||
|
var value = new CacheValueDto |
||||
|
{ |
||||
|
Size = res.Size, |
||||
|
Type = res.Type, |
||||
|
Values = res.Values, |
||||
|
}; |
||||
|
if (res.Ttl.HasValue) |
||||
|
{ |
||||
|
value.Expiration = Clock.Now.Add(res.Ttl.Value); |
||||
|
} |
||||
|
|
||||
|
return value; |
||||
|
} |
||||
|
|
||||
|
[Authorize(CachingManagementPermissionNames.Cache.Refresh)] |
||||
|
public async virtual Task RefreshAsync(CacheRefreshInput input) |
||||
|
{ |
||||
|
TimeSpan? absExpir = null; |
||||
|
TimeSpan? sldExpr = null; |
||||
|
|
||||
|
if (input.AbsoluteExpiration.HasValue && input.AbsoluteExpiration.Value > Clock.Now) |
||||
|
{ |
||||
|
absExpir = input.AbsoluteExpiration.Value - Clock.Now; |
||||
|
} |
||||
|
if (input.SlidingExpiration.HasValue && input.SlidingExpiration.Value > Clock.Now) |
||||
|
{ |
||||
|
sldExpr = input.SlidingExpiration.Value - Clock.Now; |
||||
|
} |
||||
|
|
||||
|
await CacheManager.RefreshAsync(input.Key, absExpir, sldExpr); |
||||
|
} |
||||
|
|
||||
|
[Authorize(CachingManagementPermissionNames.Cache.Delete)] |
||||
|
public async virtual Task RemoveAsync(CacheKeyInput input) |
||||
|
{ |
||||
|
await CacheManager.RemoveAsync(input.Key); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,15 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Volo.Abp.Caching" Version="$(VoloAbpPackageVersion)" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,17 @@ |
|||||
|
using Volo.Abp.Caching; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace LINGYUN.Abp.CachingManagement; |
||||
|
|
||||
|
[DependsOn( |
||||
|
typeof(AbpCachingModule))] |
||||
|
public class AbpCachingManagementDomainModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
Configure<AbpDistributedCacheOptions>(options => |
||||
|
{ |
||||
|
|
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace LINGYUN.Abp.CachingManagement; |
||||
|
|
||||
|
public class CacheValueResponse |
||||
|
{ |
||||
|
public string Type { get; } |
||||
|
public long Size { get; } |
||||
|
public TimeSpan? Ttl { get; } |
||||
|
public IDictionary<string, object> Values { get; } |
||||
|
public CacheValueResponse( |
||||
|
string type, |
||||
|
long size, |
||||
|
IDictionary<string, object> values, |
||||
|
TimeSpan? ttl = null) |
||||
|
{ |
||||
|
Type = type; |
||||
|
Size = size; |
||||
|
Ttl = ttl; |
||||
|
Values = values; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,18 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace LINGYUN.Abp.CachingManagement; |
||||
|
|
||||
|
public class CackeKeysResponse |
||||
|
{ |
||||
|
public string NextMarker { get; } |
||||
|
|
||||
|
public IEnumerable<string> Keys { get; } |
||||
|
|
||||
|
public CackeKeysResponse( |
||||
|
string nextMarker, |
||||
|
IEnumerable<string> keys) |
||||
|
{ |
||||
|
NextMarker = nextMarker; |
||||
|
Keys = keys; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,18 @@ |
|||||
|
namespace LINGYUN.Abp.CachingManagement; |
||||
|
|
||||
|
public class GetCacheKeysRequest |
||||
|
{ |
||||
|
public string Prefix { get; } |
||||
|
public string Filter { get; } |
||||
|
public string Marker { get; } |
||||
|
|
||||
|
public GetCacheKeysRequest( |
||||
|
string prefix = null, |
||||
|
string filter = null, |
||||
|
string marker = null) |
||||
|
{ |
||||
|
Prefix = prefix; |
||||
|
Filter = filter; |
||||
|
Marker = marker; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.CachingManagement; |
||||
|
|
||||
|
public interface ICacheManager |
||||
|
{ |
||||
|
Task<CackeKeysResponse> GetKeysAsync(GetCacheKeysRequest request, CancellationToken cancellationToken = default); |
||||
|
|
||||
|
Task<CacheValueResponse> GetValueAsync(string key, CancellationToken cancellationToken = default); |
||||
|
|
||||
|
Task RefreshAsync(RefreshCacheRequest request, CancellationToken cancellationToken = default); |
||||
|
|
||||
|
Task RemoveAsync(string key, CancellationToken cancellationToken = default); |
||||
|
} |
||||
@ -0,0 +1,32 @@ |
|||||
|
using System; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.CachingManagement; |
||||
|
|
||||
|
public static class ICacheManagerExtensions |
||||
|
{ |
||||
|
public static Task<CackeKeysResponse> GetKeysAsync( |
||||
|
this ICacheManager cacheManager, |
||||
|
string prefix = null, |
||||
|
string filter = null, |
||||
|
string marker = null, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
return cacheManager.GetKeysAsync( |
||||
|
new GetCacheKeysRequest(prefix, filter, marker), |
||||
|
cancellationToken); |
||||
|
} |
||||
|
|
||||
|
public static Task RefreshAsync( |
||||
|
this ICacheManager cacheManager, |
||||
|
string key, |
||||
|
TimeSpan? absExpr = null, |
||||
|
TimeSpan? sldExpr = null, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
return cacheManager.RefreshAsync( |
||||
|
new RefreshCacheRequest(key, absExpr, sldExpr), |
||||
|
cancellationToken); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
using System; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
|
||||
|
namespace LINGYUN.Abp.CachingManagement; |
||||
|
|
||||
|
public class RefreshCacheRequest |
||||
|
{ |
||||
|
[Required] |
||||
|
public string Key { get; } |
||||
|
public TimeSpan? AbsoluteExpiration { get; } |
||||
|
public TimeSpan? SlidingExpiration { get; } |
||||
|
public RefreshCacheRequest( |
||||
|
string key, |
||||
|
TimeSpan? absoluteExpiration = null, |
||||
|
TimeSpan? slidingExpiration = null) |
||||
|
{ |
||||
|
Key = key; |
||||
|
AbsoluteExpiration = absoluteExpiration; |
||||
|
SlidingExpiration = slidingExpiration; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,19 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net6.0</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Volo.Abp.AspNetCore.Mvc" Version="$(VoloAbpPackageVersion)" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.CachingManagement.Application.Contracts\LINGYUN.Abp.CachingManagement.Application.Contracts.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,40 @@ |
|||||
|
using LINGYUN.Abp.CachingManagement.Localization; |
||||
|
using Localization.Resources.AbpUi; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
using Volo.Abp.AspNetCore.Mvc.Localization; |
||||
|
using Volo.Abp.Localization; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace LINGYUN.Abp.CachingManagement; |
||||
|
|
||||
|
[DependsOn( |
||||
|
typeof(AbpCachingManagementApplicationContractsModule), |
||||
|
typeof(AbpAspNetCoreMvcModule))] |
||||
|
public class AbpCachingManagementHttpApiModule : AbpModule |
||||
|
{ |
||||
|
public override void PreConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
PreConfigure<IMvcBuilder>(mvcBuilder => |
||||
|
{ |
||||
|
mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpCachingManagementHttpApiModule).Assembly); |
||||
|
}); |
||||
|
|
||||
|
PreConfigure<AbpMvcDataAnnotationsLocalizationOptions>(options => |
||||
|
{ |
||||
|
options.AddAssemblyResource( |
||||
|
typeof(CacheResource), |
||||
|
typeof(AbpCachingManagementApplicationContractsModule).Assembly); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
Configure<AbpLocalizationOptions>(options => |
||||
|
{ |
||||
|
options.Resources |
||||
|
.Get<CacheResource>() |
||||
|
.AddBaseTypes(typeof(AbpUiResource)); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,56 @@ |
|||||
|
using LINGYUN.Abp.CachingManagement.Localization; |
||||
|
using LINGYUN.Abp.CachingManagement.Permissions; |
||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
|
||||
|
namespace LINGYUN.Abp.CachingManagement; |
||||
|
|
||||
|
[Controller] |
||||
|
[Authorize(CachingManagementPermissionNames.Cache.Default)] |
||||
|
[RemoteService(Name = AbpCachingManagementRemoteServiceConsts.RemoteServiceName)] |
||||
|
[Area(AbpCachingManagementRemoteServiceConsts.ModuleName)] |
||||
|
[Route("api/caching-management/cache")] |
||||
|
public class CacheController : AbpControllerBase, ICacheAppService |
||||
|
{ |
||||
|
protected ICacheAppService CacheAppService { get; } |
||||
|
|
||||
|
public CacheController(ICacheAppService cacheAppService) |
||||
|
{ |
||||
|
CacheAppService = cacheAppService; |
||||
|
|
||||
|
LocalizationResource = typeof(CacheResource); |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
[Route("keys")] |
||||
|
public virtual Task<CacheKeysDto> GetKeysAsync(GetCacheKeysInput input) |
||||
|
{ |
||||
|
return CacheAppService.GetKeysAsync(input); |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
[Route("value")] |
||||
|
public virtual Task<CacheValueDto> GetValueAsync(CacheKeyInput input) |
||||
|
{ |
||||
|
return CacheAppService.GetValueAsync(input); |
||||
|
} |
||||
|
|
||||
|
[HttpPut] |
||||
|
[Route("refresh")] |
||||
|
[Authorize(CachingManagementPermissionNames.Cache.Refresh)] |
||||
|
public virtual Task RefreshAsync(CacheRefreshInput input) |
||||
|
{ |
||||
|
return CacheAppService.RefreshAsync(input); |
||||
|
} |
||||
|
|
||||
|
[HttpDelete] |
||||
|
[Route("remove")] |
||||
|
[Authorize(CachingManagementPermissionNames.Cache.Delete)] |
||||
|
public virtual Task RemoveAsync(CacheKeyInput input) |
||||
|
{ |
||||
|
return CacheAppService.RemoveAsync(input); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,19 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Volo.Abp.Caching.StackExchangeRedis" Version="$(VoloAbpPackageVersion)" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.CachingManagement.Domain\LINGYUN.Abp.CachingManagement.Domain.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,11 @@ |
|||||
|
using Volo.Abp.Caching.StackExchangeRedis; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace LINGYUN.Abp.CachingManagement.StackExchangeRedis; |
||||
|
|
||||
|
[DependsOn( |
||||
|
typeof(AbpCachingManagementDomainModule), |
||||
|
typeof(AbpCachingStackExchangeRedisModule))] |
||||
|
public class AbpCachingManagementStackExchangeRedisModule : AbpModule |
||||
|
{ |
||||
|
} |
||||
@ -0,0 +1,228 @@ |
|||||
|
using Microsoft.Extensions.Caching.Distributed; |
||||
|
using Microsoft.Extensions.Caching.StackExchangeRedis; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using StackExchange.Redis; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Reflection; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Caching; |
||||
|
using Volo.Abp.Caching.StackExchangeRedis; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace LINGYUN.Abp.CachingManagement.StackExchangeRedis; |
||||
|
|
||||
|
[Dependency(ReplaceServices = true)] |
||||
|
public class StackExchangeRedisCacheManager : ICacheManager, ISingletonDependency |
||||
|
{ |
||||
|
private readonly static MethodInfo GetRedisDatabaseMethod; |
||||
|
private readonly static MethodInfo ConnectAsyncMethod; |
||||
|
|
||||
|
protected RedisCacheOptions RedisCacheOptions { get; } |
||||
|
protected AbpDistributedCacheOptions CacheOptions { get; } |
||||
|
protected ICurrentTenant CurrentTenant { get; } |
||||
|
protected IDistributedCache DistributedCache { get; } |
||||
|
protected AbpRedisCache RedisCache => DistributedCache.As<AbpRedisCache>(); |
||||
|
|
||||
|
protected IDatabase RedisDatabase => GetRedisDatabase(); |
||||
|
private IDatabase _redisDatabase; |
||||
|
|
||||
|
static StackExchangeRedisCacheManager() |
||||
|
{ |
||||
|
var type = typeof(AbpRedisCache); |
||||
|
|
||||
|
ConnectAsyncMethod = type.GetMethod("ConnectAsync", BindingFlags.Instance | BindingFlags.NonPublic); |
||||
|
GetRedisDatabaseMethod = type.GetMethod("GetRedisDatabase", BindingFlags.Instance | BindingFlags.NonPublic); |
||||
|
} |
||||
|
|
||||
|
public StackExchangeRedisCacheManager( |
||||
|
ICurrentTenant currentTenant, |
||||
|
IDistributedCache distributedCache, |
||||
|
IOptions<AbpDistributedCacheOptions> cacheOptions, |
||||
|
IOptions<RedisCacheOptions> redisCacheOptions) |
||||
|
{ |
||||
|
CurrentTenant = currentTenant; |
||||
|
DistributedCache = distributedCache;// distributedCache.As<AbpRedisCache>();
|
||||
|
CacheOptions = cacheOptions.Value; |
||||
|
RedisCacheOptions = redisCacheOptions.Value; |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<CackeKeysResponse> GetKeysAsync(GetCacheKeysRequest request, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
await ConnectAsync(cancellationToken); |
||||
|
|
||||
|
// 缓存键名规则: InstanceName + (t + TenantId)(CurrentTenant.IsAvailable) + CacheItemName + KeyPrefix + Key
|
||||
|
// 缓存键名规则: InstanceName + (c:)(!CurrentTenant.IsAvailable) + CacheItemName + KeyPrefix + Key
|
||||
|
|
||||
|
var match = "*"; |
||||
|
// abp*
|
||||
|
if (!RedisCacheOptions.InstanceName.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
match = RedisCacheOptions.InstanceName; |
||||
|
} |
||||
|
// abp*t:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx*
|
||||
|
// abp*c:*
|
||||
|
if (CurrentTenant.IsAvailable) |
||||
|
{ |
||||
|
match += "t:" + CurrentTenant.Id.ToString() + "*"; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
match += "c:*"; |
||||
|
} |
||||
|
// abp*t:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx*application*
|
||||
|
// abp*c:*application*
|
||||
|
if (!CacheOptions.KeyPrefix.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
match += CacheOptions.KeyPrefix + "*"; |
||||
|
} |
||||
|
|
||||
|
// app*abp*t:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx*application*
|
||||
|
// app*abp*c:*application*
|
||||
|
if (!request.Prefix.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
match = request.Prefix + "*" + match; |
||||
|
} |
||||
|
|
||||
|
// if filter is Mailing:
|
||||
|
// app*abp*t:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx*application*Mailing*
|
||||
|
// app*abp*c:*application*Mailing*
|
||||
|
if (!request.Filter.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
match += request.Filter + "*"; |
||||
|
} |
||||
|
// scan 0 match * count 50000
|
||||
|
// redis有自定义的key排序,由传递的marker来确定下一次检索起始位
|
||||
|
|
||||
|
var args = new object[] { request.Marker ?? "0", "match", match, "count", 50000 }; |
||||
|
|
||||
|
var result = await RedisDatabase.ExecuteAsync("scan", args); |
||||
|
|
||||
|
var results = (RedisResult[])result; |
||||
|
|
||||
|
// 第一个返回结果 下一次检索起始位 0复位
|
||||
|
// 第二个返回结果为key列表
|
||||
|
// https://redis.io/commands/scan/
|
||||
|
return new CackeKeysResponse( |
||||
|
(string)results[0], |
||||
|
(string[])results[1]); |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<CacheValueResponse> GetValueAsync(string key, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
await ConnectAsync(cancellationToken); |
||||
|
|
||||
|
long size = 0; |
||||
|
var values = new Dictionary<string, object>(); |
||||
|
|
||||
|
// type RedisKey
|
||||
|
var type = await RedisDatabase.KeyTypeAsync(key); |
||||
|
// ttl RedisKey
|
||||
|
var ttl = await RedisDatabase.KeyTimeToLiveAsync(key); |
||||
|
|
||||
|
switch (type) |
||||
|
{ |
||||
|
case RedisType.Hash: |
||||
|
// hlen RedisKey
|
||||
|
size = await RedisDatabase.HashLengthAsync(key); |
||||
|
// hscan RedisKey
|
||||
|
var hvalues = RedisDatabase.HashScan(key); |
||||
|
foreach (var hvalue in hvalues) |
||||
|
{ |
||||
|
if (!hvalue.Name.IsNullOrEmpty) |
||||
|
{ |
||||
|
values.Add(hvalue.Name.ToString(), hvalue.Value.IsNullOrEmpty ? "" : hvalue.Value.ToString()); |
||||
|
} |
||||
|
} |
||||
|
break; |
||||
|
case RedisType.String: |
||||
|
// strlen RedisKey
|
||||
|
size = await RedisDatabase.StringLengthAsync(key); |
||||
|
// get RedisKey
|
||||
|
var svalue = RedisDatabase.StringGet(key); |
||||
|
values.Add("value", svalue.IsNullOrEmpty ? "" : svalue.ToString()); |
||||
|
break; |
||||
|
case RedisType.List: |
||||
|
// llen RedisKey
|
||||
|
size = await RedisDatabase.ListLengthAsync(key); |
||||
|
// lrange RedisKey
|
||||
|
var lvalues = RedisDatabase.ListRange(key); |
||||
|
for (var lindex = 0; lindex < lvalues.Length; lindex++) |
||||
|
{ |
||||
|
if (!lvalues[lindex].IsNullOrEmpty) |
||||
|
{ |
||||
|
values.Add($"index.{lindex}", lvalues[lindex].IsNullOrEmpty ? "" : lvalues[lindex].ToString()); |
||||
|
} |
||||
|
} |
||||
|
break; |
||||
|
default: |
||||
|
throw new BusinessException("Abp.CachingManagement:01001") |
||||
|
.WithData("Type", type.ToString()); |
||||
|
} |
||||
|
|
||||
|
return new CacheValueResponse( |
||||
|
type.ToString(), |
||||
|
size, |
||||
|
values, |
||||
|
ttl); |
||||
|
} |
||||
|
|
||||
|
public async virtual Task RefreshAsync(RefreshCacheRequest request, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
var cacheKey = request.Key; |
||||
|
if (!RedisCacheOptions.InstanceName.IsNullOrWhiteSpace() && cacheKey.StartsWith(RedisCacheOptions.InstanceName)) |
||||
|
{ |
||||
|
cacheKey = cacheKey.Substring(RedisCacheOptions.InstanceName.Length); |
||||
|
} |
||||
|
if (request.AbsoluteExpiration.HasValue || request.SlidingExpiration.HasValue) |
||||
|
{ |
||||
|
var value = await RedisCache.GetAsync(cacheKey, cancellationToken); |
||||
|
|
||||
|
await RedisCache.SetAsync( |
||||
|
cacheKey, |
||||
|
value, |
||||
|
new DistributedCacheEntryOptions |
||||
|
{ |
||||
|
SlidingExpiration = request.SlidingExpiration, |
||||
|
AbsoluteExpirationRelativeToNow = request.AbsoluteExpiration, |
||||
|
}, |
||||
|
cancellationToken); |
||||
|
|
||||
|
return; |
||||
|
} |
||||
|
await RedisCache.RefreshAsync(cacheKey, cancellationToken); |
||||
|
} |
||||
|
|
||||
|
public async virtual Task RemoveAsync(string key, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
var cacheKey = key; |
||||
|
if (!RedisCacheOptions.InstanceName.IsNullOrWhiteSpace() && cacheKey.StartsWith(RedisCacheOptions.InstanceName)) |
||||
|
{ |
||||
|
cacheKey = cacheKey.Substring(RedisCacheOptions.InstanceName.Length); |
||||
|
} |
||||
|
await RedisCache.RemoveAsync(cacheKey, cancellationToken); |
||||
|
} |
||||
|
|
||||
|
protected virtual Task ConnectAsync(CancellationToken token = default) |
||||
|
{ |
||||
|
if (_redisDatabase != null) |
||||
|
{ |
||||
|
return Task.CompletedTask; |
||||
|
} |
||||
|
|
||||
|
return (Task)ConnectAsyncMethod.Invoke(RedisCache, new object[] { token }); |
||||
|
} |
||||
|
|
||||
|
private IDatabase GetRedisDatabase() |
||||
|
{ |
||||
|
if (_redisDatabase == null) |
||||
|
{ |
||||
|
_redisDatabase = GetRedisDatabaseMethod.Invoke(RedisCache, null) as IDatabase; |
||||
|
} |
||||
|
|
||||
|
return _redisDatabase; |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue