diff --git a/EasyCaching.sln b/EasyCaching.sln index e8f9f0fc..8dc5aa75 100644 --- a/EasyCaching.sln +++ b/EasyCaching.sln @@ -49,6 +49,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyCaching.CSRedis", "src\ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyCaching.Bus.CSRedis", "src\EasyCaching.Bus.CSRedis\EasyCaching.Bus.CSRedis.csproj", "{861E5373-BEF6-4AA2-92C7-8F4941A079E7}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyCaching.Disk", "src\EasyCaching.Disk\EasyCaching.Disk.csproj", "{3D48FD75-01D6-44F9-B7C3-CB6DE784F476}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -139,6 +141,10 @@ Global {861E5373-BEF6-4AA2-92C7-8F4941A079E7}.Debug|Any CPU.Build.0 = Debug|Any CPU {861E5373-BEF6-4AA2-92C7-8F4941A079E7}.Release|Any CPU.ActiveCfg = Release|Any CPU {861E5373-BEF6-4AA2-92C7-8F4941A079E7}.Release|Any CPU.Build.0 = Release|Any CPU + {3D48FD75-01D6-44F9-B7C3-CB6DE784F476}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3D48FD75-01D6-44F9-B7C3-CB6DE784F476}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3D48FD75-01D6-44F9-B7C3-CB6DE784F476}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3D48FD75-01D6-44F9-B7C3-CB6DE784F476}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {CE61FAA2-0233-451C-991D-4222ED61C84B} = {A0F5CC7E-155F-4726-8DEB-E966950B3FE9} @@ -162,5 +168,6 @@ Global {6EBE36A2-F128-4C63-B90A-B700D8C2F2E8} = {EBB55F65-7D07-4281-8D5E-7B0CA88E1AD0} {6584761E-E51C-408F-BE51-CA0F6269589B} = {A0F5CC7E-155F-4726-8DEB-E966950B3FE9} {861E5373-BEF6-4AA2-92C7-8F4941A079E7} = {A0F5CC7E-155F-4726-8DEB-E966950B3FE9} + {3D48FD75-01D6-44F9-B7C3-CB6DE784F476} = {A0F5CC7E-155F-4726-8DEB-E966950B3FE9} EndGlobalSection EndGlobal diff --git a/build/releasenotes.props b/build/releasenotes.props index 2654fab8..40ac6d05 100644 --- a/build/releasenotes.props +++ b/build/releasenotes.props @@ -1,34 +1,44 @@ - - 1. fix typo: IsHightAvailability -> IsHighAvailability. + + 1. Named Serializer + 2. Add a new CachingProviderType for DiskCachingProvider + 3. Remove Refresh/RefreshAsync methods + 4. HybridCachingProvider add GetAsync method with type 1. Upgrading dependencies. + 2. Remove Refresh/RefreshAsync methods - 1. Fixed zrange error. + 1. Upgrading dependencies. + 2. Remove Refresh/RefreshAsync methods 1. Upgrading dependencies. + 2. Remove Refresh/RefreshAsync methods 1. Upgrading dependencies. + 2. Remove Refresh/RefreshAsync methods - 1. Can be downgraded to LocalCacheProvider. + 1. Upgrading dependencies. + 2. Remove Refresh/RefreshAsync methods 1. Upgrading dependencies. + 2. Remove Refresh/RefreshAsync methods 1. Upgrading dependencies. + 2. Remove Refresh/RefreshAsync methods - 1. Upgrading dependencies. + 1. Upgrading dependencies. - 1. Upgrading dependencies. + 1. Upgrading dependencies. 1. Upgrading dependencies. @@ -38,6 +48,7 @@ 1. Upgrading dependencies. + 2. Remove Refresh/RefreshAsync methods 1. Upgrading dependencies. @@ -45,5 +56,8 @@ 1. Upgrading dependencies. + + 1. init. + diff --git a/build/version.props b/build/version.props index 2fc070ba..c672d79b 100644 --- a/build/version.props +++ b/build/version.props @@ -1,20 +1,21 @@ - 0.5.6 - 0.5.6 - 0.5.6.1 - 0.5.6 - 0.5.6 - 0.5.6.1 - 0.5.6 - 0.5.6 - 0.5.6 - 0.5.6 - 0.5.6 - 0.5.6 - 0.5.6 - 0.5.6 - 0.5.6 - 0.5.6 + 0.6.0 + 0.6.0 + 0.6.0 + 0.6.0 + 0.6.0 + 0.6.0 + 0.6.0 + 0.6.0 + 0.6.0 + 0.6.0 + 0.6.0 + 0.6.0 + 0.6.0 + 0.6.0 + 0.6.0 + 0.6.0 + 0.6.0 diff --git a/src/EasyCaching.Bus.CSRedis/EasyCaching.Bus.CSRedis.csproj b/src/EasyCaching.Bus.CSRedis/EasyCaching.Bus.CSRedis.csproj index 2f2d10af..90eb66f9 100644 --- a/src/EasyCaching.Bus.CSRedis/EasyCaching.Bus.CSRedis.csproj +++ b/src/EasyCaching.Bus.CSRedis/EasyCaching.Bus.CSRedis.csproj @@ -3,15 +3,15 @@ netstandard2.0 - Catcher Wong - Catcher Wong + ncc;Catcher Wong + ncc;Catcher Wong $(EasyCachingRedisBusPackageVersion) A simple caching bus(message bus) based on CSRedis. Bus,Hybrid,Redis,Caching,Cache https://github.com/dotnetcore/EasyCaching - https://github.com/dotnetcore/EasyCaching/blob/master/LICENSE + LICENSE https://github.com/dotnetcore/EasyCaching https://github.com/dotnetcore/EasyCaching https://raw.githubusercontent.com/dotnetcore/EasyCaching/master/media/nuget-icon.png @@ -26,7 +26,11 @@ - + + + + + diff --git a/src/EasyCaching.Bus.RabbitMQ/EasyCaching.Bus.RabbitMQ.csproj b/src/EasyCaching.Bus.RabbitMQ/EasyCaching.Bus.RabbitMQ.csproj index 2df0a2e4..ae7d9ee6 100644 --- a/src/EasyCaching.Bus.RabbitMQ/EasyCaching.Bus.RabbitMQ.csproj +++ b/src/EasyCaching.Bus.RabbitMQ/EasyCaching.Bus.RabbitMQ.csproj @@ -3,15 +3,15 @@ netstandard2.0 - Catcher Wong - Catcher Wong + ncc;Catcher Wong + ncc;Catcher Wong $(EasyCachingRabbitBusPackageVersion) A simple caching bus(message bus) based on RabbitMQ. Bus,Hybrid,RabbitMQ,Caching,Cache https://github.com/dotnetcore/EasyCaching - https://github.com/dotnetcore/EasyCaching/blob/master/LICENSE + LICENSE https://github.com/dotnetcore/EasyCaching https://github.com/dotnetcore/EasyCaching https://raw.githubusercontent.com/dotnetcore/EasyCaching/master/media/nuget-icon.png @@ -25,13 +25,19 @@ $(NoWarn);1591 + + + + + + diff --git a/src/EasyCaching.Bus.Redis/EasyCaching.Bus.Redis.csproj b/src/EasyCaching.Bus.Redis/EasyCaching.Bus.Redis.csproj index a9e2e243..a509501d 100644 --- a/src/EasyCaching.Bus.Redis/EasyCaching.Bus.Redis.csproj +++ b/src/EasyCaching.Bus.Redis/EasyCaching.Bus.Redis.csproj @@ -3,15 +3,15 @@ netstandard2.0 - Catcher Wong - Catcher Wong + ncc;Catcher Wong + ncc;Catcher Wong $(EasyCachingRedisBusPackageVersion) A simple caching bus(message bus) based on StackExchange.Redis. Bus,Hybrid,Redis,Caching,Cache https://github.com/dotnetcore/EasyCaching - https://github.com/dotnetcore/EasyCaching/blob/master/LICENSE + LICENSE https://github.com/dotnetcore/EasyCaching https://github.com/dotnetcore/EasyCaching https://raw.githubusercontent.com/dotnetcore/EasyCaching/master/media/nuget-icon.png @@ -25,6 +25,9 @@ $(NoWarn);1591 + + + diff --git a/src/EasyCaching.CSRedis/Configurations/EasyCachingOptionsExtensions.cs b/src/EasyCaching.CSRedis/Configurations/EasyCachingOptionsExtensions.cs index ffb1df70..5702a410 100644 --- a/src/EasyCaching.CSRedis/Configurations/EasyCachingOptionsExtensions.cs +++ b/src/EasyCaching.CSRedis/Configurations/EasyCachingOptionsExtensions.cs @@ -41,10 +41,8 @@ public static EasyCachingOptions UseCSRedis(this EasyCachingOptions options, ICo void configure(RedisOptions x) { - x.CachingProviderType = redisOptions.CachingProviderType; x.EnableLogging = redisOptions.EnableLogging; x.MaxRdSecond = redisOptions.MaxRdSecond; - x.Order = redisOptions.Order; x.DBConfig = redisOptions.DBConfig; } diff --git a/src/EasyCaching.CSRedis/Configurations/RedisOptions.cs b/src/EasyCaching.CSRedis/Configurations/RedisOptions.cs index 2e3f01d9..43e0244d 100755 --- a/src/EasyCaching.CSRedis/Configurations/RedisOptions.cs +++ b/src/EasyCaching.CSRedis/Configurations/RedisOptions.cs @@ -7,7 +7,7 @@ public class RedisOptions : BaseProviderOptions { public RedisOptions() { - this.CachingProviderType = CachingProviderType.Redis; + } /// diff --git a/src/EasyCaching.CSRedis/Configurations/RedisOptionsExtension.cs b/src/EasyCaching.CSRedis/Configurations/RedisOptionsExtension.cs index fb6c5384..7fa38803 100755 --- a/src/EasyCaching.CSRedis/Configurations/RedisOptionsExtension.cs +++ b/src/EasyCaching.CSRedis/Configurations/RedisOptionsExtension.cs @@ -75,11 +75,11 @@ public void AddServices(IServiceCollection services) Func createFactory = x => { var clients = x.GetServices(); - var serializer = x.GetRequiredService(); + var serializers = x.GetServices(); var optionsMon = x.GetRequiredService>(); var options = optionsMon.Get(_name); var factory = x.GetService(); - return new DefaultCSRedisCachingProvider(_name, clients, serializer, options, factory); + return new DefaultCSRedisCachingProvider(_name, clients, serializers, options, factory); }; services.AddSingleton(createFactory); diff --git a/src/EasyCaching.CSRedis/DefaultCSRedisCachingProvider.cs b/src/EasyCaching.CSRedis/DefaultCSRedisCachingProvider.cs index a81f2374..abdc570d 100755 --- a/src/EasyCaching.CSRedis/DefaultCSRedisCachingProvider.cs +++ b/src/EasyCaching.CSRedis/DefaultCSRedisCachingProvider.cs @@ -48,31 +48,30 @@ public partial class DefaultCSRedisCachingProvider : EasyCachingAbstractProvider /// /// Name. /// Clients. - /// Serializer. + /// Serializers. /// Options. /// Logger factory. public DefaultCSRedisCachingProvider( string name, IEnumerable clients, - IEasyCachingSerializer serializer, + IEnumerable serializers, RedisOptions options, ILoggerFactory loggerFactory = null) { this._name = name; - this._serializer = serializer; + this._serializer = serializers.FirstOrDefault(x => x.Name.Equals(_name)) ?? serializers.Single(x => x.Name.Equals(EasyCachingConstValue.DefaultSerializerName)); this._options = options; this._logger = loggerFactory?.CreateLogger(); this._cache = clients.Single(x => x.Name.Equals(_name)); this._cacheStats = new CacheStats(); this.ProviderName = this._name; + this.ProviderType = CachingProviderType.Redis; this.ProviderStats = this._cacheStats; - this.ProviderType = _options.CachingProviderType; - this.ProviderOrder = _options.Order; this.ProviderMaxRdSecond = _options.MaxRdSecond; this.IsDistributedProvider = true; } - + /// /// Exists the specified cacheKey. /// @@ -498,42 +497,7 @@ public override int BaseGetCount(string prefix = "") return this.SearchRedisKeys(this.HandlePrefix(prefix)).Length; } - - /// - /// Refresh the specified cacheKey, cacheValue and expiration. - /// - /// Cache key. - /// Cache value. - /// Expiration. - /// The 1st type parameter. - public override void BaseRefresh(string cacheKey, T cacheValue, TimeSpan expiration) - { - ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); - ArgumentCheck.NotNull(cacheValue, nameof(cacheValue)); - ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); - - this.Remove(cacheKey); - this.Set(cacheKey, cacheValue, expiration); - } - - /// - /// Refreshs the async. - /// - /// The async. - /// Cache key. - /// Cache value. - /// Expiration. - /// The 1st type parameter. - public override async Task BaseRefreshAsync(string cacheKey, T cacheValue, TimeSpan expiration) - { - ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); - ArgumentCheck.NotNull(cacheValue, nameof(cacheValue)); - ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); - - await this.RemoveAsync(cacheKey); - await this.SetAsync(cacheKey, cacheValue, expiration); - } - + /// /// Remove the specified cacheKey. /// diff --git a/src/EasyCaching.CSRedis/EasyCaching.CSRedis.csproj b/src/EasyCaching.CSRedis/EasyCaching.CSRedis.csproj index 8630aa45..8bdcdd85 100644 --- a/src/EasyCaching.CSRedis/EasyCaching.CSRedis.csproj +++ b/src/EasyCaching.CSRedis/EasyCaching.CSRedis.csproj @@ -3,15 +3,15 @@ netstandard2.0 - Catcher Wong - Catcher Wong + ncc;Catcher Wong + ncc;Catcher Wong $(EasyCachingCSRedisPackageVersion) A simple distributed caching provider based on csredis. Redis,DistributedCache,Caching,Cache https://github.com/dotnetcore/EasyCaching - https://github.com/dotnetcore/EasyCaching/blob/master/LICENSE + LICENSE https://github.com/dotnetcore/EasyCaching https://github.com/dotnetcore/EasyCaching https://raw.githubusercontent.com/dotnetcore/EasyCaching/master/media/nuget-icon.png @@ -26,7 +26,11 @@ - + + + + + diff --git a/src/EasyCaching.Core/Configurations/BaseProviderOptions.cs b/src/EasyCaching.Core/Configurations/BaseProviderOptions.cs index 28032a3e..8cb0f2f4 100644 --- a/src/EasyCaching.Core/Configurations/BaseProviderOptions.cs +++ b/src/EasyCaching.Core/Configurations/BaseProviderOptions.cs @@ -4,16 +4,7 @@ /// Base provider options. /// public class BaseProviderOptions - { - /// - /// Gets or sets the type of the caching provider. - /// - /// - /// Reserved, not used yet. - /// - /// The type of the caching provider. - public CachingProviderType CachingProviderType { get; set; } - + { /// /// Gets or sets the max random second. /// @@ -24,15 +15,6 @@ public class BaseProviderOptions /// The max random second. public int MaxRdSecond { get; set; } = 120; - /// - /// Gets or sets the order. - /// - /// - /// Mainly for hybird - /// - /// The order. - public int Order { get; set; } - /// /// Gets or sets a value indicating whether enable logging. /// diff --git a/src/EasyCaching.Core/EasyCaching.Core.csproj b/src/EasyCaching.Core/EasyCaching.Core.csproj index 3f3e1ed3..0079157e 100644 --- a/src/EasyCaching.Core/EasyCaching.Core.csproj +++ b/src/EasyCaching.Core/EasyCaching.Core.csproj @@ -3,15 +3,15 @@ netstandard2.0 - Catcher Wong - Catcher Wong + ncc;Catcher Wong + ncc;Catcher Wong $(EasyCachingCorePackageVersion) EasyCaching is a open source caching library that contains basic usages and some advanced usages of caching which can help us to handle caching more easier! Caching,Cache,Distributed,Memory,Interceptor,Hybrid,ResponseCaching https://github.com/dotnetcore/EasyCaching - https://github.com/dotnetcore/EasyCaching/blob/master/LICENSE + LICENSE https://github.com/dotnetcore/EasyCaching https://github.com/dotnetcore/EasyCaching https://raw.githubusercontent.com/dotnetcore/EasyCaching/master/media/nuget-icon.png @@ -25,6 +25,10 @@ $(NoWarn);1591 + + + + diff --git a/src/EasyCaching.Core/EasyCachingAbstractProvider.cs b/src/EasyCaching.Core/EasyCachingAbstractProvider.cs index 4de506d5..3fdb3f67 100644 --- a/src/EasyCaching.Core/EasyCachingAbstractProvider.cs +++ b/src/EasyCaching.Core/EasyCachingAbstractProvider.cs @@ -14,14 +14,12 @@ public abstract class EasyCachingAbstractProvider : IEasyCachingProvider protected string ProviderName { get; set; } protected bool IsDistributedProvider { get; set; } - protected int ProviderOrder { get; set; } protected int ProviderMaxRdSecond { get; set; } protected CachingProviderType ProviderType { get; set; } protected CacheStats ProviderStats { get; set; } public string Name => this.ProviderName; public bool IsDistributedCache => this.IsDistributedProvider; - public int Order => this.ProviderOrder; public int MaxRdSecond => this.ProviderMaxRdSecond; public CachingProviderType CachingProviderType => this.ProviderType; public CacheStats CacheStats => this.ProviderStats; @@ -40,8 +38,6 @@ public abstract class EasyCachingAbstractProvider : IEasyCachingProvider public abstract IDictionary> BaseGetByPrefix(string prefix); public abstract Task>> BaseGetByPrefixAsync(string prefix); public abstract int BaseGetCount(string prefix = ""); - public abstract void BaseRefresh(string cacheKey, T cacheValue, TimeSpan expiration); - public abstract Task BaseRefreshAsync(string cacheKey, T cacheValue, TimeSpan expiration); public abstract void BaseRemove(string cacheKey); public abstract void BaseRemoveAll(IEnumerable cacheKeys); public abstract Task BaseRemoveAllAsync(IEnumerable cacheKeys); @@ -402,58 +398,6 @@ public int GetCount(string prefix = "") return BaseGetCount(prefix); } - public void Refresh(string cacheKey, T cacheValue, TimeSpan expiration) - { - var operationId = s_diagnosticListener.WriteSetCacheBefore(new BeforeSetRequestEventData(CachingProviderType.ToString(), Name, nameof(Refresh), new Dictionary { { cacheKey, cacheValue } }, expiration)); - Exception e = null; - try - { - BaseRefresh(cacheKey, cacheValue, expiration); - } - catch (Exception ex) - { - e = ex; - throw; - } - finally - { - if (e != null) - { - s_diagnosticListener.WriteSetCacheError(operationId, e); - } - else - { - s_diagnosticListener.WriteSetCacheAfter(operationId); - } - } - } - - public async Task RefreshAsync(string cacheKey, T cacheValue, TimeSpan expiration) - { - var operationId = s_diagnosticListener.WriteSetCacheBefore(new BeforeSetRequestEventData(CachingProviderType.ToString(), Name, nameof(RefreshAsync), new Dictionary { { cacheKey, cacheValue } }, expiration)); - Exception e = null; - try - { - await BaseRefreshAsync(cacheKey, cacheValue, expiration); - } - catch (Exception ex) - { - e = ex; - throw; - } - finally - { - if (e != null) - { - s_diagnosticListener.WriteSetCacheError(operationId, e); - } - else - { - s_diagnosticListener.WriteSetCacheAfter(operationId); - } - } - } - public void Remove(string cacheKey) { var operationId = s_diagnosticListener.WriteRemoveCacheBefore(new BeforeRemoveRequestEventData(CachingProviderType.ToString(), Name, nameof(Remove), new[] { cacheKey })); diff --git a/src/EasyCaching.Core/IEasyCachingProvider.cs b/src/EasyCaching.Core/IEasyCachingProvider.cs index 811a5702..b5e4b396 100644 --- a/src/EasyCaching.Core/IEasyCachingProvider.cs +++ b/src/EasyCaching.Core/IEasyCachingProvider.cs @@ -112,24 +112,6 @@ public interface IEasyCachingProvider /// true if is distributed cache; otherwise, false. bool IsDistributedCache { get; } - /// - /// Refresh the cached value by specified cacheKey, cacheValue and expiration. - /// - /// Cache key. - /// Cache value. - /// Expiration. - /// The 1st type parameter. - void Refresh(string cacheKey, T cacheValue, TimeSpan expiration); - - /// - /// Refresh the cached value by specified cacheKey, cacheValue and expiration async. - /// - /// Cache key. - /// Cache value. - /// Expiration. - /// The 1st type parameter. - Task RefreshAsync(string cacheKey, T cacheValue, TimeSpan expiration); - /// /// Removes cached item by cachekey's prefix. /// @@ -222,12 +204,6 @@ public interface IEasyCachingProvider /// The async. Task FlushAsync(); - /// - /// Gets the order. - /// - /// The order. - int Order { get; } - /// /// Gets the max rd second. /// diff --git a/src/EasyCaching.Core/IHybridCachingProvider.cs b/src/EasyCaching.Core/IHybridCachingProvider.cs index a82e4abd..959dc5ed 100644 --- a/src/EasyCaching.Core/IHybridCachingProvider.cs +++ b/src/EasyCaching.Core/IHybridCachingProvider.cs @@ -152,5 +152,13 @@ public interface IHybridCachingProvider /// /// Prefix of CacheKey. Task RemoveByPrefixAsync(string prefix); + + /// + /// Gets the specified cacheKey async. + /// + /// The async. + /// Cache key. + /// Object Type. + Task GetAsync(string cacheKey, Type type); } } diff --git a/src/EasyCaching.Core/Interceptor/EasyCachingAbleAttribute.cs b/src/EasyCaching.Core/Interceptor/EasyCachingAbleAttribute.cs new file mode 100644 index 00000000..ca016f3a --- /dev/null +++ b/src/EasyCaching.Core/Interceptor/EasyCachingAbleAttribute.cs @@ -0,0 +1,17 @@ +namespace EasyCaching.Core.Interceptor +{ + using System; + + /// + /// Easycaching able attribute. + /// + [AttributeUsage(AttributeTargets.Method, Inherited = true)] + public class EasyCachingAbleAttribute : EasyCachingInterceptorAttribute + { + /// + /// Gets or sets the expiration. The default value is 30 second. + /// + /// The expiration. + public int Expiration { get; set; } = 30; + } +} diff --git a/src/EasyCaching.Core/Interceptor/EasyCachingEvictAttribute.cs b/src/EasyCaching.Core/Interceptor/EasyCachingEvictAttribute.cs new file mode 100644 index 00000000..13404c08 --- /dev/null +++ b/src/EasyCaching.Core/Interceptor/EasyCachingEvictAttribute.cs @@ -0,0 +1,26 @@ +namespace EasyCaching.Core.Interceptor +{ + using System; + + /// + /// Easycaching evict attribute. + /// + [AttributeUsage(AttributeTargets.Method, Inherited = true)] + public class EasyCachingEvictAttribute : EasyCachingInterceptorAttribute + { + /// + /// Gets or sets a value indicating whether evict all cached values by cachekey prefix + /// + /// + /// This need to use with CacheKeyPrefix. + /// + /// true if is all; otherwise, false. + public bool IsAll { get; set; } = false; + + /// + /// Gets or sets a value indicating whether is before. + /// + /// true if is before; otherwise, false. + public bool IsBefore { get; set; } = false; + } +} diff --git a/src/EasyCaching.Core/Interceptor/EasyCachingInterceptorAttribute.cs b/src/EasyCaching.Core/Interceptor/EasyCachingInterceptorAttribute.cs index e3a14348..5f04efe6 100644 --- a/src/EasyCaching.Core/Interceptor/EasyCachingInterceptorAttribute.cs +++ b/src/EasyCaching.Core/Interceptor/EasyCachingInterceptorAttribute.cs @@ -33,52 +33,4 @@ public class EasyCachingInterceptorAttribute : Attribute /// The cache key prefix. public bool IsHighAvailability { get; set; } = true; } - - /// - /// Easycaching able attribute. - /// - [AttributeUsage(AttributeTargets.Method, Inherited = true)] - public class EasyCachingAbleAttribute : EasyCachingInterceptorAttribute - { - /// - /// Gets or sets the expiration. The default value is 30 second. - /// - /// The expiration. - public int Expiration { get; set; } = 30; - } - - /// - /// Easycaching put attribute. - /// - [AttributeUsage(AttributeTargets.Method, Inherited = true)] - public class EasyCachingPutAttribute : EasyCachingInterceptorAttribute - { - /// - /// Gets or sets the expiration. The default value is 30 second. - /// - /// The expiration. - public int Expiration { get; set; } = 30; - } - - /// - /// Easycaching evict attribute. - /// - [AttributeUsage(AttributeTargets.Method, Inherited = true)] - public class EasyCachingEvictAttribute : EasyCachingInterceptorAttribute - { - /// - /// Gets or sets a value indicating whether evict all cached values by cachekey prefix - /// - /// - /// This need to use with CacheKeyPrefix. - /// - /// true if is all; otherwise, false. - public bool IsAll { get; set; } = false; - - /// - /// Gets or sets a value indicating whether is before. - /// - /// true if is before; otherwise, false. - public bool IsBefore { get; set; } = false; - } } diff --git a/src/EasyCaching.Core/Interceptor/EasyCachingPutAttribute.cs b/src/EasyCaching.Core/Interceptor/EasyCachingPutAttribute.cs new file mode 100644 index 00000000..3f44458b --- /dev/null +++ b/src/EasyCaching.Core/Interceptor/EasyCachingPutAttribute.cs @@ -0,0 +1,17 @@ +namespace EasyCaching.Core.Interceptor +{ + using System; + + /// + /// Easycaching put attribute. + /// + [AttributeUsage(AttributeTargets.Method, Inherited = true)] + public class EasyCachingPutAttribute : EasyCachingInterceptorAttribute + { + /// + /// Gets or sets the expiration. The default value is 30 second. + /// + /// The expiration. + public int Expiration { get; set; } = 30; + } +} diff --git a/src/EasyCaching.Core/Interceptor/ParameterCacheKeys.cs b/src/EasyCaching.Core/Interceptor/ParameterCacheKeys.cs index 4b4971e8..d0697f6f 100644 --- a/src/EasyCaching.Core/Interceptor/ParameterCacheKeys.cs +++ b/src/EasyCaching.Core/Interceptor/ParameterCacheKeys.cs @@ -1,10 +1,10 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; - namespace EasyCaching.Core.Interceptor { + using System; + using System.Collections; + using System.Collections.Generic; + using System.Linq; + public static class ParameterCacheKeys { public static string GenerateCacheKey(object parameter) diff --git a/src/EasyCaching.Core/Internal/CachingProviderType.cs b/src/EasyCaching.Core/Internal/CachingProviderType.cs index d8e198c4..2103f00f 100644 --- a/src/EasyCaching.Core/Internal/CachingProviderType.cs +++ b/src/EasyCaching.Core/Internal/CachingProviderType.cs @@ -9,6 +9,7 @@ public enum CachingProviderType Memcached, Redis, SQLite, + Disk, Ext1, Ext2 } diff --git a/src/EasyCaching.Core/Internal/EasyCachingConstValue.cs b/src/EasyCaching.Core/Internal/EasyCachingConstValue.cs index 9d94e559..89c05689 100644 --- a/src/EasyCaching.Core/Internal/EasyCachingConstValue.cs +++ b/src/EasyCaching.Core/Internal/EasyCachingConstValue.cs @@ -35,6 +35,11 @@ public class EasyCachingConstValue /// public const string InMemorySection = "easycaching:inmemory"; + /// + /// The disk section. + /// + public const string DiskSection = "easycaching:disk"; + /// /// The redis bus section. /// @@ -69,5 +74,15 @@ public class EasyCachingConstValue /// The default name of the SQLite. /// public const string DefaultSQLiteName = "DefaultSQLite"; + + /// + /// The default name of the disk. + /// + public const string DefaultDiskName = "DefaultDisk"; + + /// + /// The default name of the serializer. + /// + public const string DefaultSerializerName = "binary"; } } diff --git a/src/EasyCaching.Core/Serialization/DefaultBinaryFormatterSerializer.cs b/src/EasyCaching.Core/Serialization/DefaultBinaryFormatterSerializer.cs index a51eb736..fb6a72a2 100644 --- a/src/EasyCaching.Core/Serialization/DefaultBinaryFormatterSerializer.cs +++ b/src/EasyCaching.Core/Serialization/DefaultBinaryFormatterSerializer.cs @@ -9,6 +9,12 @@ /// public class DefaultBinaryFormatterSerializer : IEasyCachingSerializer { + /// + /// Gets the name. + /// + /// The name. + public string Name => EasyCachingConstValue.DefaultSerializerName; + /// /// Deserialize the specified bytes. /// diff --git a/src/EasyCaching.Core/Serialization/IEasyCachingSerializer.cs b/src/EasyCaching.Core/Serialization/IEasyCachingSerializer.cs index 272207d6..77dfaae7 100644 --- a/src/EasyCaching.Core/Serialization/IEasyCachingSerializer.cs +++ b/src/EasyCaching.Core/Serialization/IEasyCachingSerializer.cs @@ -7,6 +7,12 @@ /// public interface IEasyCachingSerializer { + /// + /// Gets the name. + /// + /// The name. + string Name { get; } + /// /// Serialize the specified value. /// @@ -23,7 +29,6 @@ public interface IEasyCachingSerializer /// The 1st type parameter. T Deserialize(byte[] bytes); - /// /// Deserialize the specified bytes. /// diff --git a/src/EasyCaching.Disk/Configurations/DiskOptions.cs b/src/EasyCaching.Disk/Configurations/DiskOptions.cs new file mode 100644 index 00000000..d37cc3c9 --- /dev/null +++ b/src/EasyCaching.Disk/Configurations/DiskOptions.cs @@ -0,0 +1,13 @@ +namespace EasyCaching.Disk +{ + using EasyCaching.Core.Configurations; + + public class DiskOptions : BaseProviderOptions + { + public DiskOptions() + { + } + + public DiskDbOptions DBConfig { get; set; } = new DiskDbOptions(); + } +} diff --git a/src/EasyCaching.Disk/Configurations/DiskOptionsExtension.cs b/src/EasyCaching.Disk/Configurations/DiskOptionsExtension.cs new file mode 100644 index 00000000..7f59f49a --- /dev/null +++ b/src/EasyCaching.Disk/Configurations/DiskOptionsExtension.cs @@ -0,0 +1,49 @@ +namespace EasyCaching.Disk +{ + using System; + using EasyCaching.Core; + using EasyCaching.Core.Configurations; + using MessagePack.Resolvers; + using Microsoft.AspNetCore.Builder; + using Microsoft.Extensions.DependencyInjection; + using Microsoft.Extensions.DependencyInjection.Extensions; + + internal sealed class DiskOptionsExtension : IEasyCachingOptionsExtension + { + /// + /// The name. + /// + private readonly string _name; + /// + /// The configure. + /// + private readonly Action configure; + + public DiskOptionsExtension(string name, Action configure) + { + this._name = name; + this.configure = configure; + } + + public void AddServices(IServiceCollection services) + { + services.AddOptions(); + services.Configure(_name, configure); + + services.TryAddSingleton(); + services.AddSingleton(x => + { + var optionsMon = x.GetRequiredService>(); + var options = optionsMon.Get(_name); + //ILoggerFactory can be null + var factory = x.GetService(); + return new DefaultDiskCachingProvider(_name, options, factory); + }); + } + + public void WithServices(IApplicationBuilder app) + { + // Method intentionally left empty. + } + } +} diff --git a/src/EasyCaching.Disk/Configurations/EasyCachingOptionsExtensions.cs b/src/EasyCaching.Disk/Configurations/EasyCachingOptionsExtensions.cs new file mode 100644 index 00000000..62df72dd --- /dev/null +++ b/src/EasyCaching.Disk/Configurations/EasyCachingOptionsExtensions.cs @@ -0,0 +1,40 @@ +namespace EasyCaching.Disk +{ + using System; + using EasyCaching.Core; + using EasyCaching.Core.Configurations; + using Microsoft.Extensions.Configuration; + + public static class EasyCachingOptionsExtensions + { + /// + /// Uses the disk caching provider. + /// + /// Options. + /// Configure. + /// Name. + public static EasyCachingOptions UseDisk(this EasyCachingOptions options, Action configure, string name = EasyCachingConstValue.DefaultDiskName) + { + ArgumentCheck.NotNull(configure, nameof(configure)); + + options.RegisterExtension(new DiskOptionsExtension(name, configure)); + + return options; + } + + public static EasyCachingOptions UseDisk(this EasyCachingOptions options, IConfiguration configuration, string name = EasyCachingConstValue.DefaultDiskName, string sectionName = EasyCachingConstValue.DiskSection) + { + var dbConfig = configuration.GetSection(sectionName); + var diskOptions = new DiskOptions(); + dbConfig.Bind(diskOptions); + + void configure(DiskOptions x) + { + x.EnableLogging = diskOptions.EnableLogging; + x.MaxRdSecond = diskOptions.MaxRdSecond; + x.DBConfig = diskOptions.DBConfig; + } + return options.UseDisk(configure, name); + } + } +} diff --git a/src/EasyCaching.Disk/DefaultDiskCachingProvider.Async.cs b/src/EasyCaching.Disk/DefaultDiskCachingProvider.Async.cs new file mode 100644 index 00000000..a034a7ba --- /dev/null +++ b/src/EasyCaching.Disk/DefaultDiskCachingProvider.Async.cs @@ -0,0 +1,429 @@ +namespace EasyCaching.Disk +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using System.Threading.Tasks; + using EasyCaching.Core; + using MessagePack; + using Microsoft.Extensions.Logging; + + public partial class DefaultDiskCachingProvider : EasyCachingAbstractProvider + { + public override async Task BaseExistsAsync(string cacheKey) + { + ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); + + var path = BuildMd5Path(cacheKey); + + if (!File.Exists(path)) return false; + + var val = await GetDiskCacheValueAsync(path); + + return val.Expiration > DateTimeOffset.UtcNow; + } + + public override Task BaseFlushAsync() + { + if (_options.EnableLogging) + _logger?.LogInformation("FlushAsync"); + + var md5FolderName = GetMd5Str(_name); + + var path = Path.Combine(_options.DBConfig.BasePath, md5FolderName); + + DeleteDirectory(path); + + _cacheKeysMap.Clear(); + + return Task.CompletedTask; + } + + public override async Task>> BaseGetAllAsync(IEnumerable cacheKeys) + { + ArgumentCheck.NotNullAndCountGTZero(cacheKeys, nameof(cacheKeys)); + + IDictionary> dict = new Dictionary>(); + + foreach (var item in cacheKeys) + { + var path = GetRawPath(item); + + if (!File.Exists(path)) + { + if (!dict.ContainsKey(item)) + { + dict.Add(item, CacheValue.NoValue); + } + } + else + { + var cached = await GetDiskCacheValueAsync(path); + + if (cached.Expiration > DateTimeOffset.UtcNow) + { + var t = MessagePackSerializer.Deserialize(cached.Value, MessagePack.Resolvers.ContractlessStandardResolver.Instance); + + if (!dict.ContainsKey(item)) + { + dict.Add(item, new CacheValue(t, true)); + } + } + else + { + if (!dict.ContainsKey(item)) + { + dict.Add(item, CacheValue.NoValue); + } + } + } + } + + return dict; + } + + public override async Task> BaseGetAsync(string cacheKey, Func> dataRetriever, TimeSpan expiration) + { + ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); + ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); + + var path = GetRawPath(cacheKey); + + if (File.Exists(path)) + { + //var cached = await GetDiskCacheValueAsync(path); + var cached = GetDiskCacheValue(path); + + if (cached.Expiration > DateTimeOffset.UtcNow) + { + var t = MessagePackSerializer.Deserialize(cached.Value, MessagePack.Resolvers.ContractlessStandardResolver.Instance); + + if (_options.EnableLogging) + _logger?.LogInformation($"Cache Hit : cachekey = {cacheKey}"); + + CacheStats.OnHit(); + + return new CacheValue(t, true); + } + } + + CacheStats.OnMiss(); + + if (_options.EnableLogging) + _logger?.LogInformation($"Cache Missed : cachekey = {cacheKey}"); + + // TODO: how to add mutex key here + if (!_cacheKeysMap.TryAdd($"{cacheKey}_Lock", "1")) + { + System.Threading.Thread.Sleep(_options.SleepMs); + return await GetAsync(cacheKey, dataRetriever, expiration); + } + + var res = await dataRetriever(); + + if (res != null) + { + await SetAsync(cacheKey, res, expiration); + //remove mutex key + _cacheKeysMap.TryRemove($"{cacheKey}_Lock", out _); + return new CacheValue(res, true); + } + else + { + //remove mutex key + _cacheKeysMap.TryRemove($"{cacheKey}_Lock", out _); + return CacheValue.NoValue; + } + } + + public override async Task BaseGetAsync(string cacheKey, Type type) + { + ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); + + var path = GetRawPath(cacheKey); + + if (!File.Exists(path)) + { + CacheStats.OnMiss(); + + if (_options.EnableLogging) + _logger?.LogInformation($"Cache Missed : cachekey = {cacheKey}"); + + return null; + } + + var cached = await GetDiskCacheValueAsync(path); + + if (cached.Expiration > DateTimeOffset.UtcNow) + { + if (_options.EnableLogging) + _logger?.LogInformation($"Cache Hit : cachekey = {cacheKey}"); + + CacheStats.OnHit(); + + var t = MessagePackSerializer.NonGeneric.Deserialize(type, cached.Value); + return t; + } + else + { + if (_options.EnableLogging) + _logger?.LogInformation($"Cache Missed : cachekey = {cacheKey}"); + + CacheStats.OnMiss(); + + return null; + } + } + + public override async Task> BaseGetAsync(string cacheKey) + { + ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); + + var path = GetRawPath(cacheKey); + + if (!File.Exists(path)) + { + CacheStats.OnMiss(); + + if (_options.EnableLogging) + _logger?.LogInformation($"Cache Missed : cachekey = {cacheKey}"); + + return CacheValue.NoValue; + } + + var cached = await GetDiskCacheValueAsync(path); + + if (cached.Expiration > DateTimeOffset.UtcNow) + { + if (_options.EnableLogging) + _logger?.LogInformation($"Cache Hit : cachekey = {cacheKey}"); + + CacheStats.OnHit(); + + var t = MessagePackSerializer.Deserialize(cached.Value, MessagePack.Resolvers.ContractlessStandardResolver.Instance); + return new CacheValue(t, true); + } + else + { + if (_options.EnableLogging) + _logger?.LogInformation($"Cache Missed : cachekey = {cacheKey}"); + + CacheStats.OnMiss(); + + return CacheValue.NoValue; + } + } + + public override async Task>> BaseGetByPrefixAsync(string prefix) + { + ArgumentCheck.NotNullOrWhiteSpace(prefix, nameof(prefix)); + + IDictionary> dict = new Dictionary>(); + + var list = _cacheKeysMap.Where(x => x.Key.StartsWith(prefix, StringComparison.Ordinal)).Select(x => x.Key).ToList(); + + if (list == null || !list.Any()) return dict; + + foreach (var item in list) + { + var path = GetRawPath(item); + + if (!File.Exists(path)) + { + if (!dict.ContainsKey(item)) + { + dict.Add(item, CacheValue.NoValue); + } + } + else + { + var cached = await GetDiskCacheValueAsync(path); + + if (cached.Expiration > DateTimeOffset.UtcNow) + { + var t = MessagePackSerializer.Deserialize(cached.Value, MessagePack.Resolvers.ContractlessStandardResolver.Instance); + + if (!dict.ContainsKey(item)) + { + dict.Add(item, new CacheValue(t, true)); + } + } + else + { + if (!dict.ContainsKey(item)) + { + dict.Add(item, CacheValue.NoValue); + } + } + } + } + + return dict; + } + + public override async Task BaseGetExpirationAsync(string cacheKey) + { + ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); + + var path = GetRawPath(cacheKey); + + if (!File.Exists(path)) + { + return TimeSpan.Zero; + } + + var cached = await GetDiskCacheValueAsync(path); + + return cached.Expiration.Subtract(DateTimeOffset.UtcNow); + } + + public override Task BaseRemoveAllAsync(IEnumerable cacheKeys) + { + ArgumentCheck.NotNullAndCountGTZero(cacheKeys, nameof(cacheKeys)); + + foreach (string key in cacheKeys) + { + if (string.IsNullOrWhiteSpace(key)) + continue; + + var path = GetRawPath(key); + + if (!File.Exists(path)) + { + continue; + } + + if (DeleteFileWithRetry(path)) + { + _cacheKeysMap.TryRemove(key, out _); + } + } + + return Task.CompletedTask; + } + + public override Task BaseRemoveAsync(string cacheKey) + { + ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); + + var path = GetRawPath(cacheKey); + + if (!File.Exists(path)) + { + return Task.CompletedTask; + //return true; + } + + if (DeleteFileWithRetry(path)) + { + _cacheKeysMap.TryRemove(cacheKey, out _); + } + + return Task.CompletedTask; + } + + public override Task BaseRemoveByPrefixAsync(string prefix) + { + ArgumentCheck.NotNullOrWhiteSpace(prefix, nameof(prefix)); + + var list = _cacheKeysMap.Where(x => x.Key.StartsWith(prefix, StringComparison.Ordinal)).Select(x => x.Key).ToList(); + + foreach (var item in list) + { + var path = BuildMd5Path(item); + + if (DeleteFileWithRetry(path)) + { + _cacheKeysMap.TryRemove(item, out _); + } + } + + return Task.CompletedTask; + } + + public override async Task BaseSetAllAsync(IDictionary values, TimeSpan expiration) + { + ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); + ArgumentCheck.NotNullAndCountGTZero(values, nameof(values)); + + foreach (var item in values) + { + try + { + var (path, fileName) = GetFilePath(item.Key); + + var bytes = BuildDiskCacheValue(item.Value, expiration); + + using (FileStream stream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read)) + { + await stream.WriteAsync(bytes, 0, bytes.Length); + } + + AppendKey(item.Key, fileName); + } + catch + { + + } + } + } + + public override async Task BaseSetAsync(string cacheKey, T cacheValue, TimeSpan expiration) + { + ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); + ArgumentCheck.NotNull(cacheValue, nameof(cacheValue)); + ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); + + var (path, fileName) = GetFilePath(cacheKey); + + var bytes = BuildDiskCacheValue(cacheValue, expiration); + + using (FileStream stream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read)) + { + await stream.WriteAsync(bytes, 0, bytes.Length); + //return true; + } + + AppendKey(cacheKey, fileName); + } + + public override async Task BaseTrySetAsync(string cacheKey, T cacheValue, TimeSpan expiration) + { + ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); + ArgumentCheck.NotNull(cacheValue, nameof(cacheValue)); + ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); + + var (path, fileName) = GetFilePath(cacheKey); + + if (File.Exists(path)) + { + var cached = await GetDiskCacheValueAsync(path); + + if (cached.Expiration.Subtract(DateTimeOffset.UtcNow) > TimeSpan.Zero) + { + return false; + } + } + + var bytes = BuildDiskCacheValue(cacheValue, expiration); + + using (FileStream stream = new FileStream(path, FileMode.CreateNew, FileAccess.Write, FileShare.None)) + { + await stream.WriteAsync(bytes, 0, bytes.Length); + AppendKey(cacheKey, fileName); + return true; + } + } + + private async Task GetDiskCacheValueAsync(string path) + { + using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + { + var cached = await MessagePackSerializer.DeserializeAsync(stream); + + return cached; + } + } + } +} diff --git a/src/EasyCaching.Disk/DefaultDiskCachingProvider.cs b/src/EasyCaching.Disk/DefaultDiskCachingProvider.cs new file mode 100644 index 00000000..abe33712 --- /dev/null +++ b/src/EasyCaching.Disk/DefaultDiskCachingProvider.cs @@ -0,0 +1,649 @@ +namespace EasyCaching.Disk +{ + using System; + using System.Collections.Concurrent; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using System.Security.Cryptography; + using System.Text; + using System.Threading; + using EasyCaching.Core; + using MessagePack; + using Microsoft.Extensions.Logging; + + public partial class DefaultDiskCachingProvider : EasyCachingAbstractProvider + { + /// + /// The options. + /// + private readonly DiskOptions _options; + + /// + /// The logger. + /// + private readonly ILogger _logger; + + /// + /// The cache stats. + /// + private readonly CacheStats _cacheStats; + + /// + /// The name. + /// + private readonly string _name; + + private readonly ConcurrentDictionary _cacheKeysMap; + + private Timer _saveKeyTimer; + + public DefaultDiskCachingProvider(string name, + DiskOptions options, + ILoggerFactory loggerFactory = null) + { + this._name = name; + this._options = options; + this._logger = loggerFactory?.CreateLogger(); + + this._cacheKeysMap = new ConcurrentDictionary(); + + this._cacheStats = new CacheStats(); + + this.ProviderName = _name; + this.ProviderType = CachingProviderType.Disk; + this.ProviderStats = _cacheStats; + this.ProviderMaxRdSecond = _options.MaxRdSecond; + this.IsDistributedProvider = false; + + Init(); + + _saveKeyTimer = new Timer(SaveKeyToFile, null, TimeSpan.FromSeconds(10), TimeSpan.FromMinutes(2)); + } + + private void Init() + { + var md5FolderName = GetMd5Str(_name); + + var basePath = Path.Combine(_options.DBConfig.BasePath, md5FolderName); + + if (!Directory.Exists(basePath)) + { + Directory.CreateDirectory(basePath); + } + + var path = Path.Combine(basePath, $"key.dat"); + + if (!File.Exists(path)) + { + File.Create(path); + } + + InitCacheKey(); + } + + private void SaveKeyToFile(object state) + { + if (!_cacheKeysMap.IsEmpty) + { + var md5FolderName = GetMd5Str(_name); + var path = Path.Combine(_options.DBConfig.BasePath, md5FolderName, $"key.dat"); + + var keys = _cacheKeysMap.Keys.ToArray(); + + var value = string.Join("\n", keys); + + var bytes = Encoding.UTF8.GetBytes(value); + + for (int i = 0; i < 3; i++) + { + try + { + using (FileStream stream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write)) + { + // batch , not all in one + stream.Write(bytes, 0, bytes.Length); + } + + break; + } + catch + { + + } + } + } + } + + private void InitCacheKey() + { + var path = BuildRawPath("key"); + + if (!File.Exists(path)) return; + + for (int i = 0; i < 3; i++) + { + try + { + using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) + { + using (StreamReader reader = new StreamReader(stream, Encoding.UTF8)) + { + string line; + while ((line = reader.ReadLine()) != null) + { + _cacheKeysMap.TryAdd(line, GetMd5Str(line)); + } + } + } + + break; + } + catch + { + + } + } + } + + public override bool BaseExists(string cacheKey) + { + ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); + + var path = BuildMd5Path(cacheKey); + + if (!File.Exists(path)) return false; + + var val = GetDiskCacheValue(path); + + return val.Expiration > DateTimeOffset.UtcNow; + } + + public override void BaseFlush() + { + if (_options.EnableLogging) + _logger?.LogInformation("Flush"); + + var md5FolderName = GetMd5Str(_name); + + var path = Path.Combine(_options.DBConfig.BasePath, md5FolderName); + + DeleteDirectory(path); + + _cacheKeysMap.Clear(); + } + + public override CacheValue BaseGet(string cacheKey, Func dataRetriever, TimeSpan expiration) + { + ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); + ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); + + var path = GetRawPath(cacheKey); + + if (File.Exists(path)) + { + var cached = GetDiskCacheValue(path); + + if (cached.Expiration > DateTimeOffset.UtcNow) + { + var t = MessagePackSerializer.Deserialize(cached.Value, MessagePack.Resolvers.ContractlessStandardResolver.Instance); + + if (_options.EnableLogging) + _logger?.LogInformation($"Cache Hit : cachekey = {cacheKey}"); + + CacheStats.OnHit(); + + return new CacheValue(t, true); + } + } + + CacheStats.OnMiss(); + + if (_options.EnableLogging) + _logger?.LogInformation($"Cache Missed : cachekey = {cacheKey}"); + + // TODO: how to add mutex key here + if (!_cacheKeysMap.TryAdd($"{cacheKey}_Lock", "1")) + { + System.Threading.Thread.Sleep(_options.SleepMs); + return Get(cacheKey, dataRetriever, expiration); + } + + var res = dataRetriever(); + + if (res != null) + { + Set(cacheKey, res, expiration); + // remove mutex key + _cacheKeysMap.TryRemove($"{cacheKey}_Lock", out _); + + return new CacheValue(res, true); + } + else + { + // remove mutex key + _cacheKeysMap.TryRemove($"{cacheKey}_Lock", out _); + return CacheValue.NoValue; + } + } + + public override CacheValue BaseGet(string cacheKey) + { + ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); + + var path = GetRawPath(cacheKey); + + if (!File.Exists(path)) + { + if (_options.EnableLogging) + _logger?.LogInformation($"Cache Missed : cachekey = {cacheKey}"); + + CacheStats.OnMiss(); + + return CacheValue.NoValue; + } + + var cached = GetDiskCacheValue(path); + + if (cached.Expiration > DateTimeOffset.UtcNow) + { + if (_options.EnableLogging) + _logger?.LogInformation($"Cache Hit : cachekey = {cacheKey}"); + + CacheStats.OnHit(); + + var t = MessagePackSerializer.Deserialize(cached.Value, MessagePack.Resolvers.ContractlessStandardResolver.Instance); + return new CacheValue(t, true); + } + else + { + if (_options.EnableLogging) + _logger?.LogInformation($"Cache Missed : cachekey = {cacheKey}"); + + CacheStats.OnMiss(); + + return CacheValue.NoValue; + } + } + + public override IDictionary> BaseGetAll(IEnumerable cacheKeys) + { + ArgumentCheck.NotNullAndCountGTZero(cacheKeys, nameof(cacheKeys)); + + IDictionary> dict = new Dictionary>(); + + foreach (var item in cacheKeys) + { + var path = GetRawPath(item); + + if (!File.Exists(path)) + { + if (!dict.ContainsKey(item)) + { + dict.Add(item, CacheValue.NoValue); + } + } + else + { + var cached = GetDiskCacheValue(path); + + if (cached.Expiration > DateTimeOffset.UtcNow) + { + var t = MessagePackSerializer.Deserialize(cached.Value); + + if (!dict.ContainsKey(item)) + { + dict.Add(item, new CacheValue(t, true)); + } + } + else + { + if (!dict.ContainsKey(item)) + { + dict.Add(item, CacheValue.NoValue); + } + } + } + } + + return dict; + } + + public override IDictionary> BaseGetByPrefix(string prefix) + { + ArgumentCheck.NotNullOrWhiteSpace(prefix, nameof(prefix)); + + IDictionary> dict = new Dictionary>(); + + var list = _cacheKeysMap.Where(x => x.Key.StartsWith(prefix, StringComparison.Ordinal)).Select(x => x.Key).ToList(); + + if (list == null || !list.Any()) return dict; + + foreach (var item in list) + { + var path = GetRawPath(item); + + if (!File.Exists(path)) + { + if (!dict.ContainsKey(item)) + { + dict.Add(item, CacheValue.NoValue); + } + } + else + { + var cached = GetDiskCacheValue(path); + + if (cached.Expiration > DateTimeOffset.UtcNow) + { + var t = MessagePackSerializer.Deserialize(cached.Value); + + if (!dict.ContainsKey(item)) + { + dict.Add(item, new CacheValue(t, true)); + } + } + else + { + if (!dict.ContainsKey(item)) + { + dict.Add(item, CacheValue.NoValue); + } + } + } + } + + return dict; + } + + public override int BaseGetCount(string prefix = "") + { + if (string.IsNullOrWhiteSpace(prefix)) + { + return _cacheKeysMap.Count; + } + else + { + return _cacheKeysMap.Count(x => x.Key.StartsWith(prefix, StringComparison.Ordinal)); + } + } + + public override TimeSpan BaseGetExpiration(string cacheKey) + { + ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); + + var path = GetRawPath(cacheKey); + + if (!File.Exists(path)) + { + return TimeSpan.Zero; + } + + var cached = GetDiskCacheValue(path); + + return cached.Expiration.Subtract(DateTimeOffset.UtcNow); + } + + public override void BaseRemove(string cacheKey) + { + ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); + + var path = GetRawPath(cacheKey); + + if (!File.Exists(path)) + { + return; + //return true; + } + + if (DeleteFileWithRetry(path)) + { + _cacheKeysMap.TryRemove(cacheKey, out _); + } + } + + public override void BaseRemoveAll(IEnumerable cacheKeys) + { + ArgumentCheck.NotNullAndCountGTZero(cacheKeys, nameof(cacheKeys)); + + foreach (string key in cacheKeys) + { + if (string.IsNullOrWhiteSpace(key)) + continue; + + var path = GetRawPath(key); + + if (!File.Exists(path)) + { + continue; + } + + if (DeleteFileWithRetry(path)) + { + _cacheKeysMap.TryRemove(key, out _); + } + } + } + + public override void BaseRemoveByPrefix(string prefix) + { + ArgumentCheck.NotNullOrWhiteSpace(prefix, nameof(prefix)); + + var list = _cacheKeysMap.Where(x => x.Key.StartsWith(prefix, StringComparison.Ordinal)).Select(x => x.Key).ToList(); + + foreach (var item in list) + { + var path = BuildMd5Path(item); + + if (DeleteFileWithRetry(path)) + { + _cacheKeysMap.TryRemove(item, out _); + } + } + } + + public override void BaseSet(string cacheKey, T cacheValue, TimeSpan expiration) + { + ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); + ArgumentCheck.NotNull(cacheValue, nameof(cacheValue)); + ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); + + var (path, fileName) = GetFilePath(cacheKey); + + var bytes = BuildDiskCacheValue(cacheValue, expiration); + + using (FileStream stream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read)) + { + stream.Write(bytes, 0, bytes.Length); + //return true; + } + + AppendKey(cacheKey, fileName); + } + + public override void BaseSetAll(IDictionary values, TimeSpan expiration) + { + ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); + ArgumentCheck.NotNullAndCountGTZero(values, nameof(values)); + + foreach (var item in values) + { + try + { + var (path, fileName) = GetFilePath(item.Key); + + var bytes = BuildDiskCacheValue(item.Value, expiration); + + using (FileStream stream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read)) + { + stream.Write(bytes, 0, bytes.Length); + } + + AppendKey(item.Key, fileName); + } + catch + { + + } + } + } + + public override bool BaseTrySet(string cacheKey, T cacheValue, TimeSpan expiration) + { + ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); + ArgumentCheck.NotNull(cacheValue, nameof(cacheValue)); + ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); + + var (path, fileName) = GetFilePath(cacheKey); + + if (File.Exists(path)) + { + var cached = GetDiskCacheValue(path); + + if (cached.Expiration.Subtract(DateTimeOffset.UtcNow) > TimeSpan.Zero) + { + return false; + } + } + + var bytes = BuildDiskCacheValue(cacheValue, expiration); + + using (FileStream stream = new FileStream(path, FileMode.CreateNew, FileAccess.Write, FileShare.None)) + { + stream.Write(bytes, 0, bytes.Length); + AppendKey(cacheKey, fileName); + return true; + } + } + + private (string path, string md5Name) GetFilePath(string key) + { + var md5FolderName = GetMd5Str(_name); + var md5FileName = GetMd5Str(key); + + var path = Path.Combine(_options.DBConfig.BasePath, md5FolderName, $"{md5FileName}.dat"); + return (path, md5FileName); + } + + private string BuildRawPath(string key) + { + var md5FolderName = GetMd5Str(_name); + + var path = Path.Combine(_options.DBConfig.BasePath, md5FolderName, $"{key}.dat"); + return path; + } + + private string GetRawPath(string cacheKey) + { + var path = string.Empty; + if (_cacheKeysMap.TryGetValue(cacheKey, out var fileName)) + { + path = BuildRawPath(fileName); + } + else + { + path = BuildMd5Path(cacheKey); + } + return path; + } + + + private string BuildMd5Path(string key) + { + var md5FolderName = GetMd5Str(_name); + var md5FileName = GetMd5Str(key); + + var path = Path.Combine(_options.DBConfig.BasePath, md5FolderName, $"{md5FileName}.dat"); + return path; + } + + private bool DeleteFileWithRetry(string path) + { + bool flag = false; + + for (int i = 0; i < 3; i++) + { + try + { + File.Delete(path); + flag = true; + break; + } + catch + { + //return false; + } + } + + return flag; + } + + private DiskCacheValue GetDiskCacheValue(string path) + { + using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + { + var cached = MessagePackSerializer.Deserialize(stream); + + return cached; + } + } + + private void AppendKey(string key, string md5Key) + { + _cacheKeysMap.TryAdd(key, md5Key); + } + + private byte[] BuildDiskCacheValue(T t, TimeSpan ts) + { + var value = MessagePackSerializer.Serialize(t, MessagePack.Resolvers.ContractlessStandardResolver.Instance); + + var cached = new DiskCacheValue(value, DateTimeOffset.UtcNow.AddSeconds((int)ts.TotalSeconds)); + + var bytes = MessagePackSerializer.Serialize(cached); + + return bytes; + } + + private string GetMd5Str(string src) + { + using (MD5 md5 = MD5.Create()) + { + byte[] data = md5.ComputeHash(Encoding.UTF8.GetBytes(src)); + + StringBuilder sBuilder = new StringBuilder(64); + + for (int i = 0; i < data.Length; i++) + { + sBuilder.Append(data[i].ToString("x2")); + } + + return sBuilder.ToString(); + } + } + + private void DeleteDirectory(string path) + { + try + { + DirectoryInfo dir = new DirectoryInfo(path); + FileSystemInfo[] fileinfo = dir.GetFileSystemInfos(); + foreach (FileSystemInfo i in fileinfo) + { + if (i is DirectoryInfo) + { + DirectoryInfo subdir = new DirectoryInfo(i.FullName); + subdir.Delete(true); + } + else + { + File.Delete(i.FullName); + } + } + } + catch + { + + } + } + } +} diff --git a/src/EasyCaching.Disk/EasyCaching.Disk.csproj b/src/EasyCaching.Disk/EasyCaching.Disk.csproj new file mode 100644 index 00000000..6da8b311 --- /dev/null +++ b/src/EasyCaching.Disk/EasyCaching.Disk.csproj @@ -0,0 +1,43 @@ + + + + + netstandard2.0 + ncc;Catcher Wong + ncc;Catcher Wong + $(EasyCachingDiskPackageVersion) + + A simple disk(file) caching provider. + + Disk,File,LocalCache,Caching,Cache + https://github.com/dotnetcore/EasyCaching + LICENSE + https://github.com/dotnetcore/EasyCaching + https://github.com/dotnetcore/EasyCaching + https://raw.githubusercontent.com/dotnetcore/EasyCaching/master/media/nuget-icon.png + + $(EasyCachingDiskPackageNotes) + + + + + true + $(NoWarn);1591 + + + + + + + + + + + + + + + + + + diff --git a/src/EasyCaching.Disk/Internal/DiskCacheValue.cs b/src/EasyCaching.Disk/Internal/DiskCacheValue.cs new file mode 100644 index 00000000..de5e45aa --- /dev/null +++ b/src/EasyCaching.Disk/Internal/DiskCacheValue.cs @@ -0,0 +1,23 @@ +namespace EasyCaching.Disk +{ + using System; + using MessagePack; + + [MessagePackObject] + public class DiskCacheValue + { + [SerializationConstructor] + public DiskCacheValue(byte[] val, DateTimeOffset time) + { + Value = val; + Expiration = time; + } + + + [Key(0)] + public byte[] Value { get; private set; } + + [Key(1)] + public DateTimeOffset Expiration { get; private set; } + } +} diff --git a/src/EasyCaching.Disk/Internal/DiskDbOptions.cs b/src/EasyCaching.Disk/Internal/DiskDbOptions.cs new file mode 100644 index 00000000..b96dbf17 --- /dev/null +++ b/src/EasyCaching.Disk/Internal/DiskDbOptions.cs @@ -0,0 +1,7 @@ +namespace EasyCaching.Disk +{ + public class DiskDbOptions + { + public string BasePath { get; set; } + } +} diff --git a/src/EasyCaching.HybridCache/EasyCaching.HybridCache.csproj b/src/EasyCaching.HybridCache/EasyCaching.HybridCache.csproj index aef405a4..ae6f103b 100644 --- a/src/EasyCaching.HybridCache/EasyCaching.HybridCache.csproj +++ b/src/EasyCaching.HybridCache/EasyCaching.HybridCache.csproj @@ -3,15 +3,15 @@ netstandard2.0 - Catcher Wong - Catcher Wong + ncc;Catcher Wong + ncc;Catcher Wong $(EasyCachingHybridPackageVersion) A simple hybrid caching provider combines local caching and distributed caching. Hybrid,Synchronization,LocalCache,DistributedCache,Caching https://github.com/dotnetcore/EasyCaching - https://github.com/dotnetcore/EasyCaching/blob/master/LICENSE + LICENSE https://github.com/dotnetcore/EasyCaching https://github.com/dotnetcore/EasyCaching https://raw.githubusercontent.com/dotnetcore/EasyCaching/master/media/nuget-icon.png @@ -25,6 +25,10 @@ $(NoWarn);1591 + + + + diff --git a/src/EasyCaching.HybridCache/HybridCachingProvider.cs b/src/EasyCaching.HybridCache/HybridCachingProvider.cs index bd3587ed..d45abfa4 100644 --- a/src/EasyCaching.HybridCache/HybridCachingProvider.cs +++ b/src/EasyCaching.HybridCache/HybridCachingProvider.cs @@ -97,7 +97,7 @@ IOptions optionsAccs retryPolicy = Policy.Handle() .WaitAndRetry(this._options.BusRetryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt - 1))); - fallbackPolicy = Policy.Handle().Fallback(()=> { }); + fallbackPolicy = Policy.Handle().Fallback(() => { }); fallbackAsyncPolicy = Policy.Handle().FallbackAsync(ct => { @@ -443,12 +443,12 @@ public bool TrySet(string cacheKey, T cacheValue, TimeSpan expiration) flag = _localCache.TrySet(cacheKey, cacheValue, expiration); } - if(flag) + if (flag) { // Here should send message to bus due to cache was set successfully. _busSyncWrap.Execute(() => _bus.Publish(_options.TopicName, new EasyCachingMessage { Id = _cacheId, CacheKeys = new string[] { cacheKey } })); } - + return flag; } @@ -490,7 +490,7 @@ public async Task TrySetAsync(string cacheKey, T cacheValue, TimeSpan e flag = await _localCache.TrySetAsync(cacheKey, cacheValue, expiration); } - if(flag) + if (flag) { // Here should send message to bus due to cache was set successfully. await _busAsyncWrap.ExecuteAsync(async () => await _bus.PublishAsync(_options.TopicName, new EasyCachingMessage { Id = _cacheId, CacheKeys = new string[] { cacheKey } })); @@ -727,5 +727,55 @@ private void LogMessage(string message, Exception ex = null) } } } + + public async Task GetAsync(string cacheKey, Type type) + { + ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); + + var cacheValue = await _localCache.GetAsync(cacheKey, type); + + if (cacheValue != null) + { + return cacheValue; + } + + LogMessage($"local cache can not get the value of {cacheKey}"); + + try + { + cacheValue = await _distributedCache.GetAsync(cacheKey, type); + } + catch (Exception ex) + { + LogMessage($"distributed cache get error, [{cacheKey}]", ex); + } + + if (cacheValue != null) + { + TimeSpan ts = TimeSpan.Zero; + + try + { + ts = await _distributedCache.GetExpirationAsync(cacheKey); + } + catch + { + + } + + if (ts <= TimeSpan.Zero) + { + ts = TimeSpan.FromSeconds(_options.DefaultExpirationForTtlFailed); + } + + await _localCache.SetAsync(cacheKey, cacheValue, ts); + + return cacheValue; + } + + LogMessage($"distributed cache can not get the value of {cacheKey}"); + + return null; + } } } diff --git a/src/EasyCaching.InMemory/Configurations/EasyCachingOptionsExtensions.cs b/src/EasyCaching.InMemory/Configurations/EasyCachingOptionsExtensions.cs index 78d37063..2f89af43 100644 --- a/src/EasyCaching.InMemory/Configurations/EasyCachingOptionsExtensions.cs +++ b/src/EasyCaching.InMemory/Configurations/EasyCachingOptionsExtensions.cs @@ -22,10 +22,8 @@ public static EasyCachingOptions UseInMemory(this EasyCachingOptions options, st void configure(InMemoryOptions x) { - x.CachingProviderType = option.CachingProviderType; x.EnableLogging = option.EnableLogging; x.MaxRdSecond = option.MaxRdSecond; - x.Order = option.Order; x.DBConfig = option.DBConfig; } @@ -67,10 +65,8 @@ public static EasyCachingOptions UseInMemory(this EasyCachingOptions options, IC void configure(InMemoryOptions x) { - x.CachingProviderType = memoryOptions.CachingProviderType; x.EnableLogging = memoryOptions.EnableLogging; x.MaxRdSecond = memoryOptions.MaxRdSecond; - x.Order = memoryOptions.Order; x.DBConfig = memoryOptions.DBConfig; } return options.UseInMemory(configure,name); diff --git a/src/EasyCaching.InMemory/Configurations/InMemoryOptions.cs b/src/EasyCaching.InMemory/Configurations/InMemoryOptions.cs index b7c7a4ea..02029952 100644 --- a/src/EasyCaching.InMemory/Configurations/InMemoryOptions.cs +++ b/src/EasyCaching.InMemory/Configurations/InMemoryOptions.cs @@ -7,7 +7,7 @@ public class InMemoryOptions : BaseProviderOptions { public InMemoryOptions() { - this.CachingProviderType = CachingProviderType.InMemory; + } public InMemoryCachingOptions DBConfig { get; set; } = new InMemoryCachingOptions(); diff --git a/src/EasyCaching.InMemory/DefaultInMemoryCachingProvider.cs b/src/EasyCaching.InMemory/DefaultInMemoryCachingProvider.cs index f8a58ff6..83fb40c7 100644 --- a/src/EasyCaching.InMemory/DefaultInMemoryCachingProvider.cs +++ b/src/EasyCaching.InMemory/DefaultInMemoryCachingProvider.cs @@ -58,10 +58,9 @@ public DefaultInMemoryCachingProvider( this._cacheStats = new CacheStats(); this.ProviderName = _name; + this.ProviderType = CachingProviderType.InMemory; this.ProviderStats = _cacheStats; - this.ProviderType = _options.CachingProviderType; this.ProviderMaxRdSecond = _options.MaxRdSecond; - this.ProviderOrder = _options.Order; this.IsDistributedProvider = false; } @@ -371,42 +370,7 @@ public override async Task BaseExistsAsync(string cacheKey) ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); return await Task.FromResult(_cache.Exists(cacheKey)); - } - - /// - /// Refresh the specified cacheKey, cacheValue and expiration. - /// - /// Cache key. - /// Cache value. - /// Expiration. - /// The 1st type parameter. - public override void BaseRefresh(string cacheKey, T cacheValue, TimeSpan expiration) - { - ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); - ArgumentCheck.NotNull(cacheValue, nameof(cacheValue)); - ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); - - this.Remove(cacheKey); - this.Set(cacheKey, cacheValue, expiration); - } - - /// - /// Refreshs the specified cacheKey, cacheValue and expiration. - /// - /// The async. - /// Cache key. - /// Cache value. - /// Expiration. - /// The 1st type parameter. - public override async Task BaseRefreshAsync(string cacheKey, T cacheValue, TimeSpan expiration) - { - ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); - ArgumentCheck.NotNull(cacheValue, nameof(cacheValue)); - ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); - - await this.RemoveAsync(cacheKey); - await this.SetAsync(cacheKey, cacheValue, expiration); - } + } /// /// Removes cached item by cachekey's prefix. diff --git a/src/EasyCaching.InMemory/EasyCaching.InMemory.csproj b/src/EasyCaching.InMemory/EasyCaching.InMemory.csproj index decf6910..b7905d98 100644 --- a/src/EasyCaching.InMemory/EasyCaching.InMemory.csproj +++ b/src/EasyCaching.InMemory/EasyCaching.InMemory.csproj @@ -3,15 +3,15 @@ netstandard2.0 - Catcher Wong - Catcher Wong + ncc;Catcher Wong + ncc;Catcher Wong $(EasyCachingInMemoryPackageVersion) A simple in-memory caching provider. In-Memory,LocalCache,Caching,Cache https://github.com/dotnetcore/EasyCaching - https://github.com/dotnetcore/EasyCaching/blob/master/LICENSE + LICENSE https://github.com/dotnetcore/EasyCaching https://github.com/dotnetcore/EasyCaching https://raw.githubusercontent.com/dotnetcore/EasyCaching/master/media/nuget-icon.png @@ -25,6 +25,10 @@ $(NoWarn);1591 + + + + diff --git a/src/EasyCaching.Interceptor.AspectCore/EasyCaching.Interceptor.AspectCore.csproj b/src/EasyCaching.Interceptor.AspectCore/EasyCaching.Interceptor.AspectCore.csproj index 41b15135..7a05633d 100644 --- a/src/EasyCaching.Interceptor.AspectCore/EasyCaching.Interceptor.AspectCore.csproj +++ b/src/EasyCaching.Interceptor.AspectCore/EasyCaching.Interceptor.AspectCore.csproj @@ -3,15 +3,15 @@ netstandard2.0 - Catcher Wong - Catcher Wong + ncc;Catcher Wong + ncc;Catcher Wong $(EasyCachingAspectCorePackageVersion) A simple caching AOP extension library based on AspectCore Interceptor,AspectCore,AOP,Caching,Cache https://github.com/dotnetcore/EasyCaching - https://github.com/dotnetcore/EasyCaching/blob/master/LICENSE + LICENSE https://github.com/dotnetcore/EasyCaching https://github.com/dotnetcore/EasyCaching https://raw.githubusercontent.com/dotnetcore/EasyCaching/master/media/nuget-icon.png @@ -25,6 +25,10 @@ $(NoWarn);1591 + + + + diff --git a/src/EasyCaching.Interceptor.AspectCore/EasyCachingInterceptor.cs b/src/EasyCaching.Interceptor.AspectCore/EasyCachingInterceptor.cs index 97a94f76..69744367 100644 --- a/src/EasyCaching.Interceptor.AspectCore/EasyCachingInterceptor.cs +++ b/src/EasyCaching.Interceptor.AspectCore/EasyCachingInterceptor.cs @@ -25,6 +25,13 @@ public class EasyCachingInterceptor : AbstractInterceptor [FromContainer] public IEasyCachingProviderFactory CacheProviderFactory { get; set; } + /// + /// Gets or sets the hybrid caching provider. + /// + /// The hybrid caching provider. + [FromContainer] + public IHybridCachingProvider HybridCachingProvider { get; set; } + /// /// Gets or sets the key generator. /// @@ -95,15 +102,22 @@ private async Task ProceedAbleAsync(AspectContext context, AspectDelegate next) var returnType = context.IsAsync() ? context.ServiceMethod.ReturnType.GetGenericArguments().First() : context.ServiceMethod.ReturnType; - - var _cacheProvider = CacheProviderFactory.GetCachingProvider(attribute.CacheProviderName ?? Options.Value.CacheProviderName); + var cacheKey = KeyGenerator.GetCacheKey(context.ServiceMethod, context.Parameters, attribute.CacheKeyPrefix); object cacheValue = null; var isAvailable = true; try { - cacheValue = await _cacheProvider.GetAsync(cacheKey, returnType); + if(attribute.IsHybridProvider) + { + cacheValue = await HybridCachingProvider.GetAsync(cacheKey, returnType); + } + else + { + var _cacheProvider = CacheProviderFactory.GetCachingProvider(attribute.CacheProviderName ?? Options.Value.CacheProviderName); + cacheValue = await _cacheProvider.GetAsync(cacheKey, returnType); + } } catch (Exception ex) { @@ -114,7 +128,7 @@ private async Task ProceedAbleAsync(AspectContext context, AspectDelegate next) else { isAvailable = false; - Logger?.LogError(new EventId(), ex, $"Cache provider \"{_cacheProvider.Name}\" get error."); + Logger?.LogError(new EventId(), ex, $"Cache provider get error."); } } @@ -153,8 +167,16 @@ private async Task ProceedAbleAsync(AspectContext context, AspectDelegate next) // 1. cached a null value for a short time // 2. do nothing if (returnValue != null) - { - await _cacheProvider.SetAsync(cacheKey, returnValue, TimeSpan.FromSeconds(attribute.Expiration)); + { + if (attribute.IsHybridProvider) + { + await HybridCachingProvider.SetAsync(cacheKey, returnValue, TimeSpan.FromSeconds(attribute.Expiration)); + } + else + { + var _cacheProvider = CacheProviderFactory.GetCachingProvider(attribute.CacheProviderName ?? Options.Value.CacheProviderName); + await _cacheProvider.SetAsync(cacheKey, returnValue, TimeSpan.FromSeconds(attribute.Expiration)); + } } } } @@ -175,27 +197,29 @@ private async Task ProcessPutAsync(AspectContext context) { if (GetMethodAttributes(context.ServiceMethod).FirstOrDefault(x => x.GetType() == typeof(EasyCachingPutAttribute)) is EasyCachingPutAttribute attribute && context.ReturnValue != null) { - var _cacheProvider = CacheProviderFactory.GetCachingProvider(attribute.CacheProviderName ?? Options.Value.CacheProviderName); var cacheKey = KeyGenerator.GetCacheKey(context.ServiceMethod, context.Parameters, attribute.CacheKeyPrefix); try - { - if (context.IsAsync()) - { - //get the result - var returnValue = await context.UnwrapAsyncReturnValue(); + { + // get the result + var returnValue = context.IsAsync() + ? await context.UnwrapAsyncReturnValue() + : context.ReturnValue; - await _cacheProvider.SetAsync(cacheKey, returnValue, TimeSpan.FromSeconds(attribute.Expiration)); - } - else - { - await _cacheProvider.SetAsync(cacheKey, context.ReturnValue, TimeSpan.FromSeconds(attribute.Expiration)); + if (attribute.IsHybridProvider) + { + await HybridCachingProvider.SetAsync(cacheKey, returnValue, TimeSpan.FromSeconds(attribute.Expiration)); + } + else + { + var _cacheProvider = CacheProviderFactory.GetCachingProvider(attribute.CacheProviderName ?? Options.Value.CacheProviderName); + await _cacheProvider.SetAsync(cacheKey, returnValue, TimeSpan.FromSeconds(attribute.Expiration)); } } catch (Exception ex) { if (!attribute.IsHighAvailability) throw; - else Logger?.LogError(new EventId(), ex, $"Cache provider \"{_cacheProvider.Name}\" set error."); + else Logger?.LogError(new EventId(), ex, $"Cache provider set error."); } } } @@ -210,28 +234,43 @@ private async Task ProcessEvictAsync(AspectContext context, bool isBefore) { if (GetMethodAttributes(context.ServiceMethod).FirstOrDefault(x => x.GetType() == typeof(EasyCachingEvictAttribute)) is EasyCachingEvictAttribute attribute && attribute.IsBefore == isBefore) { - var _cacheProvider = CacheProviderFactory.GetCachingProvider(attribute.CacheProviderName ?? Options.Value.CacheProviderName); try { if (attribute.IsAll) { - //If is all , clear all cached items which cachekey start with the prefix. + // If is all , clear all cached items which cachekey start with the prefix. var cachePrefix = KeyGenerator.GetCacheKeyPrefix(context.ServiceMethod, attribute.CacheKeyPrefix); - await _cacheProvider.RemoveByPrefixAsync(cachePrefix); + if (attribute.IsHybridProvider) + { + await HybridCachingProvider.RemoveByPrefixAsync(cachePrefix); + } + else + { + var _cacheProvider = CacheProviderFactory.GetCachingProvider(attribute.CacheProviderName ?? Options.Value.CacheProviderName); + await _cacheProvider.RemoveByPrefixAsync(cachePrefix); + } } else { - //If not all , just remove the cached item by its cachekey. + // If not all , just remove the cached item by its cachekey. var cacheKey = KeyGenerator.GetCacheKey(context.ServiceMethod, context.Parameters, attribute.CacheKeyPrefix); - await _cacheProvider.RemoveAsync(cacheKey); + if (attribute.IsHybridProvider) + { + await HybridCachingProvider.RemoveAsync(cacheKey); + } + else + { + var _cacheProvider = CacheProviderFactory.GetCachingProvider(attribute.CacheProviderName ?? Options.Value.CacheProviderName); + await _cacheProvider.RemoveAsync(cacheKey); + } } } catch (Exception ex) { if (!attribute.IsHighAvailability) throw; - else Logger?.LogError(new EventId(), ex, $"Cache provider \"{_cacheProvider.Name}\" remove error."); + else Logger?.LogError(new EventId(), ex, $"Cache provider remove error."); } } } diff --git a/src/EasyCaching.Interceptor.Castle/EasyCaching.Interceptor.Castle.csproj b/src/EasyCaching.Interceptor.Castle/EasyCaching.Interceptor.Castle.csproj index e90942c5..dcc7209a 100644 --- a/src/EasyCaching.Interceptor.Castle/EasyCaching.Interceptor.Castle.csproj +++ b/src/EasyCaching.Interceptor.Castle/EasyCaching.Interceptor.Castle.csproj @@ -3,15 +3,15 @@ netstandard2.0 - Catcher Wong - Catcher Wong + ncc;Catcher Wong + ncc;Catcher Wong $(EasyCachingCastlePackageVersion) A simple caching AOP extension library based on Castle Interceptor,Castle,AOP,Caching,Cache https://github.com/dotnetcore/EasyCaching - https://github.com/dotnetcore/EasyCaching/blob/master/LICENSE + LICENSE https://github.com/dotnetcore/EasyCaching https://github.com/dotnetcore/EasyCaching https://raw.githubusercontent.com/dotnetcore/EasyCaching/master/media/nuget-icon.png @@ -25,6 +25,10 @@ $(NoWarn);1591 + + + + diff --git a/src/EasyCaching.Interceptor.Castle/EasyCachingInterceptor.cs b/src/EasyCaching.Interceptor.Castle/EasyCachingInterceptor.cs index b3eb2f11..6e666f18 100644 --- a/src/EasyCaching.Interceptor.Castle/EasyCachingInterceptor.cs +++ b/src/EasyCaching.Interceptor.Castle/EasyCachingInterceptor.cs @@ -27,6 +27,11 @@ public class EasyCachingInterceptor : IInterceptor /// private readonly IEasyCachingProviderFactory _cacheProviderFactory; + /// + /// The hybrid caching provider. + /// + public IHybridCachingProvider _hybridCachingProvider; + /// /// Get or set the options /// @@ -54,13 +59,20 @@ private static readonly ConcurrentDictionary /// Cache provider factory. /// Key generator. /// Options. - /// logger - public EasyCachingInterceptor(IEasyCachingProviderFactory cacheProviderFactory, IEasyCachingKeyGenerator keyGenerator, IOptions options, ILogger logger = null) + /// Logger. + /// Hybrid caching provider. + public EasyCachingInterceptor( + IEasyCachingProviderFactory cacheProviderFactory + , IEasyCachingKeyGenerator keyGenerator + , IOptions options + , ILogger logger = null + , IHybridCachingProvider hybridCachingProvider = null) { _options = options; _cacheProviderFactory = cacheProviderFactory; _keyGenerator = keyGenerator; _logger = logger; + _hybridCachingProvider = hybridCachingProvider; } /// @@ -100,15 +112,22 @@ private void ProceedAble(IInvocation invocation) var returnType = serviceMethod.IsReturnTask() ? serviceMethod.ReturnType.GetGenericArguments().First() : serviceMethod.ReturnType; - - var _cacheProvider = _cacheProviderFactory.GetCachingProvider(attribute.CacheProviderName ?? _options.Value.CacheProviderName); + var cacheKey = _keyGenerator.GetCacheKey(serviceMethod, invocation.Arguments, attribute.CacheKeyPrefix); object cacheValue = null; var isAvailable = true; try { - cacheValue = (_cacheProvider.GetAsync(cacheKey, returnType)).GetAwaiter().GetResult(); + if (attribute.IsHybridProvider) + { + cacheValue = _hybridCachingProvider.GetAsync(cacheKey, returnType).GetAwaiter().GetResult(); + } + else + { + var _cacheProvider = _cacheProviderFactory.GetCachingProvider(attribute.CacheProviderName ?? _options.Value.CacheProviderName); + cacheValue = _cacheProvider.GetAsync(cacheKey, returnType).GetAwaiter().GetResult(); + } } catch (Exception ex) { @@ -119,7 +138,7 @@ private void ProceedAble(IInvocation invocation) else { isAvailable = false; - _logger?.LogError(new EventId(), ex, $"Cache provider \"{_cacheProvider.Name}\" get error."); + _logger?.LogError(new EventId(), ex, $"Cache provider get error."); } } @@ -152,7 +171,15 @@ private void ProceedAble(IInvocation invocation) // 2. do nothing if (returnValue != null) { - _cacheProvider.Set(cacheKey, returnValue, TimeSpan.FromSeconds(attribute.Expiration)); + if (attribute.IsHybridProvider) + { + _hybridCachingProvider.Set(cacheKey, returnValue, TimeSpan.FromSeconds(attribute.Expiration)); + } + else + { + var _cacheProvider = _cacheProviderFactory.GetCachingProvider(attribute.CacheProviderName ?? _options.Value.CacheProviderName); + _cacheProvider.Set(cacheKey, returnValue, TimeSpan.FromSeconds(attribute.Expiration)); + } } } } @@ -174,27 +201,28 @@ private void ProcessPut(IInvocation invocation) if (GetMethodAttributes(serviceMethod).FirstOrDefault(x => x.GetType() == typeof(EasyCachingPutAttribute)) is EasyCachingPutAttribute attribute && invocation.ReturnValue != null) { - var _cacheProvider = _cacheProviderFactory.GetCachingProvider(attribute.CacheProviderName ?? _options.Value.CacheProviderName); var cacheKey = _keyGenerator.GetCacheKey(serviceMethod, invocation.Arguments, attribute.CacheKeyPrefix); try { - if (serviceMethod.IsReturnTask()) - { - //get the result - var returnValue = invocation.UnwrapAsyncReturnValue().Result; + var returnValue = serviceMethod.IsReturnTask() + ? invocation.UnwrapAsyncReturnValue().Result + : invocation.ReturnValue; - _cacheProvider.Set(cacheKey, returnValue, TimeSpan.FromSeconds(attribute.Expiration)); + if (attribute.IsHybridProvider) + { + _hybridCachingProvider.Set(cacheKey, returnValue, TimeSpan.FromSeconds(attribute.Expiration)); } else { - _cacheProvider.Set(cacheKey, invocation.ReturnValue, TimeSpan.FromSeconds(attribute.Expiration)); + var _cacheProvider = _cacheProviderFactory.GetCachingProvider(attribute.CacheProviderName ?? _options.Value.CacheProviderName); + _cacheProvider.Set(cacheKey, returnValue, TimeSpan.FromSeconds(attribute.Expiration)); } } catch (Exception ex) { if (!attribute.IsHighAvailability) throw; - else _logger?.LogError(new EventId(), ex, $"Cache provider \"{_cacheProvider.Name}\" set error."); + else _logger?.LogError(new EventId(), ex, $"Cache provider set error."); } } } @@ -210,7 +238,6 @@ private void ProcessEvict(IInvocation invocation, bool isBefore) if (GetMethodAttributes(serviceMethod).FirstOrDefault(x => x.GetType() == typeof(EasyCachingEvictAttribute)) is EasyCachingEvictAttribute attribute && attribute.IsBefore == isBefore) { - var _cacheProvider = _cacheProviderFactory.GetCachingProvider(attribute.CacheProviderName ?? _options.Value.CacheProviderName); try { if (attribute.IsAll) @@ -218,20 +245,36 @@ private void ProcessEvict(IInvocation invocation, bool isBefore) //If is all , clear all cached items which cachekey start with the prefix. var cacheKeyPrefix = _keyGenerator.GetCacheKeyPrefix(serviceMethod, attribute.CacheKeyPrefix); - _cacheProvider.RemoveByPrefix(cacheKeyPrefix); + if (attribute.IsHybridProvider) + { + _hybridCachingProvider.RemoveByPrefix(cacheKeyPrefix); + } + else + { + var _cacheProvider = _cacheProviderFactory.GetCachingProvider(attribute.CacheProviderName ?? _options.Value.CacheProviderName); + _cacheProvider.RemoveByPrefix(cacheKeyPrefix); + } } else { //If not all , just remove the cached item by its cachekey. var cacheKey = _keyGenerator.GetCacheKey(serviceMethod, invocation.Arguments, attribute.CacheKeyPrefix); - _cacheProvider.Remove(cacheKey); + if (attribute.IsHybridProvider) + { + _hybridCachingProvider.Remove(cacheKey); + } + else + { + var _cacheProvider = _cacheProviderFactory.GetCachingProvider(attribute.CacheProviderName ?? _options.Value.CacheProviderName); + _cacheProvider.Remove(cacheKey); + } } } catch (Exception ex) { if (!attribute.IsHighAvailability) throw; - else _logger?.LogError(new EventId(), ex, $"Cache provider \"{_cacheProvider.Name}\" remove error."); + else _logger?.LogError(new EventId(), ex, $"Cache provider remove error."); } } } diff --git a/src/EasyCaching.Memcached/Configurations/EasyCachingMemcachedClientConfiguration.cs b/src/EasyCaching.Memcached/Configurations/EasyCachingMemcachedClientConfiguration.cs index 91838189..1e0c9be4 100644 --- a/src/EasyCaching.Memcached/Configurations/EasyCachingMemcachedClientConfiguration.cs +++ b/src/EasyCaching.Memcached/Configurations/EasyCachingMemcachedClientConfiguration.cs @@ -2,13 +2,14 @@ { using System; using System.Collections.Generic; + using System.Linq; using System.Net; + using System.Net.Sockets; using Enyim.Caching.Configuration; using Enyim.Caching.Memcached; using Enyim.Caching.Memcached.Protocol.Binary; using Enyim.Reflection; using Microsoft.Extensions.Logging; - using Microsoft.Extensions.Options; public class EasyCachingMemcachedClientConfiguration : IMemcachedClientConfiguration { @@ -18,12 +19,12 @@ public class EasyCachingMemcachedClientConfiguration : IMemcachedClientConfigura private IMemcachedKeyTransformer _keyTransformer; private ILogger _logger; private string _name; - + public EasyCachingMemcachedClientConfiguration( string name, ILoggerFactory loggerFactory, MemcachedOptions optionsAccessor, - ITranscoder transcoder = null, + IEnumerable transcoders = null, IMemcachedKeyTransformer keyTransformer = null) { this._name = name; @@ -35,11 +36,8 @@ public EasyCachingMemcachedClientConfiguration( _logger = loggerFactory.CreateLogger(); var options = optionsAccessor.DBConfig; - Servers = new List(); - foreach (var server in options.Servers) - { - Servers.Add(new DnsEndPoint(server.Address, server.Port)); - } + + ConfigureServers(options); SocketPool = new SocketPoolConfiguration(); if (options.SocketPool != null) @@ -64,6 +62,8 @@ public EasyCachingMemcachedClientConfiguration( SocketPool.QueueTimeout = options.SocketPool.QueueTimeout; _logger.LogInformation($"{nameof(SocketPool.QueueTimeout)}: {SocketPool.QueueTimeout}"); + + SocketPool.InitPoolTimeout = options.SocketPool.InitPoolTimeout; } Protocol = options.Protocol; @@ -107,10 +107,15 @@ public EasyCachingMemcachedClientConfiguration( NodeLocator = options.Servers.Count > 1 ? typeof(DefaultNodeLocator) : typeof(SingleNodeLocator); } - if (transcoder != null) + if (transcoders != null) { - this._transcoder = transcoder; - _logger.LogDebug($"Use Transcoder Type : '{transcoder.ToString()}'"); + var coder = transcoders.FirstOrDefault(x => x.Name.Equals(_name)); + + if (coder != null) + { + this._transcoder = coder; + _logger.LogDebug($"Use Transcoder Type : '{coder.ToString()}'"); + } } if (options.NodeLocatorFactory != null) @@ -119,23 +124,32 @@ public EasyCachingMemcachedClientConfiguration( } } - /// - /// Adds a new server to the pool. - /// - /// The address and the port of the server in the format 'host:port'. - public void AddServer(string address) + private void ConfigureServers(EasyCachingMemcachedClientOptions options) { - this.Servers.Add(ConfigurationHelper.ResolveToEndPoint(address)); - } + Servers = new List(); + foreach (var server in options.Servers) + { + if (!IPAddress.TryParse(server.Address, out var address)) + { + address = Dns.GetHostAddresses(server.Address) + .FirstOrDefault(i => i.AddressFamily == AddressFamily.InterNetwork); - /// - /// Adds the server. - /// - /// Host. - /// Port. - public void AddServer(string host, int port) - { - this.Servers.Add(new DnsEndPoint(host, port)); + if (address == null) + { + _logger.LogError($"Could not resolve host '{server.Address}'."); + } + else + { + _logger.LogInformation($"Memcached server address - {address}"); + } + } + else + { + _logger.LogInformation($"Memcached server address - {server.Address }:{server.Port}"); + } + + Servers.Add(new IPEndPoint(address, server.Port)); + } } /// @@ -147,7 +161,7 @@ public void AddServer(string host, int port) /// /// Gets a list of each representing a Memcached server in the pool. /// - public IList Servers { get; private set; } + public IList Servers { get; private set; } /// /// Gets the configuration of the socket pool. @@ -204,7 +218,7 @@ public ITranscoder Transcoder #region [ interface ] - IList IMemcachedClientConfiguration.Servers + IList IMemcachedClientConfiguration.Servers { get { return this.Servers; } } diff --git a/src/EasyCaching.Memcached/Configurations/EasyCachingOptionsExtensions.cs b/src/EasyCaching.Memcached/Configurations/EasyCachingOptionsExtensions.cs index eaee4b59..c425b0b1 100644 --- a/src/EasyCaching.Memcached/Configurations/EasyCachingOptionsExtensions.cs +++ b/src/EasyCaching.Memcached/Configurations/EasyCachingOptionsExtensions.cs @@ -44,10 +44,8 @@ public static EasyCachingOptions UseMemcached(this EasyCachingOptions options, I void configure(MemcachedOptions x) { - x.CachingProviderType = mOptions.CachingProviderType; x.EnableLogging = mOptions.EnableLogging; x.MaxRdSecond = mOptions.MaxRdSecond; - x.Order = mOptions.Order; x.DBConfig = mOptions.DBConfig; } diff --git a/src/EasyCaching.Memcached/Configurations/EasyCachingTranscoder.cs b/src/EasyCaching.Memcached/Configurations/EasyCachingTranscoder.cs index 74d5a54c..d16c1ce1 100755 --- a/src/EasyCaching.Memcached/Configurations/EasyCachingTranscoder.cs +++ b/src/EasyCaching.Memcached/Configurations/EasyCachingTranscoder.cs @@ -1,28 +1,43 @@ namespace EasyCaching.Memcached { + using System; + using System.Collections.Generic; + using System.Linq; using EasyCaching.Core; using EasyCaching.Core.Serialization; using Enyim.Caching.Memcached; - using System; - + /// /// EasyCaching transcoder. /// public class EasyCachingTranscoder : DefaultTranscoder - { + { + /// + /// The name. + /// + private readonly string _name; + /// /// The serializer. /// private readonly IEasyCachingSerializer _serializer; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// Serializer. - public EasyCachingTranscoder(IEasyCachingSerializer serializer) + /// Name. + /// Serializers. + public EasyCachingTranscoder(string name, IEnumerable serializers) { - this._serializer = serializer; - } + this._name = name; + this._serializer = serializers.FirstOrDefault(x => x.Name.Equals(_name)) ?? serializers.Single(x => x.Name.Equals(EasyCachingConstValue.DefaultSerializerName)); + } + + /// + /// Gets the name. + /// + /// The name. + public string Name => _name; /// /// Serializes the object. diff --git a/src/EasyCaching.Memcached/Configurations/MemcachedOptions.cs b/src/EasyCaching.Memcached/Configurations/MemcachedOptions.cs index 53d032ed..812536b0 100644 --- a/src/EasyCaching.Memcached/Configurations/MemcachedOptions.cs +++ b/src/EasyCaching.Memcached/Configurations/MemcachedOptions.cs @@ -7,7 +7,7 @@ public class MemcachedOptions : BaseProviderOptions { public MemcachedOptions() { - this.CachingProviderType = CachingProviderType.Memcached; + } public EasyCachingMemcachedClientOptions DBConfig { get; set; } = new EasyCachingMemcachedClientOptions(); diff --git a/src/EasyCaching.Memcached/Configurations/MemcachedOptionsExtension.cs b/src/EasyCaching.Memcached/Configurations/MemcachedOptionsExtension.cs index 8386200c..be5664d4 100644 --- a/src/EasyCaching.Memcached/Configurations/MemcachedOptionsExtension.cs +++ b/src/EasyCaching.Memcached/Configurations/MemcachedOptionsExtension.cs @@ -49,17 +49,21 @@ public void AddServices(IServiceCollection services) services.Configure(_name, configure); services.TryAddSingleton(); - services.TryAddSingleton(); services.TryAddSingleton(); services.TryAddSingleton(); + services.AddSingleton(x => + { + var serializers = x.GetServices(); + return new EasyCachingTranscoder(_name, serializers); + }); services.AddSingleton(x => { var optionsMon = x.GetRequiredService>(); var options = optionsMon.Get(_name); var loggerFactory = x.GetRequiredService(); - var transcoder = x.GetRequiredService(); + var transcoders = x.GetServices(); var transformer = x.GetRequiredService(); - return new EasyCachingMemcachedClientConfiguration(_name, loggerFactory, options, transcoder, transformer); + return new EasyCachingMemcachedClientConfiguration(_name, loggerFactory, options, transcoders, transformer); }); services.AddSingleton(x => @@ -96,7 +100,7 @@ public void WithServices(IApplicationBuilder app) client.GetAsync("EnyimMemcached").Wait(); } app.ApplicationServices.GetService>() - .LogInformation(new EventId(), "EnyimMemcached Started."); + .LogInformation(new EventId(), "EnyimMemcached Started."); } catch (Exception ex) { diff --git a/src/EasyCaching.Memcached/DefaultMemcachedCachingProvider.cs b/src/EasyCaching.Memcached/DefaultMemcachedCachingProvider.cs index 542f58f4..089334a7 100644 --- a/src/EasyCaching.Memcached/DefaultMemcachedCachingProvider.cs +++ b/src/EasyCaching.Memcached/DefaultMemcachedCachingProvider.cs @@ -60,9 +60,8 @@ public DefaultMemcachedCachingProvider( this._cacheStats = new CacheStats(); this.ProviderName = this._name; + this.ProviderType = CachingProviderType.Memcached; this.ProviderStats = this._cacheStats; - this.ProviderType = _options.CachingProviderType; - this.ProviderOrder = _options.Order; this.ProviderMaxRdSecond = _options.MaxRdSecond; this.IsDistributedProvider = true; } @@ -353,42 +352,7 @@ public override async Task BaseExistsAsync(string cacheKey) return await Task.FromResult(_memcachedClient.TryGet(this.HandleCacheKey(cacheKey), out object obj)); } - - /// - /// Refresh the specified cacheKey, cacheValue and expiration. - /// - /// Cache key. - /// Cache value. - /// Expiration. - /// The 1st type parameter. - public override void BaseRefresh(string cacheKey, T cacheValue, TimeSpan expiration) - { - ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); - ArgumentCheck.NotNull(cacheValue, nameof(cacheValue)); - ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); - - this.Remove(cacheKey); - this.Set(cacheKey, cacheValue, expiration); - } - - /// - /// Refreshs the specified cacheKey, cacheValue and expiration. - /// - /// The async. - /// Cache key. - /// Cache value. - /// Expiration. - /// The 1st type parameter. - public override async Task BaseRefreshAsync(string cacheKey, T cacheValue, TimeSpan expiration) - { - ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); - ArgumentCheck.NotNull(cacheValue, nameof(cacheValue)); - ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); - - await this.RemoveAsync(cacheKey); - await this.SetAsync(cacheKey, cacheValue, expiration); - } - + /// /// Removes cached item by cachekey's prefix. /// diff --git a/src/EasyCaching.Memcached/EasyCaching.Memcached.csproj b/src/EasyCaching.Memcached/EasyCaching.Memcached.csproj index 06b46b56..3b0ed74d 100644 --- a/src/EasyCaching.Memcached/EasyCaching.Memcached.csproj +++ b/src/EasyCaching.Memcached/EasyCaching.Memcached.csproj @@ -3,15 +3,15 @@ netstandard2.0 - Catcher Wong - Catcher Wong + ncc;Catcher Wong + ncc;Catcher Wong $(EasyCachingMemcachedPackageVersion) A simple distributed caching provider based on EnyimMemcachedCore. Memcached,DistributedCache,Caching,Cache https://github.com/dotnetcore/EasyCaching - https://github.com/dotnetcore/EasyCaching/blob/master/LICENSE + LICENSE https://github.com/dotnetcore/EasyCaching https://github.com/dotnetcore/EasyCaching https://raw.githubusercontent.com/dotnetcore/EasyCaching/master/media/nuget-icon.png @@ -25,11 +25,15 @@ $(NoWarn);1591 + + + + - + diff --git a/src/EasyCaching.Redis/Configurations/EasyCachingOptionsExtensions.cs b/src/EasyCaching.Redis/Configurations/EasyCachingOptionsExtensions.cs index a0c494ba..c7d2d6d7 100644 --- a/src/EasyCaching.Redis/Configurations/EasyCachingOptionsExtensions.cs +++ b/src/EasyCaching.Redis/Configurations/EasyCachingOptionsExtensions.cs @@ -44,10 +44,8 @@ public static EasyCachingOptions UseRedis(this EasyCachingOptions options, IConf void configure(RedisOptions x) { - x.CachingProviderType = redisOptions.CachingProviderType; x.EnableLogging = redisOptions.EnableLogging; - x.MaxRdSecond = redisOptions.MaxRdSecond; - x.Order = redisOptions.Order; + x.MaxRdSecond = redisOptions.MaxRdSecond; x.DBConfig = redisOptions.DBConfig; } diff --git a/src/EasyCaching.Redis/Configurations/RedisOptions.cs b/src/EasyCaching.Redis/Configurations/RedisOptions.cs index 887118f2..278db56e 100644 --- a/src/EasyCaching.Redis/Configurations/RedisOptions.cs +++ b/src/EasyCaching.Redis/Configurations/RedisOptions.cs @@ -7,7 +7,7 @@ public class RedisOptions: BaseProviderOptions { public RedisOptions() { - this.CachingProviderType = CachingProviderType.Redis; + } public RedisDBOptions DBConfig { get; set; } = new RedisDBOptions(); diff --git a/src/EasyCaching.Redis/Configurations/RedisOptionsExtension.cs b/src/EasyCaching.Redis/Configurations/RedisOptionsExtension.cs index c9548d50..8cfcfe62 100755 --- a/src/EasyCaching.Redis/Configurations/RedisOptionsExtension.cs +++ b/src/EasyCaching.Redis/Configurations/RedisOptionsExtension.cs @@ -58,11 +58,11 @@ public void AddServices(IServiceCollection services) Func createFactory = x => { var dbProviders = x.GetServices(); - var serializer = x.GetRequiredService(); + var serializers = x.GetServices(); var optionsMon = x.GetRequiredService>(); var options = optionsMon.Get(_name); var factory = x.GetService(); - return new DefaultRedisCachingProvider(_name, dbProviders, serializer, options, factory); + return new DefaultRedisCachingProvider(_name, dbProviders, serializers, options, factory); }; services.AddSingleton(createFactory); diff --git a/src/EasyCaching.Redis/DefaultRedisCachingProvider.cs b/src/EasyCaching.Redis/DefaultRedisCachingProvider.cs index 44c70210..4c40e2dc 100755 --- a/src/EasyCaching.Redis/DefaultRedisCachingProvider.cs +++ b/src/EasyCaching.Redis/DefaultRedisCachingProvider.cs @@ -60,32 +60,31 @@ public partial class DefaultRedisCachingProvider : EasyCachingAbstractProvider /// /// Name. /// Db providers. - /// Serializer. + /// Serializers. /// Options. /// Logger factory. public DefaultRedisCachingProvider( string name, IEnumerable dbProviders, - IEasyCachingSerializer serializer, + IEnumerable serializers, RedisOptions options, ILoggerFactory loggerFactory = null) { ArgumentCheck.NotNullAndCountGTZero(dbProviders, nameof(dbProviders)); - ArgumentCheck.NotNull(serializer, nameof(serializer)); + ArgumentCheck.NotNullAndCountGTZero(serializers, nameof(serializers)); + this._name = name; this._dbProvider = dbProviders.Single(x => x.DBProviderName.Equals(name)); - this._serializer = serializer; + this._serializer = serializers.FirstOrDefault(x => x.Name.Equals(_name)) ?? serializers.Single(x => x.Name.Equals(EasyCachingConstValue.DefaultSerializerName)); this._options = options; this._logger = loggerFactory?.CreateLogger(); this._cache = _dbProvider.GetDatabase(); this._servers = _dbProvider.GetServerList(); this._cacheStats = new CacheStats(); - this._name = name; this.ProviderName = this._name; + this.ProviderType = CachingProviderType.Redis; this.ProviderStats = this._cacheStats; - this.ProviderType = _options.CachingProviderType; - this.ProviderOrder = _options.Order; this.ProviderMaxRdSecond = _options.MaxRdSecond; this.IsDistributedProvider = true; } @@ -393,41 +392,6 @@ public override async Task BaseExistsAsync(string cacheKey) return await _cache.KeyExistsAsync(cacheKey); } - /// - /// Refresh the specified cacheKey, cacheValue and expiration. - /// - /// Cache key. - /// Cache value. - /// Expiration. - /// The 1st type parameter. - public override void BaseRefresh(string cacheKey, T cacheValue, TimeSpan expiration) - { - ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); - ArgumentCheck.NotNull(cacheValue, nameof(cacheValue)); - ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); - - this.Remove(cacheKey); - this.Set(cacheKey, cacheValue, expiration); - } - - /// - /// Refreshs the specified cacheKey, cacheValue and expiration. - /// - /// The async. - /// Cache key. - /// Cache value. - /// Expiration. - /// The 1st type parameter. - public override async Task BaseRefreshAsync(string cacheKey, T cacheValue, TimeSpan expiration) - { - ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); - ArgumentCheck.NotNull(cacheValue, nameof(cacheValue)); - ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); - - await this.RemoveAsync(cacheKey); - await this.SetAsync(cacheKey, cacheValue, expiration); - } - /// /// Removes cached item by cachekey's prefix. /// diff --git a/src/EasyCaching.Redis/EasyCaching.Redis.csproj b/src/EasyCaching.Redis/EasyCaching.Redis.csproj index 93dea6df..ed56f8ab 100644 --- a/src/EasyCaching.Redis/EasyCaching.Redis.csproj +++ b/src/EasyCaching.Redis/EasyCaching.Redis.csproj @@ -3,15 +3,15 @@ netstandard2.0 - Catcher Wong - Catcher Wong + ncc;Catcher Wong + ncc;Catcher Wong $(EasyCachingRedisPackageVersion) A simple distributed caching provider based on StackExchange.Redis. Redis,DistributedCache,Caching,Cache https://github.com/dotnetcore/EasyCaching - https://github.com/dotnetcore/EasyCaching/blob/master/LICENSE + LICENSE https://github.com/dotnetcore/EasyCaching https://github.com/dotnetcore/EasyCaching https://raw.githubusercontent.com/dotnetcore/EasyCaching/master/media/nuget-icon.png @@ -25,6 +25,10 @@ $(NoWarn);1591 + + + + diff --git a/src/EasyCaching.ResponseCaching/EasyCaching.ResponseCaching.csproj b/src/EasyCaching.ResponseCaching/EasyCaching.ResponseCaching.csproj index b48d8e02..b25771d4 100644 --- a/src/EasyCaching.ResponseCaching/EasyCaching.ResponseCaching.csproj +++ b/src/EasyCaching.ResponseCaching/EasyCaching.ResponseCaching.csproj @@ -3,15 +3,15 @@ netstandard2.0 - Catcher Wong - Catcher Wong + ncc;Catcher Wong + ncc;Catcher Wong $(EasyCachingResponseCachingPackageVersion) EasyCaching.ResponseCaching is the extension of ResponseCaching Caching,Cache,ResponseCaching https://github.com/dotnetcore/EasyCaching - https://github.com/dotnetcore/EasyCaching/blob/master/LICENSE + LICENSE https://github.com/dotnetcore/EasyCaching https://github.com/dotnetcore/EasyCaching https://raw.githubusercontent.com/dotnetcore/EasyCaching/master/media/nuget-icon.png @@ -25,6 +25,10 @@ $(NoWarn);1591 + + + + diff --git a/src/EasyCaching.SQLite/Configurations/EasyCachingOptionsExtensions.cs b/src/EasyCaching.SQLite/Configurations/EasyCachingOptionsExtensions.cs index 0172dbc6..ac723fa5 100644 --- a/src/EasyCaching.SQLite/Configurations/EasyCachingOptionsExtensions.cs +++ b/src/EasyCaching.SQLite/Configurations/EasyCachingOptionsExtensions.cs @@ -44,10 +44,8 @@ public static EasyCachingOptions UseSQLite(this EasyCachingOptions options, ICon void configure(SQLiteOptions x) { - x.CachingProviderType = sqliteOptions.CachingProviderType; x.EnableLogging = sqliteOptions.EnableLogging; - x.MaxRdSecond = sqliteOptions.MaxRdSecond; - x.Order = sqliteOptions.Order; + x.MaxRdSecond = sqliteOptions.MaxRdSecond; x.DBConfig = sqliteOptions.DBConfig; } diff --git a/src/EasyCaching.SQLite/Configurations/SQLiteOptions.cs b/src/EasyCaching.SQLite/Configurations/SQLiteOptions.cs index bade09e0..e7ee00b0 100644 --- a/src/EasyCaching.SQLite/Configurations/SQLiteOptions.cs +++ b/src/EasyCaching.SQLite/Configurations/SQLiteOptions.cs @@ -7,7 +7,7 @@ public class SQLiteOptions: BaseProviderOptions { public SQLiteOptions() { - this.CachingProviderType = CachingProviderType.SQLite; + } public SQLiteDBOptions DBConfig { get; set; } = new SQLiteDBOptions(); diff --git a/src/EasyCaching.SQLite/DefaultSQLiteCachingProvider.cs b/src/EasyCaching.SQLite/DefaultSQLiteCachingProvider.cs index 205ee138..e52ddb0d 100644 --- a/src/EasyCaching.SQLite/DefaultSQLiteCachingProvider.cs +++ b/src/EasyCaching.SQLite/DefaultSQLiteCachingProvider.cs @@ -59,9 +59,8 @@ public DefaultSQLiteCachingProvider( this._name = name; this.ProviderName = this._name; + this.ProviderType = CachingProviderType.SQLite; this.ProviderStats = this._cacheStats; - this.ProviderType = _options.CachingProviderType; - this.ProviderOrder = _options.Order; this.ProviderMaxRdSecond = _options.MaxRdSecond; this.IsDistributedProvider = true; } @@ -390,42 +389,7 @@ public override async Task BaseSetAsync(string cacheKey, T cacheValue, TimeSp cachevalue = Newtonsoft.Json.JsonConvert.SerializeObject(cacheValue), expiration = expiration.Ticks / 10000000 }); - } - - /// - /// Refresh the specified cacheKey, cacheValue and expiration. - /// - /// Cache key. - /// Cache value. - /// Expiration. - /// The 1st type parameter. - public override void BaseRefresh(string cacheKey, T cacheValue, TimeSpan expiration) - { - ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); - ArgumentCheck.NotNull(cacheValue, nameof(cacheValue)); - ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); - - this.Remove(cacheKey); - this.Set(cacheKey, cacheValue, expiration); - } - - /// - /// Refreshs the specified cacheKey, cacheValue and expiration. - /// - /// The async. - /// Cache key. - /// Cache value. - /// Expiration. - /// The 1st type parameter. - public override async Task BaseRefreshAsync(string cacheKey, T cacheValue, TimeSpan expiration) - { - ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); - ArgumentCheck.NotNull(cacheValue, nameof(cacheValue)); - ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); - - await this.RemoveAsync(cacheKey); - await this.SetAsync(cacheKey, cacheValue, expiration); - } + } /// /// Removes cached item by cachekey's prefix. diff --git a/src/EasyCaching.SQLite/EasyCaching.SQLite.csproj b/src/EasyCaching.SQLite/EasyCaching.SQLite.csproj index 7a20e78a..bc0fbc1e 100644 --- a/src/EasyCaching.SQLite/EasyCaching.SQLite.csproj +++ b/src/EasyCaching.SQLite/EasyCaching.SQLite.csproj @@ -3,15 +3,15 @@ netstandard2.0 - Catcher Wong - Catcher Wong + ncc;Catcher Wong + ncc;Catcher Wong $(EasyCachingSQLitePackageVersion) A simple local caching provider based on Microsoft.Data.SQLite SQLite,LocalCache,Caching,Cache,InMemory,Persisted https://github.com/dotnetcore/EasyCaching - https://github.com/dotnetcore/EasyCaching/blob/master/LICENSE + LICENSE https://github.com/dotnetcore/EasyCaching https://github.com/dotnetcore/EasyCaching https://raw.githubusercontent.com/dotnetcore/EasyCaching/master/media/nuget-icon.png @@ -25,6 +25,10 @@ $(NoWarn);1591 + + + + diff --git a/src/EasyCaching.Serialization.Json/Configurations/EasyCachingOptionsExtensions.cs b/src/EasyCaching.Serialization.Json/Configurations/EasyCachingOptionsExtensions.cs index 85eadaef..22db98b8 100644 --- a/src/EasyCaching.Serialization.Json/Configurations/EasyCachingOptionsExtensions.cs +++ b/src/EasyCaching.Serialization.Json/Configurations/EasyCachingOptionsExtensions.cs @@ -13,16 +13,19 @@ public static class EasyCachingOptionsExtensions /// /// The json. /// Options. - public static EasyCachingOptions WithJson(this EasyCachingOptions options) => options.WithJson(x => { }); + /// Name. + public static EasyCachingOptions WithJson(this EasyCachingOptions options, string name = "json") => options.WithJson(x => { }, name); + /// /// Withs the json. /// /// The json. /// Options. /// Configure. - public static EasyCachingOptions WithJson(this EasyCachingOptions options, Action configure) + /// Name. + public static EasyCachingOptions WithJson(this EasyCachingOptions options, Action configure, string name) { - options.RegisterExtension(new JsonOptionsExtension(configure)); + options.RegisterExtension(new JsonOptionsExtension(name, configure)); return options; } diff --git a/src/EasyCaching.Serialization.Json/Configurations/JsonOptionsExtension.cs b/src/EasyCaching.Serialization.Json/Configurations/JsonOptionsExtension.cs index f2a03b50..6f4d72b8 100644 --- a/src/EasyCaching.Serialization.Json/Configurations/JsonOptionsExtension.cs +++ b/src/EasyCaching.Serialization.Json/Configurations/JsonOptionsExtension.cs @@ -11,6 +11,11 @@ /// internal sealed class JsonOptionsExtension : IEasyCachingOptionsExtension { + /// + /// The name. + /// + private readonly string _name; + /// /// The configure. /// @@ -19,9 +24,11 @@ internal sealed class JsonOptionsExtension : IEasyCachingOptionsExtension /// /// Initializes a new instance of the class. /// + /// Name. /// Configure. - public JsonOptionsExtension(Action configure) + public JsonOptionsExtension(string name, Action configure) { + this._name = name; this._configure = configure; } @@ -36,8 +43,13 @@ public void AddServices(IServiceCollection services) if (_configure != null) configure = _configure; services.AddOptions(); - services.Configure(configure); - services.AddSingleton(); + services.Configure(_name, configure); + services.AddSingleton(x=> + { + var optionsMon = x.GetRequiredService>(); + var options = optionsMon.Get(_name); + return new DefaultJsonSerializer(_name, options); + }); } /// diff --git a/src/EasyCaching.Serialization.Json/DefaultJsonSerializer.cs b/src/EasyCaching.Serialization.Json/DefaultJsonSerializer.cs index d9d86fb5..680e6a09 100644 --- a/src/EasyCaching.Serialization.Json/DefaultJsonSerializer.cs +++ b/src/EasyCaching.Serialization.Json/DefaultJsonSerializer.cs @@ -5,7 +5,6 @@ using System.Text; using EasyCaching.Core.Internal; using EasyCaching.Core.Serialization; - using Microsoft.Extensions.Options; using Newtonsoft.Json; /// @@ -18,13 +17,19 @@ public class DefaultJsonSerializer : IEasyCachingSerializer /// private readonly JsonSerializer jsonSerializer; + /// + /// The name. + /// + private readonly string _name; + /// /// Initializes a new instance of the class. /// - /// Options. - public DefaultJsonSerializer(IOptions optionsAcc) + /// Name. + /// Options. + public DefaultJsonSerializer(string name, EasyCachingJsonSerializerOptions options) { - var options = optionsAcc.Value; + _name = name; jsonSerializer = new JsonSerializer { ReferenceLoopHandling = options.ReferenceLoopHandling, @@ -39,6 +44,12 @@ public DefaultJsonSerializer(IOptions optionsA }; } + /// + /// Gets the name. + /// + /// The name. + public string Name => _name; + /// /// Deserialize the specified bytes. /// diff --git a/src/EasyCaching.Serialization.Json/EasyCaching.Serialization.Json.csproj b/src/EasyCaching.Serialization.Json/EasyCaching.Serialization.Json.csproj index 1ba7f982..90300d50 100644 --- a/src/EasyCaching.Serialization.Json/EasyCaching.Serialization.Json.csproj +++ b/src/EasyCaching.Serialization.Json/EasyCaching.Serialization.Json.csproj @@ -3,15 +3,15 @@ netstandard2.0 - Catcher Wong - Catcher Wong + ncc;Catcher Wong + ncc;Catcher Wong $(EasyCachingJsonPackageVersion) A serialize library based on Newtonsoft.Json Caching,Serialization,Json https://github.com/dotnetcore/EasyCaching - https://github.com/dotnetcore/EasyCaching/blob/master/LICENSE + LICENSE https://github.com/dotnetcore/EasyCaching https://github.com/dotnetcore/EasyCaching https://raw.githubusercontent.com/dotnetcore/EasyCaching/master/media/nuget-icon.png @@ -25,12 +25,16 @@ $(NoWarn);1591 + + + + - + diff --git a/src/EasyCaching.Serialization.MessagePack/Configurations/EasyCachingOptionsExtensions.cs b/src/EasyCaching.Serialization.MessagePack/Configurations/EasyCachingOptionsExtensions.cs index d432e6cb..8c84b090 100644 --- a/src/EasyCaching.Serialization.MessagePack/Configurations/EasyCachingOptionsExtensions.cs +++ b/src/EasyCaching.Serialization.MessagePack/Configurations/EasyCachingOptionsExtensions.cs @@ -12,9 +12,10 @@ public static class EasyCachingOptionsExtensions /// /// The message pack. /// Options. - public static EasyCachingOptions WithMessagePack(this EasyCachingOptions options) + /// Name. + public static EasyCachingOptions WithMessagePack(this EasyCachingOptions options, string name = "msgpack") { - options.RegisterExtension(new MessagePackOptionsExtension()); + options.RegisterExtension(new MessagePackOptionsExtension(name)); return options; } diff --git a/src/EasyCaching.Serialization.MessagePack/Configurations/MessagePackOptionsExtension.cs b/src/EasyCaching.Serialization.MessagePack/Configurations/MessagePackOptionsExtension.cs index 2202816d..9e6fccf2 100644 --- a/src/EasyCaching.Serialization.MessagePack/Configurations/MessagePackOptionsExtension.cs +++ b/src/EasyCaching.Serialization.MessagePack/Configurations/MessagePackOptionsExtension.cs @@ -10,13 +10,31 @@ /// internal sealed class MessagePackOptionsExtension : IEasyCachingOptionsExtension { + /// + /// The name. + /// + private readonly string _name; + + /// + /// Initializes a new instance of the + /// class. + /// + /// Name. + public MessagePackOptionsExtension(string name) + { + this._name = name; + } + /// /// Adds the services. /// /// Services. public void AddServices(IServiceCollection services) { - services.AddSingleton(); + services.AddSingleton(x => + { + return new DefaultMessagePackSerializer(_name); + }); } /// diff --git a/src/EasyCaching.Serialization.MessagePack/DefaultMessagePackSerializer.cs b/src/EasyCaching.Serialization.MessagePack/DefaultMessagePackSerializer.cs index a9e2af4a..34cbfba8 100644 --- a/src/EasyCaching.Serialization.MessagePack/DefaultMessagePackSerializer.cs +++ b/src/EasyCaching.Serialization.MessagePack/DefaultMessagePackSerializer.cs @@ -10,15 +10,28 @@ /// public class DefaultMessagePackSerializer : IEasyCachingSerializer { + /// + /// The name. + /// + private readonly string _name; + /// /// Initializes a new instance of the /// class. /// - public DefaultMessagePackSerializer() + /// Name. + public DefaultMessagePackSerializer(string name) { + _name = name; MessagePackSerializer.SetDefaultResolver(ContractlessStandardResolver.Instance); } + /// + /// Gets the name. + /// + /// The name. + public string Name => _name; + /// /// Deserialize the specified bytes. /// diff --git a/src/EasyCaching.Serialization.MessagePack/EasyCaching.Serialization.MessagePack.csproj b/src/EasyCaching.Serialization.MessagePack/EasyCaching.Serialization.MessagePack.csproj index 050e9906..dcbaf9e7 100644 --- a/src/EasyCaching.Serialization.MessagePack/EasyCaching.Serialization.MessagePack.csproj +++ b/src/EasyCaching.Serialization.MessagePack/EasyCaching.Serialization.MessagePack.csproj @@ -3,15 +3,15 @@ netstandard2.0 - Catcher Wong - Catcher Wong + ncc;Catcher Wong + ncc;Catcher Wong $(EasyCachingMessagePackPackageVersion) A serialize library based on MessagePack Caching,Serialization,MessagePack https://github.com/dotnetcore/EasyCaching - https://github.com/dotnetcore/EasyCaching/blob/master/LICENSE + LICENSE https://github.com/dotnetcore/EasyCaching https://github.com/dotnetcore/EasyCaching https://raw.githubusercontent.com/dotnetcore/EasyCaching/master/media/nuget-icon.png @@ -25,11 +25,15 @@ $(NoWarn);1591 + + + + - + diff --git a/src/EasyCaching.Serialization.Protobuf/Configurations/EasyCachingOptionsExtensions.cs b/src/EasyCaching.Serialization.Protobuf/Configurations/EasyCachingOptionsExtensions.cs index 4977243f..788ee344 100644 --- a/src/EasyCaching.Serialization.Protobuf/Configurations/EasyCachingOptionsExtensions.cs +++ b/src/EasyCaching.Serialization.Protobuf/Configurations/EasyCachingOptionsExtensions.cs @@ -12,9 +12,10 @@ public static class EasyCachingOptionsExtensions /// /// The protobuf. /// Options. - public static EasyCachingOptions WithProtobuf(this EasyCachingOptions options) + /// Name. + public static EasyCachingOptions WithProtobuf(this EasyCachingOptions options, string name = "proto") { - options.RegisterExtension(new ProtobufOptionsExtension()); + options.RegisterExtension(new ProtobufOptionsExtension(name)); return options; } diff --git a/src/EasyCaching.Serialization.Protobuf/Configurations/ProtobufOptionsExtension.cs b/src/EasyCaching.Serialization.Protobuf/Configurations/ProtobufOptionsExtension.cs index 5adedf3d..dcca951a 100644 --- a/src/EasyCaching.Serialization.Protobuf/Configurations/ProtobufOptionsExtension.cs +++ b/src/EasyCaching.Serialization.Protobuf/Configurations/ProtobufOptionsExtension.cs @@ -10,13 +10,31 @@ /// internal sealed class ProtobufOptionsExtension : IEasyCachingOptionsExtension { + /// + /// The name. + /// + private readonly string _name; + + /// + /// Initializes a new instance of the + /// class. + /// + /// Name. + public ProtobufOptionsExtension(string name) + { + this._name = name; + } + /// /// Adds the services. /// /// Services. public void AddServices(IServiceCollection services) { - services.AddSingleton(); + services.AddSingleton(x => + { + return new DefaultProtobufSerializer(_name); + }); } /// diff --git a/src/EasyCaching.Serialization.Protobuf/DefaultProtobufSerializer.cs b/src/EasyCaching.Serialization.Protobuf/DefaultProtobufSerializer.cs index 1d16a199..5e33a564 100644 --- a/src/EasyCaching.Serialization.Protobuf/DefaultProtobufSerializer.cs +++ b/src/EasyCaching.Serialization.Protobuf/DefaultProtobufSerializer.cs @@ -12,6 +12,27 @@ /// public class DefaultProtobufSerializer : IEasyCachingSerializer { + /// + /// The name. + /// + private readonly string _name; + + /// + /// Initializes a new instance of the + /// class. + /// + /// Name. + public DefaultProtobufSerializer(string name) + { + _name = name; + } + + /// + /// Gets the name. + /// + /// The name. + public string Name => _name; + /// /// Deserialize the specified bytes. /// diff --git a/src/EasyCaching.Serialization.Protobuf/EasyCaching.Serialization.Protobuf.csproj b/src/EasyCaching.Serialization.Protobuf/EasyCaching.Serialization.Protobuf.csproj index 6ea03e9c..f4ade9c7 100644 --- a/src/EasyCaching.Serialization.Protobuf/EasyCaching.Serialization.Protobuf.csproj +++ b/src/EasyCaching.Serialization.Protobuf/EasyCaching.Serialization.Protobuf.csproj @@ -3,15 +3,15 @@ netstandard2.0 - Catcher Wong - Catcher Wong + ncc;Catcher Wong + ncc;Catcher Wong $(EasyCachingProtobufPackageVersion) A serialize library based on protobuf-net Caching,Serialization,Protobuf https://github.com/dotnetcore/EasyCaching - https://github.com/dotnetcore/EasyCaching/blob/master/LICENSE + LICENSE https://github.com/dotnetcore/EasyCaching https://github.com/dotnetcore/EasyCaching https://raw.githubusercontent.com/dotnetcore/EasyCaching/master/media/nuget-icon.png @@ -25,6 +25,10 @@ $(NoWarn);1591 + + + + diff --git a/test/EasyCaching.PerformanceTests/SerializerBenchmark.cs b/test/EasyCaching.PerformanceTests/SerializerBenchmark.cs index 497d1956..c707574d 100644 --- a/test/EasyCaching.PerformanceTests/SerializerBenchmark.cs +++ b/test/EasyCaching.PerformanceTests/SerializerBenchmark.cs @@ -14,9 +14,9 @@ [AllStatisticsColumn] public abstract class SerializerBenchmark { - private DefaultJsonSerializer _json = new DefaultJsonSerializer(new OptionsWrapper(new EasyCachingJsonSerializerOptions())); - private DefaultMessagePackSerializer _messagepack = new DefaultMessagePackSerializer(); - private DefaultProtobufSerializer _protobuf = new DefaultProtobufSerializer(); + private DefaultJsonSerializer _json = new DefaultJsonSerializer("json", new EasyCachingJsonSerializerOptions()); + private DefaultMessagePackSerializer _messagepack = new DefaultMessagePackSerializer("msgpack"); + private DefaultProtobufSerializer _protobuf = new DefaultProtobufSerializer("proto"); private DefaultBinaryFormatterSerializer _binary = new DefaultBinaryFormatterSerializer(); protected MyPoco _single; protected List _list; diff --git a/test/EasyCaching.UnitTests/CachingTests/BaseCachingProviderTest.cs b/test/EasyCaching.UnitTests/CachingTests/BaseCachingProviderTest.cs index 730c78c8..79fb4de6 100644 --- a/test/EasyCaching.UnitTests/CachingTests/BaseCachingProviderTest.cs +++ b/test/EasyCaching.UnitTests/CachingTests/BaseCachingProviderTest.cs @@ -605,92 +605,7 @@ protected virtual async Task GetAsync_Parallel_Should_Succeed() Assert.InRange(count, 1, 5); } - #endregion - - #region Refresh/RefreshAsync - [Fact] - public void Refresh_Should_Succeed() - { - var cacheKey = $"{_nameSpace}{Guid.NewGuid().ToString()}"; - var cacheValue = "value"; - - _provider.Set(cacheKey, cacheValue, _defaultTs); - - var tmp = _provider.Get(cacheKey); - Assert.Equal("value", tmp.Value); - - var newValue = "NewValue"; - - _provider.Refresh(cacheKey, newValue, _defaultTs); - - var act = _provider.Get(cacheKey); - - Assert.Equal("NewValue", act.Value); - } - - [Fact] - public async Task Refresh_Async_Should_Succeed() - { - var cacheKey = $"{_nameSpace}{Guid.NewGuid().ToString()}"; - var cacheValue = "value"; - var cacheBytes = new byte[] { 0x01 }; - - await _provider.SetAsync(cacheKey, cacheValue, _defaultTs); - - var tmp = await _provider.GetAsync(cacheKey); - Assert.Equal("value", tmp.Value); - - var newValue = "NewValue"; - - - await _provider.RefreshAsync(cacheKey, newValue, _defaultTs); - - var act = await _provider.GetAsync(cacheKey); - - Assert.Equal("NewValue", act.Value); - } - - [Fact] - public void Refresh_Value_Type_Object_Should_Succeed() - { - var cacheKey = $"{_nameSpace}{Guid.NewGuid().ToString()}"; - var cacheValue = 100; - - _provider.Set(cacheKey, cacheValue, _defaultTs); - - var tmp = _provider.Get(cacheKey); - Assert.Equal(cacheValue, tmp.Value); - - var newValue = 999; - - _provider.Refresh(cacheKey, newValue, _defaultTs); - - var act = _provider.Get(cacheKey); - - Assert.Equal(newValue, act.Value); - } - - [Fact] - public async Task Refresh_Value_Type_Object_Async_Should_Succeed() - { - var cacheKey = $"{_nameSpace}{Guid.NewGuid().ToString()}"; - var cacheValue = 100; - - await _provider.SetAsync(cacheKey, cacheValue, _defaultTs); - - var tmp = await _provider.GetAsync(cacheKey); - Assert.Equal(cacheValue, tmp.Value); - - var newValue = 999; - - await _provider.RefreshAsync(cacheKey, newValue, _defaultTs); - - var act = await _provider.GetAsync(cacheKey); - - Assert.Equal(newValue, act.Value); - } - - #endregion + #endregion #region Remove/RemoveAsync [Fact] diff --git a/test/EasyCaching.UnitTests/CachingTests/DiskCachingProviderTest.cs b/test/EasyCaching.UnitTests/CachingTests/DiskCachingProviderTest.cs new file mode 100644 index 00000000..96c2e00f --- /dev/null +++ b/test/EasyCaching.UnitTests/CachingTests/DiskCachingProviderTest.cs @@ -0,0 +1,30 @@ +namespace EasyCaching.UnitTests +{ + using System; + using System.IO; + using System.Threading.Tasks; + using EasyCaching.Core; + using EasyCaching.Disk; + using Microsoft.Extensions.DependencyInjection; + using Xunit; + + public class DiskCachingProviderTest : BaseCachingProviderTest + { + public DiskCachingProviderTest() + { + IServiceCollection services = new ServiceCollection(); + services.AddEasyCaching(x => x.UseDisk(options => + { + options.MaxRdSecond = 0; + options.DBConfig = new DiskDbOptions + { + BasePath = Path.GetTempPath() + }; + + })); + IServiceProvider serviceProvider = services.BuildServiceProvider(); + _provider = serviceProvider.GetService(); + _defaultTs = TimeSpan.FromSeconds(30); + } + } +} \ No newline at end of file diff --git a/test/EasyCaching.UnitTests/CachingTests/MemcachedProviderTest.cs b/test/EasyCaching.UnitTests/CachingTests/MemcachedProviderTest.cs index 44162913..1ef7562c 100644 --- a/test/EasyCaching.UnitTests/CachingTests/MemcachedProviderTest.cs +++ b/test/EasyCaching.UnitTests/CachingTests/MemcachedProviderTest.cs @@ -333,7 +333,6 @@ public MemcachedProviderUseEasyCachingWithConfigTest() 'easycaching': { 'memcached': { 'MaxRdSecond': 600, - 'Order': 99, 'dbconfig': { 'Servers': [ { @@ -365,7 +364,7 @@ public MemcachedProviderUseEasyCachingWithConfigTest() public void Provider_Information_Should_Be_Correct() { Assert.Equal(600, _provider.MaxRdSecond); - Assert.Equal(99, _provider.Order); + //Assert.Equal(99, _provider.Order); Assert.Equal("mName", _provider.Name); } } diff --git a/test/EasyCaching.UnitTests/CachingTests/MemoryCachingProviderTest.cs b/test/EasyCaching.UnitTests/CachingTests/MemoryCachingProviderTest.cs index 04429c9d..da7b7f5f 100644 --- a/test/EasyCaching.UnitTests/CachingTests/MemoryCachingProviderTest.cs +++ b/test/EasyCaching.UnitTests/CachingTests/MemoryCachingProviderTest.cs @@ -165,9 +165,7 @@ public MemoryCachingProviderUseEasyCachingWithConfigTest() { 'easycaching': { 'inmemory': { - 'CachingProviderType': 1, 'MaxRdSecond': 600, - 'Order': 99, 'dbconfig': { 'SizeLimit' : 50 } @@ -194,7 +192,7 @@ public MemoryCachingProviderUseEasyCachingWithConfigTest() public void Provider_Information_Should_Be_Correct() { Assert.Equal(600, _provider.MaxRdSecond); - Assert.Equal(99, _provider.Order); + //Assert.Equal(99, _provider.Order); Assert.Equal("mName", _provider.Name); } } diff --git a/test/EasyCaching.UnitTests/CachingTests/SQLiteCachingTest.cs b/test/EasyCaching.UnitTests/CachingTests/SQLiteCachingTest.cs index 89c600d3..604bce1b 100644 --- a/test/EasyCaching.UnitTests/CachingTests/SQLiteCachingTest.cs +++ b/test/EasyCaching.UnitTests/CachingTests/SQLiteCachingTest.cs @@ -191,7 +191,6 @@ public SQLiteCachingProviderUseEasyCachingWithConfigTest() 'easycaching': { 'sqlite': { 'MaxRdSecond': 600, - 'Order': 99, 'dbconfig': { 'FileName': 'my.db' } @@ -231,7 +230,7 @@ public SQLiteCachingProviderUseEasyCachingWithConfigTest() public void Provider_Information_Should_Be_Correct() { Assert.Equal(600, _provider.MaxRdSecond); - Assert.Equal(99, _provider.Order); + //Assert.Equal(99, _provider.Order); Assert.Equal("mName", _provider.Name); } } diff --git a/test/EasyCaching.UnitTests/Diagnostics/MyCachingProvider.cs b/test/EasyCaching.UnitTests/Diagnostics/MyCachingProvider.cs index 17d30e69..4300cb75 100755 --- a/test/EasyCaching.UnitTests/Diagnostics/MyCachingProvider.cs +++ b/test/EasyCaching.UnitTests/Diagnostics/MyCachingProvider.cs @@ -13,7 +13,6 @@ public MyCachingProvider() this.ProviderStats = new CacheStats(); this.ProviderType = CachingProviderType.InMemory; this.ProviderMaxRdSecond = 120; - this.ProviderOrder = 1; this.IsDistributedProvider = false; } @@ -97,16 +96,6 @@ public override Task BaseGetExpirationAsync(string cacheKey) return Task.FromResult(TimeSpan.FromSeconds(1)); } - public override void BaseRefresh(string cacheKey, T cacheValue, TimeSpan expiration) - { - - } - - public override Task BaseRefreshAsync(string cacheKey, T cacheValue, TimeSpan expiration) - { - return Task.CompletedTask; - } - public override void BaseRemove(string cacheKey) { diff --git a/test/EasyCaching.UnitTests/EasyCaching.UnitTests.csproj b/test/EasyCaching.UnitTests/EasyCaching.UnitTests.csproj index 96bac279..8d8a1367 100644 --- a/test/EasyCaching.UnitTests/EasyCaching.UnitTests.csproj +++ b/test/EasyCaching.UnitTests/EasyCaching.UnitTests.csproj @@ -32,6 +32,7 @@ + diff --git a/test/EasyCaching.UnitTests/SerializerTests/JsonSerializerTest.cs b/test/EasyCaching.UnitTests/SerializerTests/JsonSerializerTest.cs index a381f4d1..56eb1a4a 100644 --- a/test/EasyCaching.UnitTests/SerializerTests/JsonSerializerTest.cs +++ b/test/EasyCaching.UnitTests/SerializerTests/JsonSerializerTest.cs @@ -10,11 +10,7 @@ public class JsonSerializerTest : BaseSerializerTest { public JsonSerializerTest() { - var options = A.Fake>(); - - A.CallTo(() => options.Value).Returns(new EasyCachingJsonSerializerOptions()); - - _serializer = new DefaultJsonSerializer(options); + _serializer = new DefaultJsonSerializer("json", new EasyCachingJsonSerializerOptions()); } [Fact] @@ -31,15 +27,11 @@ public void Isuue_50_Test() [Fact] public void ReferenceLoopHandling_Test_Should_Succeed() { - var options = A.Fake>(); - - A.CallTo(() => options.Value).Returns(new EasyCachingJsonSerializerOptions() + var serializer = new DefaultJsonSerializer("json", new EasyCachingJsonSerializerOptions() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore }); - var serializer = new DefaultJsonSerializer(options); - Employee joe = new Employee { Name = "Joe User" }; Employee mike = new Employee { Name = "Mike Manager" }; joe.Manager = mike; @@ -62,15 +54,11 @@ public class Employee [Fact] public void NullValueHandling_Test_Should_Succeed() { - var options = A.Fake>(); - - A.CallTo(() => options.Value).Returns(new EasyCachingJsonSerializerOptions() + var serializer = new DefaultJsonSerializer("json", new EasyCachingJsonSerializerOptions() { NullValueHandling = NullValueHandling.Ignore }); - var serializer = new DefaultJsonSerializer(options); - Employee joe = new Employee { Name = "Joe User" }; var joe_byte = serializer.Serialize(joe); diff --git a/test/EasyCaching.UnitTests/SerializerTests/MessagePackSerializerTest.cs b/test/EasyCaching.UnitTests/SerializerTests/MessagePackSerializerTest.cs index d900cc59..50efb697 100644 --- a/test/EasyCaching.UnitTests/SerializerTests/MessagePackSerializerTest.cs +++ b/test/EasyCaching.UnitTests/SerializerTests/MessagePackSerializerTest.cs @@ -6,7 +6,7 @@ public class MessagePackSerializerTest : BaseSerializerTest { public MessagePackSerializerTest() { - _serializer = new DefaultMessagePackSerializer(); + _serializer = new DefaultMessagePackSerializer("msgpack"); } } } \ No newline at end of file diff --git a/test/EasyCaching.UnitTests/SerializerTests/ProtobufSerializerTest.cs b/test/EasyCaching.UnitTests/SerializerTests/ProtobufSerializerTest.cs index 909b5d6d..0bc538c3 100644 --- a/test/EasyCaching.UnitTests/SerializerTests/ProtobufSerializerTest.cs +++ b/test/EasyCaching.UnitTests/SerializerTests/ProtobufSerializerTest.cs @@ -6,7 +6,7 @@ public class ProtobufSerializerTest: BaseSerializerTest { public ProtobufSerializerTest() { - _serializer = new DefaultProtobufSerializer(); + _serializer = new DefaultProtobufSerializer("proto"); } } }