From 5ba011cb34b356015a904572c5561ca186fee04d Mon Sep 17 00:00:00 2001 From: catcherwong Date: Fri, 1 Feb 2019 08:30:57 +0800 Subject: [PATCH 01/20] :hammer: Refactoring Hybird Caching Provider. --- .../IHybridCachingProvider.cs | 28 +- .../HybridCachingProvider.cs | 629 ++---------------- .../CachingTests/HybridCachingTest.cs | 184 ++--- 3 files changed, 181 insertions(+), 660 deletions(-) diff --git a/src/EasyCaching.Core/IHybridCachingProvider.cs b/src/EasyCaching.Core/IHybridCachingProvider.cs index 44d2ff79..2b33ba49 100644 --- a/src/EasyCaching.Core/IHybridCachingProvider.cs +++ b/src/EasyCaching.Core/IHybridCachingProvider.cs @@ -1,7 +1,31 @@ -namespace EasyCaching.Core +using System; +using System.Threading.Tasks; + +namespace EasyCaching.Core { /// /// Hybrid caching provider. /// - public interface IHybridCachingProvider : IEasyCachingProvider { } + public interface IHybridCachingProvider //: IEasyCachingProvider + { + void Set(string cacheKey, T cacheValue, TimeSpan expiration); + + Task SetAsync(string cacheKey, T cacheValue, TimeSpan expiration); + + CacheValue Get(string cacheKey); + + Task> GetAsync(string cacheKey); + + void Remove(string cacheKey); + + Task RemoveAsync(string cacheKey); + + Task ExistsAsync(string cacheKey); + + bool Exists(string cacheKey); + + bool TrySet(string cacheKey, T cacheValue, TimeSpan expiration); + + Task TrySetAsync(string cacheKey, T cacheValue, TimeSpan expiration); + } } diff --git a/src/EasyCaching.HybridCache/HybridCachingProvider.cs b/src/EasyCaching.HybridCache/HybridCachingProvider.cs index 84e59a22..c006c95f 100644 --- a/src/EasyCaching.HybridCache/HybridCachingProvider.cs +++ b/src/EasyCaching.HybridCache/HybridCachingProvider.cs @@ -12,661 +12,158 @@ /// public class HybridCachingProvider : IHybridCachingProvider { - /// - /// The caching providers. - /// - private readonly IEnumerable _providers; - - /// - /// Gets a value indicating whether this is - /// distributed cache. - /// - /// true if is distributed cache; otherwise, false. - public bool IsDistributedCache => throw new NotImplementedException(); - - /// - /// Gets the order. - /// - /// The order. - public int Order => throw new NotImplementedException(); - - /// - /// Gets the max rd second. - /// - /// The max rd second. - public int MaxRdSecond => throw new NotImplementedException(); - - /// - /// Gets the type of the caching provider. - /// - /// The type of the caching provider. - public CachingProviderType CachingProviderType => throw new NotImplementedException(); - - public CacheStats CacheStats => throw new NotImplementedException(); - - public string Name => throw new NotImplementedException(); - - /// - /// Initializes a new instance of the class. - /// - /// Providers. - public HybridCachingProvider(IEnumerable providers) + private readonly IEasyCachingProvider _localCache; + private readonly IEasyCachingProvider _distributedCache; + private readonly IEasyCachingBus _bus; + + public HybridCachingProvider( + IEnumerable providers + , IEasyCachingBus bus = null + ) { - if (providers == null || !providers.Any()) - { - throw new ArgumentNullException(nameof(providers)); - } + ArgumentCheck.NotNullAndCountGTZero(providers, nameof(providers)); - //2-level and 3-level are enough for hybrid - if (providers.Count() > 3) - { - throw new ArgumentOutOfRangeException(nameof(providers)); - } + var local = providers.OrderBy(x => x.Order).FirstOrDefault(x=>!x.IsDistributedCache); - // - this._providers = providers.OrderBy(x => x.Order); + if (local == null) throw new Exception(); + else this._localCache = local; - //TODO: local cache should subscribe the remote cache - } + var distributed = providers.OrderBy(x => x.Order).FirstOrDefault(x => x.IsDistributedCache); - /// - /// Exists the specified cacheKey. - /// - /// The exists. - /// Cache key. - public bool Exists(string cacheKey) - { - ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); + if (distributed == null) throw new Exception(); + else this._distributedCache = distributed; - var flag = false; - - foreach (var provider in _providers) - { - flag = provider.Exists(cacheKey); + this._bus = bus; - if (flag) break; - } - return flag; } - /// - /// Existses the specified cacheKey async. - /// - /// The async. - /// Cache key. - public async Task ExistsAsync(string cacheKey) + public bool Exists(string cacheKey) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); - var flag = false; - - foreach (var provider in _providers) - { - flag = provider.Exists(cacheKey); - - if (flag) break; - } - - return await Task.FromResult(flag); + return _distributedCache.Exists(cacheKey); } - /// - /// Get the specified cacheKey, dataRetriever and expiration. - /// - /// The get. - /// Cache key. - /// Data retriever. - /// Expiration. - /// The 1st type parameter. - public CacheValue Get(string cacheKey, Func dataRetriever, TimeSpan expiration) + public async Task ExistsAsync(string cacheKey) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); - ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); - - CacheValue cachedValue = null; - - foreach (var provider in _providers) - { - cachedValue = provider.Get(cacheKey, dataRetriever, expiration); - if (cachedValue.HasValue) - { - break; - } - } - - if (!cachedValue.HasValue) - { - var retriever = dataRetriever(); - if (retriever != null) - { - Set(cacheKey, retriever, expiration); - return new CacheValue(retriever, true); - } - else - { - //TODO : Set a null value to cache!! - return CacheValue.NoValue; - } - } - - return cachedValue; + return await _distributedCache.ExistsAsync(cacheKey); } - /// - /// Get the specified cacheKey. - /// - /// The get. - /// Cache key. - /// The 1st type parameter. public CacheValue Get(string cacheKey) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); - CacheValue cachedValue = null; - - foreach (var provider in _providers) - { - cachedValue = provider.Get(cacheKey); + var cacheValue = _localCache.Get(cacheKey); - if (cachedValue.HasValue) - { - break; - } - } - - if (!cachedValue.HasValue) + if(cacheValue.HasValue) { - return CacheValue.NoValue; + return cacheValue; } - return cachedValue; - } + cacheValue = _distributedCache.Get(cacheKey); - /// - /// Gets the specified cacheKey, dataRetriever and expiration async. - /// - /// The async. - /// Cache key. - /// Data retriever. - /// Expiration. - /// The 1st type parameter. - public async Task> GetAsync(string cacheKey, Func> dataRetriever, TimeSpan expiration) - { - ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); - ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); - - CacheValue cachedValue = null; - - foreach (var provider in _providers) + if (cacheValue.HasValue) { - cachedValue = provider.Get(cacheKey); + _localCache.Set(cacheKey, cacheValue.Value, TimeSpan.FromSeconds(60)); - if (cachedValue.HasValue) - { - break; - } - } - - if (!cachedValue.HasValue) - { - var retriever = await dataRetriever?.Invoke(); - if (retriever != null) - { - await SetAsync(cacheKey, retriever, expiration); - return new CacheValue(retriever, true); - } - else - { - return CacheValue.NoValue; - } + return cacheValue; } - return cachedValue; + return CacheValue.NoValue; } - /// - /// Gets the specified cacheKey async. - /// - /// The async. - /// Cache key. - /// The 1st type parameter. public async Task> GetAsync(string cacheKey) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); - CacheValue cachedValue = null; + var cacheValue = await _localCache.GetAsync(cacheKey); - foreach (var provider in _providers) + if (cacheValue.HasValue) { - cachedValue = provider.Get(cacheKey); - - if (cachedValue.HasValue) - { - break; - } + return cacheValue; } - if (!cachedValue.HasValue) + cacheValue = await _distributedCache.GetAsync(cacheKey); + + if (cacheValue.HasValue) { - return CacheValue.NoValue; + await _localCache.SetAsync(cacheKey, cacheValue.Value, TimeSpan.FromSeconds(60)); + + return cacheValue; } - return await Task.FromResult(cachedValue); + return CacheValue.NoValue; } - /// - /// Remove the specified cacheKey. - /// - /// The remove. - /// Cache key. public void Remove(string cacheKey) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); - foreach (var provider in _providers) - { - provider.Remove(cacheKey); - } + _distributedCache.Remove(cacheKey); + _localCache.Remove(cacheKey); + + //send message to bus } - /// - /// Removes the specified cacheKey async. - /// - /// The async. - /// Cache key. public async Task RemoveAsync(string cacheKey) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); - var tasks = new List(); - - foreach (var provider in _providers) - { - tasks.Add(provider.RemoveAsync(cacheKey)); - } + await _distributedCache.RemoveAsync(cacheKey); + await _localCache.RemoveAsync(cacheKey); - await Task.WhenAll(tasks); + //send message to bus } - /// - /// Set the specified cacheKey, cacheValue and expiration. - /// - /// The set. - /// Cache key. - /// Cache value. - /// Expiration. - /// The 1st type parameter. public void Set(string cacheKey, T cacheValue, TimeSpan expiration) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); - ArgumentCheck.NotNull(cacheValue, nameof(cacheValue)); - ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); - foreach (var provider in _providers) - { - provider.Set(cacheKey, cacheValue, expiration); - } + _localCache.Set(cacheKey, cacheValue, expiration); + _distributedCache.Set(cacheKey, cacheValue, expiration); + + //send message to bus } - /// - /// Sets the specified cacheKey, cacheValue and expiration async. - /// - /// The async. - /// Cache key. - /// Cache value. - /// Expiration. - /// The 1st type parameter. public async Task SetAsync(string cacheKey, T cacheValue, TimeSpan expiration) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); - ArgumentCheck.NotNull(cacheValue, nameof(cacheValue)); - ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); - - var tasks = new List(); - - foreach (var provider in _providers) - { - tasks.Add(provider.SetAsync(cacheKey, cacheValue, expiration)); - } - await Task.WhenAll(tasks); - } - - /// - /// Refresh the specified cacheKey, cacheValue and expiration. - /// - /// Cache key. - /// Cache value. - /// Expiration. - /// The 1st type parameter. - public void Refresh(string cacheKey, T cacheValue, TimeSpan expiration) - { - ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); - ArgumentCheck.NotNull(cacheValue, nameof(cacheValue)); - ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); + await _localCache.SetAsync(cacheKey, cacheValue, expiration); + await _distributedCache.SetAsync(cacheKey, cacheValue, expiration); - this.Remove(cacheKey); - this.Set(cacheKey, cacheValue, expiration); + //send message to bus } - /// - /// Refreshs the specified cacheKey, cacheValue and expiration. - /// - /// The async. - /// Cache key. - /// Cache value. - /// Expiration. - /// The 1st type parameter. - public async Task RefreshAsync(string cacheKey, T cacheValue, TimeSpan expiration) + public bool TrySet(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. - /// - /// The by prefix async. - /// Prefix. - public void RemoveByPrefix(string prefix) - { - ArgumentCheck.NotNullOrWhiteSpace(prefix, nameof(prefix)); - - foreach (var provider in _providers) - { - provider.RemoveByPrefix(prefix); - } - } - - /// - /// Removes cached item by cachekey's prefix async. - /// - /// The by prefix async. - /// Prefix. - public async Task RemoveByPrefixAsync(string prefix) - { - ArgumentCheck.NotNullOrWhiteSpace(prefix, nameof(prefix)); - - var tasks = new List(); - - foreach (var provider in _providers) - { - tasks.Add(provider.RemoveByPrefixAsync(prefix)); - } - - await Task.WhenAll(tasks); - } - - /// - /// Sets all. - /// - /// Values. - /// Expiration. - /// The 1st type parameter. - public void SetAll(IDictionary values, TimeSpan expiration) - { - ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); - ArgumentCheck.NotNullAndCountGTZero(values, nameof(values)); - - foreach (var provider in _providers) - { - provider.SetAll(values, expiration); - } - } - - /// - /// Sets all async. - /// - /// The all async. - /// Values. - /// Expiration. - /// The 1st type parameter. - public async Task SetAllAsync(IDictionary values, TimeSpan expiration) - { - ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); - ArgumentCheck.NotNullAndCountGTZero(values, nameof(values)); - - var tasks = new List(); - - foreach (var provider in _providers) - { - tasks.Add(provider.SetAllAsync(values, expiration)); - } - await Task.WhenAll(tasks); - } - - /// - /// Gets all. - /// - /// The all. - /// Cache keys. - /// The 1st type parameter. - public IDictionary> GetAll(IEnumerable cacheKeys) - { - ArgumentCheck.NotNullAndCountGTZero(cacheKeys, nameof(cacheKeys)); - - var local = _providers.FirstOrDefault(); - - var localDict = local.GetAll(cacheKeys); - - //not find in local caching. - var localNotFindKeys = localDict.Where(x => !x.Value.HasValue).Select(x => x.Key); - - if (!localNotFindKeys.Any()) - { - return localDict; - } - - foreach (var item in localNotFindKeys) - localDict.Remove(item); - - //remote - foreach (var provider in _providers.Skip(1)) - { - var disDict = provider.GetAll(localNotFindKeys); - localDict.Concat(disDict).ToDictionary(k => k.Key, v => v.Value); - } - - return localDict; - } - - /// - /// Gets all async. - /// - /// The all async. - /// Cache keys. - /// The 1st type parameter. - public async Task>> GetAllAsync(IEnumerable cacheKeys) - { - ArgumentCheck.NotNullAndCountGTZero(cacheKeys, nameof(cacheKeys)); - - var local = _providers.FirstOrDefault(); - - var localDict = await local.GetAllAsync(cacheKeys); - - //not find in local caching. - var localNotFindKeys = localDict.Where(x => !x.Value.HasValue).Select(x => x.Key); - - if (!localNotFindKeys.Any()) - { - return localDict; - } - - foreach (var item in localNotFindKeys) - localDict.Remove(item); - - //remote - foreach (var provider in _providers.Skip(1)) - { - var disDict = provider.GetAll(localNotFindKeys); - localDict.Concat(disDict).ToDictionary(k => k.Key, v => v.Value); - } - - return localDict; - } - - /// - /// Gets the by prefix. - /// - /// The by prefix. - /// Prefix. - /// The 1st type parameter. - public IDictionary> GetByPrefix(string prefix) - { - ArgumentCheck.NotNullOrWhiteSpace(prefix, nameof(prefix)); - - var local = _providers.FirstOrDefault(); - - var localDict = local.GetByPrefix(prefix); - - //not find in local caching. - var localNotFindKeys = localDict.Where(x => !x.Value.HasValue).Select(x => x.Key); - - if (!localNotFindKeys.Any()) - { - return localDict; - } - - foreach (var item in localNotFindKeys) - localDict.Remove(item); - - //remote - foreach (var provider in _providers.Skip(1)) - { - var disDict = provider.GetAll(localNotFindKeys); - localDict.Concat(disDict).ToDictionary(k => k.Key, v => v.Value); - } - - return localDict; - } + var flag = _distributedCache.TrySet(cacheKey, cacheValue, expiration); - /// - /// Gets the by prefix async. - /// - /// The by prefix async. - /// Prefix. - /// The 1st type parameter. - public async Task>> GetByPrefixAsync(string prefix) - { - ArgumentCheck.NotNullOrWhiteSpace(prefix, nameof(prefix)); - - var local = _providers.FirstOrDefault(); - - var localDict = await local.GetByPrefixAsync(prefix); - - //not find in local caching. - var localNotFindKeys = localDict.Where(x => !x.Value.HasValue).Select(x => x.Key); - - if (!localNotFindKeys.Any()) - { - return localDict; - } - - foreach (var item in localNotFindKeys) - localDict.Remove(item); - - //remote - foreach (var provider in _providers.Skip(1)) - { - var disDict = provider.GetAll(localNotFindKeys); - localDict.Concat(disDict).ToDictionary(k => k.Key, v => v.Value); - } - - return localDict; - } - - /// - /// Removes all. - /// - /// Cache keys. - public void RemoveAll(IEnumerable cacheKeys) - { - ArgumentCheck.NotNullAndCountGTZero(cacheKeys, nameof(cacheKeys)); - - foreach (var provider in _providers) - { - provider.RemoveAll(cacheKeys); - } - } - - /// - /// Removes all async. - /// - /// The all async. - /// Cache keys. - public async Task RemoveAllAsync(IEnumerable cacheKeys) - { - ArgumentCheck.NotNullAndCountGTZero(cacheKeys, nameof(cacheKeys)); - - var tasks = new List(); - - foreach (var provider in _providers) + if(flag) { - tasks.Add(provider.RemoveAllAsync(cacheKeys)); + _localCache.Set(cacheKey, cacheValue, expiration); } - await Task.WhenAll(tasks); - } - - /// - /// Gets the count. - /// - /// The count. - /// Prefix. - public int GetCount(string prefix = "") - { - var list = new List(); - - foreach (var provider in _providers) - { - list.Add(provider.GetCount(prefix)); - } - - return list.OrderByDescending(x => x).FirstOrDefault(); + return flag; } - /// - /// Flush All Cached Item. - /// - public void Flush() + public async Task TrySetAsync(string cacheKey, T cacheValue, TimeSpan expiration) { - foreach (var provider in _providers) - { - provider.Flush(); - } - } + ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); - /// - /// Flush All Cached Item async. - /// - /// The async. - public async Task FlushAsync() - { - var tasks = new List(); + var flag = await _distributedCache.TrySetAsync(cacheKey, cacheValue, expiration); - foreach (var provider in _providers) + if (flag) { - tasks.Add(provider.FlushAsync()); + await _localCache.SetAsync(cacheKey, cacheValue, expiration); } - await Task.WhenAll(tasks); - } - - public bool TrySet(string cacheKey, T cacheValue, TimeSpan expiration) - { - throw new NotImplementedException(); - } - - public Task TrySetAsync(string cacheKey, T cacheValue, TimeSpan expiration) - { - throw new NotImplementedException(); + return flag; } } } diff --git a/test/EasyCaching.UnitTests/CachingTests/HybridCachingTest.cs b/test/EasyCaching.UnitTests/CachingTests/HybridCachingTest.cs index 90ab2b4d..044623a0 100644 --- a/test/EasyCaching.UnitTests/CachingTests/HybridCachingTest.cs +++ b/test/EasyCaching.UnitTests/CachingTests/HybridCachingTest.cs @@ -1,92 +1,92 @@ -namespace EasyCaching.UnitTests -{ - using EasyCaching.Core; - using EasyCaching.Core.Internal; - using EasyCaching.HybridCache; - using EasyCaching.InMemory; - using EasyCaching.Redis; - using FakeItEasy; - using Microsoft.Extensions.Caching.Memory; - using Microsoft.Extensions.Options; - using System; - using System.Collections.Generic; - using System.Threading.Tasks; - using Xunit; - - public class HybridCachingTest : BaseCachingProviderTest - { - public HybridCachingTest() - { - RedisOptions options = new RedisOptions(); - options.DBConfig.AllowAdmin = true; - options.DBConfig.Endpoints.Add(new ServerEndPoint("127.0.0.1", 6379)); - options.DBConfig.Database = 6; - - var fakeOption = A.Fake>(); - - A.CallTo(() => fakeOption.CurrentValue).Returns(options); - - var fakeDbProvider = A.Fake(option => option.WithArgumentsForConstructor(new object[] { fakeOption })); - - var serializer = new DefaultBinaryFormatterSerializer(); - - var providers = new List - { - new DefaultInMemoryCachingProvider(new InMemory.InMemoryCaching(new InMemoryCachingOptions()), new TestOptionMonitorWrapper(new InMemoryOptions())), - new DefaultRedisCachingProvider(fakeDbProvider, serializer, new TestOptionMonitorWrapper(new RedisOptions())) - }; - - _provider = new HybridCachingProvider(providers); - _defaultTs = TimeSpan.FromSeconds(30); - _nameSpace = "HybridBasic"; - } - - [Fact] - protected override void Get_Count_Without_Prefix_Should_Succeed() - { - - } - - [Fact] - protected override void Get_Count_With_Prefix_Should_Succeed() - { - - } - - [Fact] - protected override void OnHit_Should_Return_One_And_OnMiss_Should_Return_Zero() - { - - } - - [Fact] - protected override void OnHit_Should_Return_Zero_And_OnMiss_Should_Return_One() - { - - } - - [Fact] - protected override void TrySet_Value_And_Get_Cached_Value_Should_Succeed() - { - - } - - [Fact] - protected override async Task TrySet_Value_And_Get_Cached_Value_Async_Should_Succeed() - { - await Task.FromResult(1); - } - - [Fact] - protected override void Get_Parallel_Should_Succeed() - { - - } - - [Fact] - protected override Task GetAsync_Parallel_Should_Succeed() - { - return Task.FromResult(1); - } - } -} +//namespace EasyCaching.UnitTests +//{ +// using EasyCaching.Core; +// using EasyCaching.Core.Internal; +// using EasyCaching.HybridCache; +// using EasyCaching.InMemory; +// using EasyCaching.Redis; +// using FakeItEasy; +// using Microsoft.Extensions.Caching.Memory; +// using Microsoft.Extensions.Options; +// using System; +// using System.Collections.Generic; +// using System.Threading.Tasks; +// using Xunit; + +// public class HybridCachingTest : BaseCachingProviderTest +// { +// public HybridCachingTest() +// { +// RedisOptions options = new RedisOptions(); +// options.DBConfig.AllowAdmin = true; +// options.DBConfig.Endpoints.Add(new ServerEndPoint("127.0.0.1", 6379)); +// options.DBConfig.Database = 6; + +// var fakeOption = A.Fake>(); + +// A.CallTo(() => fakeOption.CurrentValue).Returns(options); + +// var fakeDbProvider = A.Fake(option => option.WithArgumentsForConstructor(new object[] { fakeOption })); + +// var serializer = new DefaultBinaryFormatterSerializer(); + +// var providers = new List +// { +// new DefaultInMemoryCachingProvider(new InMemory.InMemoryCaching(new InMemoryCachingOptions()), new TestOptionMonitorWrapper(new InMemoryOptions())), +// new DefaultRedisCachingProvider(fakeDbProvider, serializer, new TestOptionMonitorWrapper(new RedisOptions())) +// }; + +// _provider = new HybridCachingProvider(providers); +// _defaultTs = TimeSpan.FromSeconds(30); +// _nameSpace = "HybridBasic"; +// } + +// [Fact] +// protected override void Get_Count_Without_Prefix_Should_Succeed() +// { + +// } + +// [Fact] +// protected override void Get_Count_With_Prefix_Should_Succeed() +// { + +// } + +// [Fact] +// protected override void OnHit_Should_Return_One_And_OnMiss_Should_Return_Zero() +// { + +// } + +// [Fact] +// protected override void OnHit_Should_Return_Zero_And_OnMiss_Should_Return_One() +// { + +// } + +// [Fact] +// protected override void TrySet_Value_And_Get_Cached_Value_Should_Succeed() +// { + +// } + +// [Fact] +// protected override async Task TrySet_Value_And_Get_Cached_Value_Async_Should_Succeed() +// { +// await Task.FromResult(1); +// } + +// [Fact] +// protected override void Get_Parallel_Should_Succeed() +// { + +// } + +// [Fact] +// protected override Task GetAsync_Parallel_Should_Succeed() +// { +// return Task.FromResult(1); +// } +// } +//} From e41cbbe955137e1d4c09332d9147f89f61677f85 Mon Sep 17 00:00:00 2001 From: catcherwong Date: Fri, 1 Feb 2019 11:51:54 +0800 Subject: [PATCH 02/20] :sparkles: Redis Bus. --- .../DefaultRabbitMQBus.cs | 23 +++--- .../IRedisSubscriberProvider.cs | 0 .../{ => Configurations}/RedisBusOptions.cs | 2 +- .../RedisBusOptionsExtension.cs | 41 ++++++++++ .../RedisSubscriberProvider.cs | 30 ++++--- src/EasyCaching.Bus.Redis/DefaultRedisBus.cs | 79 +++++++------------ .../EasyCaching.Bus.Redis.csproj | 6 ++ .../EasyCachingOptionsExtensions.cs | 61 ++++++++++++++ .../RedisBusServiceCollectionExtensions.cs | 38 --------- .../Bus/EasyCachingMessage.cs | 9 +++ .../{ => Bus}/IEasyCachingBus.cs | 0 .../Bus/IEasyCachingPublisher.cs | 27 +++++++ .../Bus/IEasyCachingSubscriber.cs | 12 +++ src/EasyCaching.Core/EasyCaching.Core.csproj | 3 + src/EasyCaching.Core/EasyCachingMessage.cs | 16 ---- src/EasyCaching.Core/IEasyCachingPublisher.cs | 29 ------- .../IEasyCachingSubscriber.cs | 23 ------ .../DefaultEasyCachingKeyGenerator.cs | 0 .../EasyCachingInterceptorAttribute.cs | 0 .../IEasyCachingKeyGenerator.cs | 0 .../DefaultBinaryFormatterSerializer.cs | 0 .../IEasyCachingSerializer.cs | 0 22 files changed, 220 insertions(+), 179 deletions(-) rename src/EasyCaching.Bus.Redis/{ => Configurations}/IRedisSubscriberProvider.cs (100%) rename src/EasyCaching.Bus.Redis/{ => Configurations}/RedisBusOptions.cs (75%) create mode 100644 src/EasyCaching.Bus.Redis/Configurations/RedisBusOptionsExtension.cs rename src/EasyCaching.Bus.Redis/{ => Configurations}/RedisSubscriberProvider.cs (60%) create mode 100644 src/EasyCaching.Bus.Redis/EasyCachingOptionsExtensions.cs delete mode 100644 src/EasyCaching.Bus.Redis/RedisBusServiceCollectionExtensions.cs create mode 100644 src/EasyCaching.Core/Bus/EasyCachingMessage.cs rename src/EasyCaching.Core/{ => Bus}/IEasyCachingBus.cs (100%) create mode 100644 src/EasyCaching.Core/Bus/IEasyCachingPublisher.cs create mode 100644 src/EasyCaching.Core/Bus/IEasyCachingSubscriber.cs delete mode 100644 src/EasyCaching.Core/EasyCachingMessage.cs delete mode 100644 src/EasyCaching.Core/IEasyCachingPublisher.cs delete mode 100644 src/EasyCaching.Core/IEasyCachingSubscriber.cs rename src/EasyCaching.Core/{ => Interceptor}/DefaultEasyCachingKeyGenerator.cs (100%) rename src/EasyCaching.Core/{Internal => Interceptor}/EasyCachingInterceptorAttribute.cs (100%) rename src/EasyCaching.Core/{ => Interceptor}/IEasyCachingKeyGenerator.cs (100%) rename src/EasyCaching.Core/{ => Serialization}/DefaultBinaryFormatterSerializer.cs (100%) rename src/EasyCaching.Core/{ => Serialization}/IEasyCachingSerializer.cs (100%) diff --git a/src/EasyCaching.Bus.RabbitMQ/DefaultRabbitMQBus.cs b/src/EasyCaching.Bus.RabbitMQ/DefaultRabbitMQBus.cs index 1c53ded3..80ee3fd2 100644 --- a/src/EasyCaching.Bus.RabbitMQ/DefaultRabbitMQBus.cs +++ b/src/EasyCaching.Bus.RabbitMQ/DefaultRabbitMQBus.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using global::RabbitMQ.Client.Events; using global::RabbitMQ.Client; + using System.Threading; /// /// Default RabbitMQ Bus. @@ -91,6 +92,11 @@ public Task PublishAsync(string channel, EasyCachingMessage message) throw new NotImplementedException(); } + public Task PublishAsync(string topic, EasyCachingMessage message, CancellationToken cancellationToken = default(CancellationToken)) + { + throw new NotImplementedException(); + } + /// /// Subscribe the specified channel. /// @@ -117,6 +123,11 @@ public void Subscribe(string channel) _subscriberChannel.BasicConsume("easycaching.queue", false, string.Empty, false, false, null, consumer); } + public void Subscribe(string topic, Action action) + { + throw new NotImplementedException(); + } + /// /// Subscribes the async. /// @@ -136,18 +147,6 @@ private void OnConsumerReceived(object sender, BasicDeliverEventArgs e) { var message = _serializer.Deserialize(e.Body); - switch (message.NotifyType) - { - case NotifyType.Add: - _localCachingProvider.Set(message.CacheKey, message.CacheValue, message.Expiration); - break; - case NotifyType.Update: - _localCachingProvider.Refresh(message.CacheKey, message.CacheValue, message.Expiration); - break; - case NotifyType.Delete: - _localCachingProvider.Remove(message.CacheKey); - break; - } } } } diff --git a/src/EasyCaching.Bus.Redis/IRedisSubscriberProvider.cs b/src/EasyCaching.Bus.Redis/Configurations/IRedisSubscriberProvider.cs similarity index 100% rename from src/EasyCaching.Bus.Redis/IRedisSubscriberProvider.cs rename to src/EasyCaching.Bus.Redis/Configurations/IRedisSubscriberProvider.cs diff --git a/src/EasyCaching.Bus.Redis/RedisBusOptions.cs b/src/EasyCaching.Bus.Redis/Configurations/RedisBusOptions.cs similarity index 75% rename from src/EasyCaching.Bus.Redis/RedisBusOptions.cs rename to src/EasyCaching.Bus.Redis/Configurations/RedisBusOptions.cs index b06e3474..9b63e057 100644 --- a/src/EasyCaching.Bus.Redis/RedisBusOptions.cs +++ b/src/EasyCaching.Bus.Redis/Configurations/RedisBusOptions.cs @@ -4,6 +4,6 @@ public class RedisBusOptions : BaseRedisOptions { - + public int Database { get; set; } = 0; } } diff --git a/src/EasyCaching.Bus.Redis/Configurations/RedisBusOptionsExtension.cs b/src/EasyCaching.Bus.Redis/Configurations/RedisBusOptionsExtension.cs new file mode 100644 index 00000000..749ae49d --- /dev/null +++ b/src/EasyCaching.Bus.Redis/Configurations/RedisBusOptionsExtension.cs @@ -0,0 +1,41 @@ +namespace EasyCaching.Bus.Redis +{ + using System; + using EasyCaching.Core; + using Microsoft.AspNetCore.Builder; + using Microsoft.Extensions.DependencyInjection; + using Microsoft.Extensions.DependencyInjection.Extensions; + + internal sealed class RedisBusOptionsExtension : IEasyCachingOptionsExtension + { + private readonly Action configure; + + public RedisBusOptionsExtension(Action configure) + { + this.configure = configure; + } + + /// + /// Adds the services. + /// + /// Services. + public void AddServices(IServiceCollection services) + { + services.AddOptions(); + services.Configure(configure); + + services.TryAddSingleton(); + services.TryAddSingleton(); + services.AddSingleton(); + } + + /// + /// Withs the services. + /// + /// Services. + public void WithServices(IApplicationBuilder services) + { + // Method intentionally left empty. + } + } +} diff --git a/src/EasyCaching.Bus.Redis/RedisSubscriberProvider.cs b/src/EasyCaching.Bus.Redis/Configurations/RedisSubscriberProvider.cs similarity index 60% rename from src/EasyCaching.Bus.Redis/RedisSubscriberProvider.cs rename to src/EasyCaching.Bus.Redis/Configurations/RedisSubscriberProvider.cs index c00b18f0..4dda4a6e 100644 --- a/src/EasyCaching.Bus.Redis/RedisSubscriberProvider.cs +++ b/src/EasyCaching.Bus.Redis/Configurations/RedisSubscriberProvider.cs @@ -42,20 +42,30 @@ public ISubscriber GetSubscriber() /// The connection multiplexer. private ConnectionMultiplexer CreateConnectionMultiplexer() { - var configurationOptions = new ConfigurationOptions + if (string.IsNullOrWhiteSpace(_options.Configuration)) { - ConnectTimeout = _options.ConnectionTimeout, - Password = _options.Password, - Ssl = _options.IsSsl, - SslHost = _options.SslHost, - }; + var configurationOptions = new ConfigurationOptions + { + ConnectTimeout = _options.ConnectionTimeout, + Password = _options.Password, + Ssl = _options.IsSsl, + SslHost = _options.SslHost, + AllowAdmin = _options.AllowAdmin, + DefaultDatabase = _options.Database, + AbortOnConnectFail = _options.AbortOnConnectFail, + }; - foreach (var endpoint in _options.Endpoints) + foreach (var endpoint in _options.Endpoints) + { + configurationOptions.EndPoints.Add(endpoint.Host, endpoint.Port); + } + + return ConnectionMultiplexer.Connect(configurationOptions.ToString()); + } + else { - configurationOptions.EndPoints.Add(endpoint.Host, endpoint.Port); + return ConnectionMultiplexer.Connect(_options.Configuration); } - - return ConnectionMultiplexer.Connect(configurationOptions.ToString()); } } } diff --git a/src/EasyCaching.Bus.Redis/DefaultRedisBus.cs b/src/EasyCaching.Bus.Redis/DefaultRedisBus.cs index b6e24146..4127d682 100644 --- a/src/EasyCaching.Bus.Redis/DefaultRedisBus.cs +++ b/src/EasyCaching.Bus.Redis/DefaultRedisBus.cs @@ -3,6 +3,8 @@ using EasyCaching.Core; using EasyCaching.Core.Internal; using StackExchange.Redis; + using System; + using System.Threading; using System.Threading.Tasks; /// @@ -21,14 +23,14 @@ public class DefaultRedisBus : IEasyCachingBus private readonly IRedisSubscriberProvider _subscriberProvider; /// - /// The serializer. + /// The handler. /// - private readonly IEasyCachingSerializer _serializer; + private Action _handler; /// - /// The local caching provider. + /// The serializer. /// - private readonly IEasyCachingProvider _localCachingProvider; + private readonly IEasyCachingSerializer _serializer; /// /// Initializes a new instance of the class. @@ -36,83 +38,60 @@ public class DefaultRedisBus : IEasyCachingBus /// Subscriber provider. public DefaultRedisBus( IRedisSubscriberProvider subscriberProvider, - IEasyCachingSerializer serializer, - IEasyCachingProvider localCachingProvider) + IEasyCachingSerializer serializer) { this._subscriberProvider = subscriberProvider; this._serializer = serializer; - this._localCachingProvider = localCachingProvider; - this._subscriber = _subscriberProvider.GetSubscriber(); } - /// - /// Subscribe the specified channel and notifyType. - /// - /// The subscribe. - /// Channel. - public void Subscribe(string channel) - { - _subscriber.Subscribe(channel, SubscribeHandle); - } - /// /// Subscribes the handle. /// /// Channel. /// Value. - private void SubscribeHandle(RedisChannel channel, RedisValue value) + private void OnMessage(RedisChannel channel, RedisValue value) { var message = _serializer.Deserialize(value); - switch (message.NotifyType) - { - case NotifyType.Add: - _localCachingProvider.Set(message.CacheKey, message.CacheValue, message.Expiration); - break; - case NotifyType.Update: - _localCachingProvider.Refresh(message.CacheKey, message.CacheValue, message.Expiration); - break; - case NotifyType.Delete: - _localCachingProvider.Remove(message.CacheKey); - break; - } + _handler?.Invoke(message); } /// - /// Subscribes the async. + /// Publish the specified topic and message. /// - /// The async. - /// Channel. - public async Task SubscribeAsync(string channel) + /// Topic. + /// Message. + public void Publish(string topic, EasyCachingMessage message) { - await _subscriber.SubscribeAsync(channel, SubscribeHandle); + ArgumentCheck.NotNullOrWhiteSpace(topic, nameof(topic)); + + _subscriber.Publish(topic, _serializer.Serialize(message)); } /// - /// Publish the specified channel and message. + /// Publishs the specified topic and message async. /// - /// The publish. - /// Channel. + /// The async. + /// Topic. /// Message. - public void Publish(string channel, EasyCachingMessage message) + /// Cancellation token. + public async Task PublishAsync(string topic, EasyCachingMessage message, CancellationToken cancellationToken = default(CancellationToken)) { - ArgumentCheck.NotNullOrWhiteSpace(channel, nameof(channel)); + ArgumentCheck.NotNullOrWhiteSpace(topic, nameof(topic)); - _subscriber.Publish(channel, _serializer.Serialize(message)); + await _subscriber.PublishAsync(topic, _serializer.Serialize(message)); } /// - /// Publishs the async. + /// Subscribe the specified topic and action. /// - /// The async. - /// Channel. - /// Message. - public async Task PublishAsync(string channel, EasyCachingMessage message) + /// Topic. + /// Action. + public void Subscribe(string topic, Action action) { - ArgumentCheck.NotNullOrWhiteSpace(channel, nameof(channel)); - - await _subscriber.PublishAsync(channel, _serializer.Serialize(message)); + _handler = action; + _subscriber.Subscribe(topic, OnMessage); } } } diff --git a/src/EasyCaching.Bus.Redis/EasyCaching.Bus.Redis.csproj b/src/EasyCaching.Bus.Redis/EasyCaching.Bus.Redis.csproj index 294d8dd9..ef0b5c02 100644 --- a/src/EasyCaching.Bus.Redis/EasyCaching.Bus.Redis.csproj +++ b/src/EasyCaching.Bus.Redis/EasyCaching.Bus.Redis.csproj @@ -24,4 +24,10 @@ + + + + + + diff --git a/src/EasyCaching.Bus.Redis/EasyCachingOptionsExtensions.cs b/src/EasyCaching.Bus.Redis/EasyCachingOptionsExtensions.cs new file mode 100644 index 00000000..7acca42c --- /dev/null +++ b/src/EasyCaching.Bus.Redis/EasyCachingOptionsExtensions.cs @@ -0,0 +1,61 @@ +namespace EasyCaching.Bus.Redis +{ + using EasyCaching.Core; + using Microsoft.Extensions.Configuration; + using System; + + /// + /// EasyCaching options extensions. + /// + public static class EasyCachingOptionsExtensions + { + /// + /// Uses the redis bus. + /// + /// The redis bus. + /// Options. + /// Configure. + public static EasyCachingOptions UseRedisBus(this EasyCachingOptions options, Action configure) + { + if (configure == null) + { + throw new ArgumentNullException(nameof(configure)); + } + + options.RegisterExtension(new RedisBusOptionsExtension(configure)); + return options; + } + + + /// + /// Uses the redis bus. + /// + /// The redis bus. + /// Options. + /// Configuration. + /// Section name. + public static EasyCachingOptions UseRedisBus(this EasyCachingOptions options, IConfiguration configuration, string sectionName = "redisbus") + { + var dbConfig = configuration.GetSection(sectionName); + var redisOptions = new RedisBusOptions(); + dbConfig.Bind(redisOptions); + + void configure(RedisBusOptions x) + { + x.AbortOnConnectFail = redisOptions.AbortOnConnectFail; + x.AllowAdmin = redisOptions.AllowAdmin; + x.Configuration = redisOptions.Configuration; + x.ConnectionTimeout = redisOptions.ConnectionTimeout; + x.Database = redisOptions.Database; + x.IsSsl = redisOptions.IsSsl; + x.Password = redisOptions.Password; + x.SslHost = redisOptions.SslHost; + + foreach (var item in redisOptions.Endpoints) x.Endpoints.Add(item); + } + + options.RegisterExtension(new RedisBusOptionsExtension(configure)); + return options; + } + } +} diff --git a/src/EasyCaching.Bus.Redis/RedisBusServiceCollectionExtensions.cs b/src/EasyCaching.Bus.Redis/RedisBusServiceCollectionExtensions.cs deleted file mode 100644 index d0ca7f73..00000000 --- a/src/EasyCaching.Bus.Redis/RedisBusServiceCollectionExtensions.cs +++ /dev/null @@ -1,38 +0,0 @@ -namespace EasyCaching.Bus.Redis -{ - using EasyCaching.Core; - using EasyCaching.Core.Internal; - using Microsoft.Extensions.DependencyInjection; - using Microsoft.Extensions.DependencyInjection.Extensions; - using System; - - /// - /// Redis bus service collection extensions. - /// - public static class RedisBusServiceCollectionExtensions - { - /// - /// Adds the default redis bus. - /// - /// The default redis bus. - /// Services. - /// Options action. - public static IServiceCollection AddDefaultRedisBus(this IServiceCollection services, Action optionsAction) - { - ArgumentCheck.NotNull(services, nameof(services)); - ArgumentCheck.NotNull(optionsAction, nameof(optionsAction)); - - var options = new RedisBusOptions(); - optionsAction?.Invoke(options); - services.AddSingleton(options); - - services.TryAddSingleton(); - services.TryAddSingleton(); - services.TryAddSingleton(); - services.TryAddSingleton(); - //services.TryAddSingleton(); - - return services; - } - } -} diff --git a/src/EasyCaching.Core/Bus/EasyCachingMessage.cs b/src/EasyCaching.Core/Bus/EasyCachingMessage.cs new file mode 100644 index 00000000..9a31b39d --- /dev/null +++ b/src/EasyCaching.Core/Bus/EasyCachingMessage.cs @@ -0,0 +1,9 @@ +namespace EasyCaching.Core +{ + public class EasyCachingMessage + { + public string[] CacheKeys { get; set; } + + public string Id { get; set; } + } +} diff --git a/src/EasyCaching.Core/IEasyCachingBus.cs b/src/EasyCaching.Core/Bus/IEasyCachingBus.cs similarity index 100% rename from src/EasyCaching.Core/IEasyCachingBus.cs rename to src/EasyCaching.Core/Bus/IEasyCachingBus.cs diff --git a/src/EasyCaching.Core/Bus/IEasyCachingPublisher.cs b/src/EasyCaching.Core/Bus/IEasyCachingPublisher.cs new file mode 100644 index 00000000..f706614b --- /dev/null +++ b/src/EasyCaching.Core/Bus/IEasyCachingPublisher.cs @@ -0,0 +1,27 @@ +namespace EasyCaching.Core +{ + using System.Threading; + using System.Threading.Tasks; + + /// + /// EasyCaching publisher. + /// + public interface IEasyCachingPublisher + { + /// + /// Publish the specified topic and message. + /// + /// Topic. + /// Message. + void Publish(string topic, EasyCachingMessage message); + + /// + /// Publishs the specified topic and message. + /// + /// The async. + /// Topic. + /// Message. + /// Cancellation token. + Task PublishAsync(string topic, EasyCachingMessage message, CancellationToken cancellationToken = default(CancellationToken)); + } +} diff --git a/src/EasyCaching.Core/Bus/IEasyCachingSubscriber.cs b/src/EasyCaching.Core/Bus/IEasyCachingSubscriber.cs new file mode 100644 index 00000000..a66753c2 --- /dev/null +++ b/src/EasyCaching.Core/Bus/IEasyCachingSubscriber.cs @@ -0,0 +1,12 @@ +namespace EasyCaching.Core +{ + using System; + + /// + /// EasyCaching subscriber. + /// + public interface IEasyCachingSubscriber + { + void Subscribe(string topic, Action action); + } +} diff --git a/src/EasyCaching.Core/EasyCaching.Core.csproj b/src/EasyCaching.Core/EasyCaching.Core.csproj index cafa2054..0536649c 100644 --- a/src/EasyCaching.Core/EasyCaching.Core.csproj +++ b/src/EasyCaching.Core/EasyCaching.Core.csproj @@ -23,6 +23,9 @@ + + + diff --git a/src/EasyCaching.Core/EasyCachingMessage.cs b/src/EasyCaching.Core/EasyCachingMessage.cs deleted file mode 100644 index ee2921da..00000000 --- a/src/EasyCaching.Core/EasyCachingMessage.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace EasyCaching.Core -{ - using EasyCaching.Core.Internal; - using System; - - public class EasyCachingMessage - { - public string CacheKey { get; set; } - - public object CacheValue { get; set; } - - public TimeSpan Expiration { get; set; } - - public NotifyType NotifyType { get; set; } - } -} diff --git a/src/EasyCaching.Core/IEasyCachingPublisher.cs b/src/EasyCaching.Core/IEasyCachingPublisher.cs deleted file mode 100644 index 6b05d88f..00000000 --- a/src/EasyCaching.Core/IEasyCachingPublisher.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace EasyCaching.Core -{ - using System; - using System.Threading.Tasks; - - /// - /// EasyCaching publisher. - /// - public interface IEasyCachingPublisher - { - /// - /// Publish the specified channel and message. - /// - /// The publish. - /// Channel. - /// Message. - /// The 1st type parameter. - void Publish(string channel, EasyCachingMessage message); - - /// - /// Publishs the specified channel and message async. - /// - /// The async. - /// Channel. - /// Message. - /// The 1st type parameter. - Task PublishAsync(string channel, EasyCachingMessage message); - } -} diff --git a/src/EasyCaching.Core/IEasyCachingSubscriber.cs b/src/EasyCaching.Core/IEasyCachingSubscriber.cs deleted file mode 100644 index 018e93d4..00000000 --- a/src/EasyCaching.Core/IEasyCachingSubscriber.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace EasyCaching.Core -{ - using System.Threading.Tasks; - - /// - /// EasyCaching subscriber. - /// - public interface IEasyCachingSubscriber - { - /// - /// Subscribe the specified channel with notifyType. - /// - /// Channel. - void Subscribe(string channel); - - /// - /// Subscribes the specified channel with notifyType async. - /// - /// The async. - /// Channel. - Task SubscribeAsync(string channel); - } -} diff --git a/src/EasyCaching.Core/DefaultEasyCachingKeyGenerator.cs b/src/EasyCaching.Core/Interceptor/DefaultEasyCachingKeyGenerator.cs similarity index 100% rename from src/EasyCaching.Core/DefaultEasyCachingKeyGenerator.cs rename to src/EasyCaching.Core/Interceptor/DefaultEasyCachingKeyGenerator.cs diff --git a/src/EasyCaching.Core/Internal/EasyCachingInterceptorAttribute.cs b/src/EasyCaching.Core/Interceptor/EasyCachingInterceptorAttribute.cs similarity index 100% rename from src/EasyCaching.Core/Internal/EasyCachingInterceptorAttribute.cs rename to src/EasyCaching.Core/Interceptor/EasyCachingInterceptorAttribute.cs diff --git a/src/EasyCaching.Core/IEasyCachingKeyGenerator.cs b/src/EasyCaching.Core/Interceptor/IEasyCachingKeyGenerator.cs similarity index 100% rename from src/EasyCaching.Core/IEasyCachingKeyGenerator.cs rename to src/EasyCaching.Core/Interceptor/IEasyCachingKeyGenerator.cs diff --git a/src/EasyCaching.Core/DefaultBinaryFormatterSerializer.cs b/src/EasyCaching.Core/Serialization/DefaultBinaryFormatterSerializer.cs similarity index 100% rename from src/EasyCaching.Core/DefaultBinaryFormatterSerializer.cs rename to src/EasyCaching.Core/Serialization/DefaultBinaryFormatterSerializer.cs diff --git a/src/EasyCaching.Core/IEasyCachingSerializer.cs b/src/EasyCaching.Core/Serialization/IEasyCachingSerializer.cs similarity index 100% rename from src/EasyCaching.Core/IEasyCachingSerializer.cs rename to src/EasyCaching.Core/Serialization/IEasyCachingSerializer.cs From 129a1cf31aa9c42f56fa6bee2cfde69b0570b521 Mon Sep 17 00:00:00 2001 From: catcherwong Date: Fri, 1 Feb 2019 12:03:33 +0800 Subject: [PATCH 03/20] :sparkles: NullEasyCachingBus. --- .../Bus/NullEasyCachingBus.cs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/EasyCaching.Core/Bus/NullEasyCachingBus.cs diff --git a/src/EasyCaching.Core/Bus/NullEasyCachingBus.cs b/src/EasyCaching.Core/Bus/NullEasyCachingBus.cs new file mode 100644 index 00000000..c8ac5d3e --- /dev/null +++ b/src/EasyCaching.Core/Bus/NullEasyCachingBus.cs @@ -0,0 +1,28 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace EasyCaching.Core +{ + public class NullEasyCachingBus : IEasyCachingBus + { + public static readonly NullEasyCachingBus Instance = new NullEasyCachingBus(); + + public void Dispose() { } + + public void Publish(string topic, EasyCachingMessage message) + { + + } + + public Task PublishAsync(string topic, EasyCachingMessage message, CancellationToken cancellationToken = default(CancellationToken)) + { + return Task.CompletedTask; + } + + public void Subscribe(string topic, Action action) + { + + } + } +} From 63cb2c2aa4e100688e3201e4ff8f6bd81113b383 Mon Sep 17 00:00:00 2001 From: catcherwong Date: Sat, 2 Feb 2019 09:26:25 +0800 Subject: [PATCH 04/20] :construction: Redis Bus And Hybrid Caching Provider. --- build/releasenotes.props | 3 + build/version.props | 1 + .../Configurations/RedisSubscriberProvider.cs | 5 +- .../EasyCaching.Bus.Redis.csproj | 25 ++- .../Bus/EasyCachingMessage.cs | 9 +- .../{Internal => Interceptor}/ICachable.cs | 0 .../EasyCachingOptionsExtensions.cs | 5 +- .../HybridCacheOptionsExtension.cs | 13 ++ .../Configurations/HybridCachingOptions.cs | 18 ++ .../EasyCaching.HybridCache.csproj | 1 + .../HybridCachingProvider.cs | 160 ++++++++++++++++-- .../NotFoundCachingProviderException.cs | 10 ++ .../DefaultRedisCachingProvider.cs | 2 +- 13 files changed, 221 insertions(+), 31 deletions(-) rename src/EasyCaching.Core/{Internal => Interceptor}/ICachable.cs (100%) create mode 100644 src/EasyCaching.HybridCache/Configurations/HybridCachingOptions.cs create mode 100644 src/EasyCaching.HybridCache/NotFoundCachingProviderException.cs diff --git a/build/releasenotes.props b/build/releasenotes.props index 97c4d902..c892258f 100644 --- a/build/releasenotes.props +++ b/build/releasenotes.props @@ -40,5 +40,8 @@ 1. Init. + + 1. Init. + diff --git a/build/version.props b/build/version.props index 2b074824..2849f92f 100644 --- a/build/version.props +++ b/build/version.props @@ -13,5 +13,6 @@ 0.3.5 0.3.5 0.1.0 + 0.1.0 diff --git a/src/EasyCaching.Bus.Redis/Configurations/RedisSubscriberProvider.cs b/src/EasyCaching.Bus.Redis/Configurations/RedisSubscriberProvider.cs index 4dda4a6e..4bc0769b 100644 --- a/src/EasyCaching.Bus.Redis/Configurations/RedisSubscriberProvider.cs +++ b/src/EasyCaching.Bus.Redis/Configurations/RedisSubscriberProvider.cs @@ -1,5 +1,6 @@ namespace EasyCaching.Bus.Redis { + using Microsoft.Extensions.Options; using StackExchange.Redis; using System; @@ -22,9 +23,9 @@ public class RedisSubscriberProvider : IRedisSubscriberProvider /// Initializes a new instance of the class. /// /// Options. - public RedisSubscriberProvider(RedisBusOptions options) + public RedisSubscriberProvider(IOptions options) { - _options = options; + _options = options.Value; _connectionMultiplexer = new Lazy(CreateConnectionMultiplexer); } diff --git a/src/EasyCaching.Bus.Redis/EasyCaching.Bus.Redis.csproj b/src/EasyCaching.Bus.Redis/EasyCaching.Bus.Redis.csproj index ef0b5c02..861a4399 100644 --- a/src/EasyCaching.Bus.Redis/EasyCaching.Bus.Redis.csproj +++ b/src/EasyCaching.Bus.Redis/EasyCaching.Bus.Redis.csproj @@ -4,21 +4,23 @@ netstandard2.0 Catcher Wong Catcher Wong - 0.1.0 + $(EasyCachingRedisBusPackageVersion) EasyCaching is a open source caching library that contains basic opreations of caching. - Caching,Cache,Distributed Cache,Memory Cache,Interceptor,Synchronization - https://github.com/catcherwong/EasyCaching - https://github.com/catcherwong/EasyCaching/blob/master/LICENSE - https://github.com/catcherwong/EasyCaching - https://github.com/catcherwong/EasyCaching - https://raw.githubusercontent.com/catcherwong/EasyCaching/master/media/easycaching-icon.png - + Bus,Hybrid Caching,Redis,Synchronization + https://github.com/dotnetcore/EasyCaching + https://github.com/dotnetcore/EasyCaching/blob/master/LICENSE + https://github.com/dotnetcore/EasyCaching + https://github.com/dotnetcore/EasyCaching + https://raw.githubusercontent.com/dotnetcore/EasyCaching/master/media/easycaching-icon.png + + $(EasyCachingRedisBusPackageVersion) + - + @@ -26,8 +28,5 @@ - - - - + diff --git a/src/EasyCaching.Core/Bus/EasyCachingMessage.cs b/src/EasyCaching.Core/Bus/EasyCachingMessage.cs index 9a31b39d..7ef9ae42 100644 --- a/src/EasyCaching.Core/Bus/EasyCachingMessage.cs +++ b/src/EasyCaching.Core/Bus/EasyCachingMessage.cs @@ -1,9 +1,14 @@ namespace EasyCaching.Core { + using System; + + [Serializable] public class EasyCachingMessage { + /// + /// Gets or sets the cache keys. + /// + /// The cache keys. public string[] CacheKeys { get; set; } - - public string Id { get; set; } } } diff --git a/src/EasyCaching.Core/Internal/ICachable.cs b/src/EasyCaching.Core/Interceptor/ICachable.cs similarity index 100% rename from src/EasyCaching.Core/Internal/ICachable.cs rename to src/EasyCaching.Core/Interceptor/ICachable.cs diff --git a/src/EasyCaching.HybridCache/Configurations/EasyCachingOptionsExtensions.cs b/src/EasyCaching.HybridCache/Configurations/EasyCachingOptionsExtensions.cs index d66a64ed..f5612b25 100644 --- a/src/EasyCaching.HybridCache/Configurations/EasyCachingOptionsExtensions.cs +++ b/src/EasyCaching.HybridCache/Configurations/EasyCachingOptionsExtensions.cs @@ -1,5 +1,6 @@ namespace EasyCaching.HybridCache { + using System; using EasyCaching.Core; /// @@ -12,9 +13,9 @@ public static class EasyCachingOptionsExtensions /// /// The hybrid. /// Options. - public static EasyCachingOptions UseHybrid(this EasyCachingOptions options) + public static EasyCachingOptions UseHybrid(this EasyCachingOptions options, Action configure) { - options.RegisterExtension(new HybridCacheOptionsExtension()); + options.RegisterExtension(new HybridCacheOptionsExtension(configure)); return options; } diff --git a/src/EasyCaching.HybridCache/Configurations/HybridCacheOptionsExtension.cs b/src/EasyCaching.HybridCache/Configurations/HybridCacheOptionsExtension.cs index cfb10801..c714fcfb 100644 --- a/src/EasyCaching.HybridCache/Configurations/HybridCacheOptionsExtension.cs +++ b/src/EasyCaching.HybridCache/Configurations/HybridCacheOptionsExtension.cs @@ -1,5 +1,6 @@ namespace EasyCaching.HybridCache { + using System; using EasyCaching.Core; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; @@ -10,12 +11,24 @@ /// internal sealed class HybridCacheOptionsExtension : IEasyCachingOptionsExtension { + /// + /// The configure. + /// + private readonly Action _configure; + + public HybridCacheOptionsExtension( Action configure) + { + this._configure = configure; + } + /// /// Adds the services. /// /// Services. public void AddServices(IServiceCollection services) { + services.AddOptions(); + services.Configure(_configure); services.TryAddSingleton(); } diff --git a/src/EasyCaching.HybridCache/Configurations/HybridCachingOptions.cs b/src/EasyCaching.HybridCache/Configurations/HybridCachingOptions.cs new file mode 100644 index 00000000..a77f4845 --- /dev/null +++ b/src/EasyCaching.HybridCache/Configurations/HybridCachingOptions.cs @@ -0,0 +1,18 @@ +namespace EasyCaching.HybridCache +{ + public class HybridCachingOptions + { + /// + /// Gets or sets the name of the topic. + /// + /// The name of the topic. + public string TopicName { get; set; } + + /// + /// Gets or sets a value indicating whether this + /// enable logging. + /// + /// true if enable logging; otherwise, false. + public bool EnableLogging { get; set; } + } +} diff --git a/src/EasyCaching.HybridCache/EasyCaching.HybridCache.csproj b/src/EasyCaching.HybridCache/EasyCaching.HybridCache.csproj index 3eef1a2d..9331ebc7 100644 --- a/src/EasyCaching.HybridCache/EasyCaching.HybridCache.csproj +++ b/src/EasyCaching.HybridCache/EasyCaching.HybridCache.csproj @@ -25,6 +25,7 @@ + diff --git a/src/EasyCaching.HybridCache/HybridCachingProvider.cs b/src/EasyCaching.HybridCache/HybridCachingProvider.cs index c006c95f..996c0082 100644 --- a/src/EasyCaching.HybridCache/HybridCachingProvider.cs +++ b/src/EasyCaching.HybridCache/HybridCachingProvider.cs @@ -2,42 +2,99 @@ { using EasyCaching.Core; using EasyCaching.Core.Internal; + using Microsoft.Extensions.Options; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; + using Microsoft.Extensions.Logging; /// /// Hybrid caching provider. /// public class HybridCachingProvider : IHybridCachingProvider { - private readonly IEasyCachingProvider _localCache; - private readonly IEasyCachingProvider _distributedCache; - private readonly IEasyCachingBus _bus; - + /// + /// The local cache. + /// + private readonly IEasyCachingProvider _localCache; + /// + /// The distributed cache. + /// + private readonly IEasyCachingProvider _distributedCache; + /// + /// The bus. + /// + private readonly IEasyCachingBus _bus; + /// + /// The options. + /// + private readonly HybridCachingOptions _options; + /// + /// The logger. + /// + private readonly ILogger _logger; + + /// + /// Initializes a new instance of the class. + /// + /// Options accs. + /// Providers. + /// Bus. + /// Logger factory. public HybridCachingProvider( - IEnumerable providers + IOptions optionsAccs + , IEnumerable providers , IEasyCachingBus bus = null + , ILoggerFactory loggerFactory = null ) { ArgumentCheck.NotNullAndCountGTZero(providers, nameof(providers)); - var local = providers.OrderBy(x => x.Order).FirstOrDefault(x=>!x.IsDistributedCache); + this._options = optionsAccs.Value; + + ArgumentCheck.NotNullOrWhiteSpace(_options.TopicName, nameof(_options.TopicName)); + + this._logger = loggerFactory?.CreateLogger(); - if (local == null) throw new Exception(); + //Here use the order to distinguish traditional provider + var local = providers.OrderBy(x => x.Order).FirstOrDefault(x => !x.IsDistributedCache); + + if (local == null) throw new NotFoundCachingProviderException("Can not found any local caching providers."); else this._localCache = local; + //Here use the order to distinguish traditional provider var distributed = providers.OrderBy(x => x.Order).FirstOrDefault(x => x.IsDistributedCache); - if (distributed == null) throw new Exception(); + if (distributed == null) throw new NotFoundCachingProviderException("Can not found any distributed caching providers."); else this._distributedCache = distributed; - this._bus = bus; + this._bus = bus ?? NullEasyCachingBus.Instance; + this._bus.Subscribe(_options.TopicName, OnMessage); + } + /// + /// Ons the message. + /// + /// Message. + private void OnMessage(EasyCachingMessage message) + { + foreach (var item in message.CacheKeys) + { + _localCache.Remove(item); + if (_options.EnableLogging) + { + _logger.LogTrace($"remove local cache that cache key is {item}"); + } + } } + /// + /// Exists the specified cacheKey. + /// + /// The exists. + /// Cache key. public bool Exists(string cacheKey) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); @@ -45,6 +102,11 @@ public bool Exists(string cacheKey) return _distributedCache.Exists(cacheKey); } + /// + /// Existses the specified cacheKey async. + /// + /// The async. + /// Cache key. public async Task ExistsAsync(string cacheKey) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); @@ -52,17 +114,28 @@ public async Task ExistsAsync(string cacheKey) return await _distributedCache.ExistsAsync(cacheKey); } + /// + /// Get the specified cacheKey. + /// + /// The get. + /// Cache key. + /// The 1st type parameter. public CacheValue Get(string cacheKey) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); var cacheValue = _localCache.Get(cacheKey); - if(cacheValue.HasValue) + if (cacheValue.HasValue) { return cacheValue; } + if(_options.EnableLogging) + { + _logger.LogTrace($"local cache can not get the value of {cacheKey}"); + } + cacheValue = _distributedCache.Get(cacheKey); if (cacheValue.HasValue) @@ -72,9 +145,20 @@ public CacheValue Get(string cacheKey) return cacheValue; } + if (_options.EnableLogging) + { + _logger.LogTrace($"distributed cache can not get the value of {cacheKey}"); + } + return CacheValue.NoValue; } + /// + /// Gets the specified cacheKey async. + /// + /// The async. + /// Cache key. + /// The 1st type parameter. public async Task> GetAsync(string cacheKey) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); @@ -86,6 +170,11 @@ public async Task> GetAsync(string cacheKey) return cacheValue; } + if (_options.EnableLogging) + { + _logger.LogTrace($"local cache can not get the value of {cacheKey}"); + } + cacheValue = await _distributedCache.GetAsync(cacheKey); if (cacheValue.HasValue) @@ -95,9 +184,18 @@ public async Task> GetAsync(string cacheKey) return cacheValue; } + if (_options.EnableLogging) + { + _logger.LogTrace($"distributed cache can not get the value of {cacheKey}"); + } + return CacheValue.NoValue; } + /// + /// Remove the specified cacheKey. + /// + /// Cache key. public void Remove(string cacheKey) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); @@ -106,8 +204,14 @@ public void Remove(string cacheKey) _localCache.Remove(cacheKey); //send message to bus + _bus.Publish(_options.TopicName, new EasyCachingMessage { CacheKeys = new string[] { cacheKey } }); } + /// + /// Removes the specified cacheKey async. + /// + /// The async. + /// Cache key. public async Task RemoveAsync(string cacheKey) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); @@ -116,8 +220,16 @@ public async Task RemoveAsync(string cacheKey) await _localCache.RemoveAsync(cacheKey); //send message to bus + await _bus.PublishAsync(_options.TopicName, new EasyCachingMessage { CacheKeys = new string[] { cacheKey } }); } + /// + /// Set the specified cacheKey, cacheValue and expiration. + /// + /// Cache key. + /// Cache value. + /// Expiration. + /// The 1st type parameter. public void Set(string cacheKey, T cacheValue, TimeSpan expiration) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); @@ -126,8 +238,17 @@ public void Set(string cacheKey, T cacheValue, TimeSpan expiration) _distributedCache.Set(cacheKey, cacheValue, expiration); //send message to bus + _bus.Publish(_options.TopicName, new EasyCachingMessage { CacheKeys = new string[] { cacheKey } }); } + /// + /// Sets the specified cacheKey, cacheValue and expiration async. + /// + /// The async. + /// Cache key. + /// Cache value. + /// Expiration. + /// The 1st type parameter. public async Task SetAsync(string cacheKey, T cacheValue, TimeSpan expiration) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); @@ -136,15 +257,24 @@ public async Task SetAsync(string cacheKey, T cacheValue, TimeSpan expiration await _distributedCache.SetAsync(cacheKey, cacheValue, expiration); //send message to bus + await _bus.PublishAsync(_options.TopicName, new EasyCachingMessage { CacheKeys = new string[] { cacheKey } }); } + /// + /// Tries the set. + /// + /// true, if set was tryed, false otherwise. + /// Cache key. + /// Cache value. + /// Expiration. + /// The 1st type parameter. public bool TrySet(string cacheKey, T cacheValue, TimeSpan expiration) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); var flag = _distributedCache.TrySet(cacheKey, cacheValue, expiration); - if(flag) + if (flag) { _localCache.Set(cacheKey, cacheValue, expiration); } @@ -152,6 +282,14 @@ public bool TrySet(string cacheKey, T cacheValue, TimeSpan expiration) return flag; } + /// + /// Tries the set async. + /// + /// The set async. + /// Cache key. + /// Cache value. + /// Expiration. + /// The 1st type parameter. public async Task TrySetAsync(string cacheKey, T cacheValue, TimeSpan expiration) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); diff --git a/src/EasyCaching.HybridCache/NotFoundCachingProviderException.cs b/src/EasyCaching.HybridCache/NotFoundCachingProviderException.cs new file mode 100644 index 00000000..4bc39db4 --- /dev/null +++ b/src/EasyCaching.HybridCache/NotFoundCachingProviderException.cs @@ -0,0 +1,10 @@ +namespace EasyCaching.HybridCache +{ + using System; + + public class NotFoundCachingProviderException : Exception + { + public NotFoundCachingProviderException(string message) : base(message) + { } + } +} diff --git a/src/EasyCaching.Redis/DefaultRedisCachingProvider.cs b/src/EasyCaching.Redis/DefaultRedisCachingProvider.cs index cf6fd095..30bc4bb9 100755 --- a/src/EasyCaching.Redis/DefaultRedisCachingProvider.cs +++ b/src/EasyCaching.Redis/DefaultRedisCachingProvider.cs @@ -59,7 +59,7 @@ public partial class DefaultRedisCachingProvider : IEasyCachingProvider /// /// is distributed cache. /// - public bool IsDistributedCache => false; + public bool IsDistributedCache => true; /// /// Gets the order. From 89af8861f088cce36f4426a629abb33dc702d5d0 Mon Sep 17 00:00:00 2001 From: catcherwong Date: Sat, 2 Feb 2019 09:28:08 +0800 Subject: [PATCH 05/20] :fire: Remove IEasyCaching. --- src/EasyCaching.Core/Internal/IEasyCaching.cs | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 src/EasyCaching.Core/Internal/IEasyCaching.cs diff --git a/src/EasyCaching.Core/Internal/IEasyCaching.cs b/src/EasyCaching.Core/Internal/IEasyCaching.cs deleted file mode 100644 index f2070ea3..00000000 --- a/src/EasyCaching.Core/Internal/IEasyCaching.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace EasyCaching.Core.Internal -{ - /// - /// Easy caching. - /// - [System.Obsolete("Should Replace with Attribute")] - public interface IEasyCaching - { - } -} From 6b85d034cd23ea39253c287930c9c929af324884 Mon Sep 17 00:00:00 2001 From: catcherwong Date: Sat, 2 Feb 2019 09:29:29 +0800 Subject: [PATCH 06/20] :fire: Remove NotifyType. --- src/EasyCaching.Core/Internal/NotifyType.cs | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 src/EasyCaching.Core/Internal/NotifyType.cs diff --git a/src/EasyCaching.Core/Internal/NotifyType.cs b/src/EasyCaching.Core/Internal/NotifyType.cs deleted file mode 100644 index 8eb65d45..00000000 --- a/src/EasyCaching.Core/Internal/NotifyType.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace EasyCaching.Core.Internal -{ - /// - /// Notify type. - /// - public enum NotifyType - { - Add = 0, - Update = 1, - Delete = 2 - } -} From 27ae774bd8d256e0063b28ba9a61313b6e19c0e2 Mon Sep 17 00:00:00 2001 From: catcherwong Date: Sat, 2 Feb 2019 13:04:37 +0800 Subject: [PATCH 07/20] :art: mproving structure of the code. --- .../Services/IAspectCoreService.cs | 4 +- .../Services/ICastleService.cs | 1 + sample/EasyCaching.Demo.Providers/Startup.cs | 1 + .../DefaultRabbitMQBus.cs | 2 + .../RabbitMQBusOptions.cs | 1 + .../RabbitMQBusServiceCollectionExtensions.cs | 5 +- .../Configurations/RedisBusOptions.cs | 4 +- .../RedisBusOptionsExtension.cs | 4 +- src/EasyCaching.Bus.Redis/DefaultRedisBus.cs | 3 +- .../EasyCachingOptionsExtensions.cs | 1 + .../EasyCachingOptionsExtensions.cs | 4 +- .../Configurations/RedisOptions.cs | 2 +- .../Configurations/RedisOptionsExtension.cs | 4 +- .../DefaultCSRedisCachingProvider.cs | 1 + .../Bus/EasyCachingMessage.cs | 5 +- src/EasyCaching.Core/Bus/IEasyCachingBus.cs | 2 +- .../Bus/IEasyCachingPublisher.cs | 2 +- .../Bus/IEasyCachingSubscriber.cs | 7 +- .../Bus/NullEasyCachingBus.cs | 42 +++++++++-- .../BaseProviderOptions.cs | 2 +- .../BaseRabbitMQOptions.cs | 2 +- .../BaseRedisOptions.cs | 2 +- ...EasyCachingApplicationBuliderExtensions.cs | 7 +- .../Configurations/EasyCachingOptions.cs | 4 +- .../EasyCachingServiceCollectionExtensions.cs | 12 ++-- .../IEasyCachingOptionsExtension.cs | 2 +- .../ServerEndPoint.cs | 6 +- src/EasyCaching.Core/EasyCaching.Core.csproj | 2 + .../IEasyCachingProviderFactory.cs | 31 -------- .../IHybridCachingProvider.cs | 72 +++++++++++++++++-- src/EasyCaching.Core/IRedisCachingProvider.cs | 6 ++ .../DefaultEasyCachingKeyGenerator.cs | 4 +- .../EasyCachingInterceptorAttribute.cs | 2 +- src/EasyCaching.Core/Interceptor/ICachable.cs | 2 +- .../Interceptor/IEasyCachingKeyGenerator.cs | 2 +- .../Internal/ArgumentCheck.cs | 2 +- .../{ => Internal}/CacheValue.cs | 0 .../{ => Internal}/CachingProviderType.cs | 0 .../{ => Internal}/EasyCachingConstValue.cs | 0 .../DefaultEasyCachingProviderFactory.cs | 42 +++++++++++ .../IEasyCachingProviderFactory.cs | 15 ++++ .../DefaultBinaryFormatterSerializer.cs | 2 +- .../Serialization/IEasyCachingSerializer.cs | 2 +- .../CacheStats.cs} | 50 ++++++------- .../Stats/CacheStatsCounter.cs | 34 +++++++++ src/EasyCaching.Core/Stats/StatsType.cs | 18 +++++ .../EasyCachingOptionsExtensions.cs | 2 +- .../HybridCacheOptionsExtension.cs | 1 + .../HybridCacheServiceCollectionExtensions.cs | 3 +- .../HybridCachingProvider.cs | 1 + .../EasyCachingOptionsExtensions.cs | 1 + .../Configurations/InMemoryOptions.cs | 2 +- .../InMemoryOptionsExtension.cs | 1 + ...eInterceptorServiceCollectionExtensions.cs | 1 + .../EasyCachingInterceptor.cs | 2 +- ...eInterceptorServiceCollectionExtensions.cs | 9 ++- .../EasyCachingInterceptor.cs | 6 +- .../EasyCachingOptionsExtensions.cs | 1 + .../Configurations/EasyCachingTranscoder.cs | 3 +- .../Configurations/MemcachedOptions.cs | 2 +- .../MemcachedOptionsExtension.cs | 6 +- .../MemcachedServiceCollectionExtensions.cs | 6 +- .../EasyCachingOptionsExtensions.cs | 1 + .../Configurations/RedisDBOptions.cs | 2 +- .../Configurations/RedisOptions.cs | 2 +- .../Configurations/RedisOptionsExtension.cs | 2 + .../DefaultRedisCachingProvider.cs | 10 +-- .../RedisCacheServiceCollectionExtensions.cs | 4 +- .../EasyCachingResponseCachingExtensions.cs | 2 +- .../EasyCachingOptionsExtensions.cs | 3 +- .../Configurations/SQLiteDBOptions.cs | 4 +- .../Configurations/SQLiteOptions.cs | 2 +- .../Configurations/SQLiteOptionsExtension.cs | 1 + .../SQLiteCacheServiceCollectionExtensions.cs | 1 - .../EasyCachingOptionsExtensions.cs | 2 +- .../Configurations/JsonOptionsExtension.cs | 5 +- .../DefaultJsonSerializer.cs | 3 +- ...onSerializerServiceCollectionExtensions.cs | 1 + .../EasyCachingOptionsExtensions.cs | 2 +- .../MessagePackOptionsExtension.cs | 3 +- .../DefaultMessagePackSerializer.cs | 6 +- ...ckSerializerServiceCollectionExtensions.cs | 4 +- .../EasyCachingOptionsExtensions.cs | 2 +- .../ProtobufOptionsExtension.cs | 3 +- .../DefaultProtobufSerializer.cs | 7 +- ...ufSerializerServiceCollectionExtensions.cs | 4 +- .../SerializerBenchmark.cs | 1 + .../CachingTests/RedisCachingProviderTest.cs | 1 + .../SERedisFeatureCachingProviderTest.cs | 3 +- .../Core/ArgumentCheckTest.cs | 2 +- .../DefaultEasyCachingKeyGeneratorTest.cs | 3 +- .../Infrastructure/IExampleService.cs | 4 +- .../AspectCoreInterceptorTest.cs | 11 ++- .../InterceptorTests/CastleInterceptorTest.cs | 22 +++--- .../SerializerTests/BaseSerializerTest.cs | 4 +- .../BinaryFormatterSerializerTest.cs | 2 +- ...rializerServiceCollectionExtensionsTest.cs | 1 + 97 files changed, 402 insertions(+), 193 deletions(-) rename src/EasyCaching.Core/{Internal => Configurations}/BaseProviderOptions.cs (97%) rename src/EasyCaching.Core/{Internal => Configurations}/BaseRabbitMQOptions.cs (97%) rename src/EasyCaching.Core/{Internal => Configurations}/BaseRedisOptions.cs (98%) rename src/EasyCaching.Core/{Internal => Configurations}/ServerEndPoint.cs (87%) delete mode 100644 src/EasyCaching.Core/IEasyCachingProviderFactory.cs rename src/EasyCaching.Core/{ => Internal}/CacheValue.cs (100%) rename src/EasyCaching.Core/{ => Internal}/CachingProviderType.cs (100%) rename src/EasyCaching.Core/{ => Internal}/EasyCachingConstValue.cs (100%) create mode 100644 src/EasyCaching.Core/ProviderFactory/DefaultEasyCachingProviderFactory.cs create mode 100644 src/EasyCaching.Core/ProviderFactory/IEasyCachingProviderFactory.cs rename src/EasyCaching.Core/{CacheStatsCounter.cs => Stats/CacheStats.cs} (61%) create mode 100644 src/EasyCaching.Core/Stats/CacheStatsCounter.cs create mode 100644 src/EasyCaching.Core/Stats/StatsType.cs diff --git a/sample/EasyCaching.Demo.Interceptors/Services/IAspectCoreService.cs b/sample/EasyCaching.Demo.Interceptors/Services/IAspectCoreService.cs index d9d6cdbd..ec52ea66 100644 --- a/sample/EasyCaching.Demo.Interceptors/Services/IAspectCoreService.cs +++ b/sample/EasyCaching.Demo.Interceptors/Services/IAspectCoreService.cs @@ -1,8 +1,8 @@ namespace EasyCaching.Demo.Interceptors.Services { - using EasyCaching.Core.Internal; using System.Threading.Tasks; - + using EasyCaching.Core.Interceptor; + public interface IAspectCoreService //: EasyCaching.Core.Internal.IEasyCaching { [EasyCachingAble(Expiration = 10)] diff --git a/sample/EasyCaching.Demo.Interceptors/Services/ICastleService.cs b/sample/EasyCaching.Demo.Interceptors/Services/ICastleService.cs index 709052d2..2bfc560d 100644 --- a/sample/EasyCaching.Demo.Interceptors/Services/ICastleService.cs +++ b/sample/EasyCaching.Demo.Interceptors/Services/ICastleService.cs @@ -1,6 +1,7 @@ namespace EasyCaching.Demo.Interceptors.Services { using System.Threading.Tasks; + using EasyCaching.Core.Interceptor; using EasyCaching.Core.Internal; public interface ICastleService diff --git a/sample/EasyCaching.Demo.Providers/Startup.cs b/sample/EasyCaching.Demo.Providers/Startup.cs index c2935895..4c41d77d 100644 --- a/sample/EasyCaching.Demo.Providers/Startup.cs +++ b/sample/EasyCaching.Demo.Providers/Startup.cs @@ -15,6 +15,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using System; + using EasyCaching.Core.Configurations; public class Startup { diff --git a/src/EasyCaching.Bus.RabbitMQ/DefaultRabbitMQBus.cs b/src/EasyCaching.Bus.RabbitMQ/DefaultRabbitMQBus.cs index 80ee3fd2..4e3489f4 100644 --- a/src/EasyCaching.Bus.RabbitMQ/DefaultRabbitMQBus.cs +++ b/src/EasyCaching.Bus.RabbitMQ/DefaultRabbitMQBus.cs @@ -8,6 +8,8 @@ using global::RabbitMQ.Client.Events; using global::RabbitMQ.Client; using System.Threading; + using EasyCaching.Core.Bus; + using EasyCaching.Core.Serialization; /// /// Default RabbitMQ Bus. diff --git a/src/EasyCaching.Bus.RabbitMQ/RabbitMQBusOptions.cs b/src/EasyCaching.Bus.RabbitMQ/RabbitMQBusOptions.cs index e3362857..63bb04c3 100644 --- a/src/EasyCaching.Bus.RabbitMQ/RabbitMQBusOptions.cs +++ b/src/EasyCaching.Bus.RabbitMQ/RabbitMQBusOptions.cs @@ -1,5 +1,6 @@ namespace EasyCaching.Bus.RabbitMQ { + using EasyCaching.Core.Configurations; using EasyCaching.Core.Internal; /// diff --git a/src/EasyCaching.Bus.RabbitMQ/RabbitMQBusServiceCollectionExtensions.cs b/src/EasyCaching.Bus.RabbitMQ/RabbitMQBusServiceCollectionExtensions.cs index 95a48491..0097aa99 100644 --- a/src/EasyCaching.Bus.RabbitMQ/RabbitMQBusServiceCollectionExtensions.cs +++ b/src/EasyCaching.Bus.RabbitMQ/RabbitMQBusServiceCollectionExtensions.cs @@ -1,10 +1,11 @@ namespace EasyCaching.Bus.RabbitMQ { + using System; using EasyCaching.Core; - using EasyCaching.Core.Internal; + using EasyCaching.Core.Bus; + using EasyCaching.Core.Serialization; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; - using System; /// /// RabbitMQ Bus service collection extensions. diff --git a/src/EasyCaching.Bus.Redis/Configurations/RedisBusOptions.cs b/src/EasyCaching.Bus.Redis/Configurations/RedisBusOptions.cs index 9b63e057..dff9b98b 100644 --- a/src/EasyCaching.Bus.Redis/Configurations/RedisBusOptions.cs +++ b/src/EasyCaching.Bus.Redis/Configurations/RedisBusOptions.cs @@ -1,7 +1,7 @@ namespace EasyCaching.Bus.Redis { - using EasyCaching.Core.Internal; - + using EasyCaching.Core.Configurations; + public class RedisBusOptions : BaseRedisOptions { public int Database { get; set; } = 0; diff --git a/src/EasyCaching.Bus.Redis/Configurations/RedisBusOptionsExtension.cs b/src/EasyCaching.Bus.Redis/Configurations/RedisBusOptionsExtension.cs index 749ae49d..ec4b0f9f 100644 --- a/src/EasyCaching.Bus.Redis/Configurations/RedisBusOptionsExtension.cs +++ b/src/EasyCaching.Bus.Redis/Configurations/RedisBusOptionsExtension.cs @@ -1,7 +1,9 @@ namespace EasyCaching.Bus.Redis { using System; - using EasyCaching.Core; + using EasyCaching.Core.Bus; + using EasyCaching.Core.Configurations; + using EasyCaching.Core.Serialization; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; diff --git a/src/EasyCaching.Bus.Redis/DefaultRedisBus.cs b/src/EasyCaching.Bus.Redis/DefaultRedisBus.cs index 4127d682..22c69ad8 100644 --- a/src/EasyCaching.Bus.Redis/DefaultRedisBus.cs +++ b/src/EasyCaching.Bus.Redis/DefaultRedisBus.cs @@ -1,7 +1,8 @@ namespace EasyCaching.Bus.Redis { using EasyCaching.Core; - using EasyCaching.Core.Internal; + using EasyCaching.Core.Bus; + using EasyCaching.Core.Serialization; using StackExchange.Redis; using System; using System.Threading; diff --git a/src/EasyCaching.Bus.Redis/EasyCachingOptionsExtensions.cs b/src/EasyCaching.Bus.Redis/EasyCachingOptionsExtensions.cs index 7acca42c..db87cd78 100644 --- a/src/EasyCaching.Bus.Redis/EasyCachingOptionsExtensions.cs +++ b/src/EasyCaching.Bus.Redis/EasyCachingOptionsExtensions.cs @@ -1,6 +1,7 @@ namespace EasyCaching.Bus.Redis { using EasyCaching.Core; + using EasyCaching.Core.Configurations; using Microsoft.Extensions.Configuration; using System; diff --git a/src/EasyCaching.CSRedis/Configurations/EasyCachingOptionsExtensions.cs b/src/EasyCaching.CSRedis/Configurations/EasyCachingOptionsExtensions.cs index 3f4fc825..908104f0 100644 --- a/src/EasyCaching.CSRedis/Configurations/EasyCachingOptionsExtensions.cs +++ b/src/EasyCaching.CSRedis/Configurations/EasyCachingOptionsExtensions.cs @@ -1,9 +1,9 @@ namespace EasyCaching.CSRedis { + using System; using EasyCaching.Core; - using EasyCaching.Core.Internal; + using EasyCaching.Core.Configurations; using Microsoft.Extensions.Configuration; - using System; /// /// EasyCaching options extensions. diff --git a/src/EasyCaching.CSRedis/Configurations/RedisOptions.cs b/src/EasyCaching.CSRedis/Configurations/RedisOptions.cs index 4e2cd5a2..2e3f01d9 100755 --- a/src/EasyCaching.CSRedis/Configurations/RedisOptions.cs +++ b/src/EasyCaching.CSRedis/Configurations/RedisOptions.cs @@ -1,7 +1,7 @@ namespace EasyCaching.CSRedis { using EasyCaching.Core; - using EasyCaching.Core.Internal; + using EasyCaching.Core.Configurations; public class RedisOptions : BaseProviderOptions { diff --git a/src/EasyCaching.CSRedis/Configurations/RedisOptionsExtension.cs b/src/EasyCaching.CSRedis/Configurations/RedisOptionsExtension.cs index 3f47c11b..9d6e0495 100755 --- a/src/EasyCaching.CSRedis/Configurations/RedisOptionsExtension.cs +++ b/src/EasyCaching.CSRedis/Configurations/RedisOptionsExtension.cs @@ -1,6 +1,8 @@ namespace EasyCaching.CSRedis { using EasyCaching.Core; + using EasyCaching.Core.Configurations; + using EasyCaching.Core.Serialization; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; @@ -30,7 +32,7 @@ internal sealed class RedisOptionsExtension : IEasyCachingOptionsExtension /// Configure. public RedisOptionsExtension(string name, Action configure) { - Core.Internal.ArgumentCheck.NotNullOrWhiteSpace(name, nameof(name)); + ArgumentCheck.NotNullOrWhiteSpace(name, nameof(name)); this._name = name; this._configure = configure; diff --git a/src/EasyCaching.CSRedis/DefaultCSRedisCachingProvider.cs b/src/EasyCaching.CSRedis/DefaultCSRedisCachingProvider.cs index f3e7b8c4..33e0d35d 100644 --- a/src/EasyCaching.CSRedis/DefaultCSRedisCachingProvider.cs +++ b/src/EasyCaching.CSRedis/DefaultCSRedisCachingProvider.cs @@ -2,6 +2,7 @@ { using EasyCaching.Core; using EasyCaching.Core.Internal; + using EasyCaching.Core.Serialization; using global::CSRedis; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; diff --git a/src/EasyCaching.Core/Bus/EasyCachingMessage.cs b/src/EasyCaching.Core/Bus/EasyCachingMessage.cs index 7ef9ae42..9284dc9f 100644 --- a/src/EasyCaching.Core/Bus/EasyCachingMessage.cs +++ b/src/EasyCaching.Core/Bus/EasyCachingMessage.cs @@ -1,7 +1,10 @@ -namespace EasyCaching.Core +namespace EasyCaching.Core.Bus { using System; + /// + /// EasyCaching message. + /// [Serializable] public class EasyCachingMessage { diff --git a/src/EasyCaching.Core/Bus/IEasyCachingBus.cs b/src/EasyCaching.Core/Bus/IEasyCachingBus.cs index 5a6591fc..743b13a9 100644 --- a/src/EasyCaching.Core/Bus/IEasyCachingBus.cs +++ b/src/EasyCaching.Core/Bus/IEasyCachingBus.cs @@ -1,4 +1,4 @@ -namespace EasyCaching.Core +namespace EasyCaching.Core.Bus { /// /// Easycaching bus. diff --git a/src/EasyCaching.Core/Bus/IEasyCachingPublisher.cs b/src/EasyCaching.Core/Bus/IEasyCachingPublisher.cs index f706614b..a4e4c9c1 100644 --- a/src/EasyCaching.Core/Bus/IEasyCachingPublisher.cs +++ b/src/EasyCaching.Core/Bus/IEasyCachingPublisher.cs @@ -1,4 +1,4 @@ -namespace EasyCaching.Core +namespace EasyCaching.Core.Bus { using System.Threading; using System.Threading.Tasks; diff --git a/src/EasyCaching.Core/Bus/IEasyCachingSubscriber.cs b/src/EasyCaching.Core/Bus/IEasyCachingSubscriber.cs index a66753c2..768005ce 100644 --- a/src/EasyCaching.Core/Bus/IEasyCachingSubscriber.cs +++ b/src/EasyCaching.Core/Bus/IEasyCachingSubscriber.cs @@ -1,4 +1,4 @@ -namespace EasyCaching.Core +namespace EasyCaching.Core.Bus { using System; @@ -7,6 +7,11 @@ /// public interface IEasyCachingSubscriber { + /// + /// Subscribe the specified topic and action. + /// + /// Topic. + /// Action. void Subscribe(string topic, Action action); } } diff --git a/src/EasyCaching.Core/Bus/NullEasyCachingBus.cs b/src/EasyCaching.Core/Bus/NullEasyCachingBus.cs index c8ac5d3e..199744e7 100644 --- a/src/EasyCaching.Core/Bus/NullEasyCachingBus.cs +++ b/src/EasyCaching.Core/Bus/NullEasyCachingBus.cs @@ -1,25 +1,57 @@ -using System; -using System.Threading; -using System.Threading.Tasks; - -namespace EasyCaching.Core +namespace EasyCaching.Core.Bus { + using System; + using System.Threading; + using System.Threading.Tasks; + + /// + /// Null easy caching bus. + /// public class NullEasyCachingBus : IEasyCachingBus { + /// + /// The instance. + /// public static readonly NullEasyCachingBus Instance = new NullEasyCachingBus(); + /// + /// Releases all resource used by the object. + /// + /// Call when you are finished using the + /// . The method leaves the + /// in an unusable state. After calling + /// , you must release all references to the + /// so the garbage collector can reclaim the memory that + /// the was occupying. public void Dispose() { } + /// + /// Publish the specified topic and message. + /// + /// Topic. + /// Message. public void Publish(string topic, EasyCachingMessage message) { } + /// + /// Publish the specified topic and message async. + /// + /// The async. + /// Topic. + /// Message. + /// Cancellation token. public Task PublishAsync(string topic, EasyCachingMessage message, CancellationToken cancellationToken = default(CancellationToken)) { return Task.CompletedTask; } + /// + /// Subscribe the specified topic and action. + /// + /// Topic. + /// Action. public void Subscribe(string topic, Action action) { diff --git a/src/EasyCaching.Core/Internal/BaseProviderOptions.cs b/src/EasyCaching.Core/Configurations/BaseProviderOptions.cs similarity index 97% rename from src/EasyCaching.Core/Internal/BaseProviderOptions.cs rename to src/EasyCaching.Core/Configurations/BaseProviderOptions.cs index adbb186b..6c60fbe9 100644 --- a/src/EasyCaching.Core/Internal/BaseProviderOptions.cs +++ b/src/EasyCaching.Core/Configurations/BaseProviderOptions.cs @@ -1,4 +1,4 @@ -namespace EasyCaching.Core.Internal +namespace EasyCaching.Core.Configurations { /// /// Base provider options. diff --git a/src/EasyCaching.Core/Internal/BaseRabbitMQOptions.cs b/src/EasyCaching.Core/Configurations/BaseRabbitMQOptions.cs similarity index 97% rename from src/EasyCaching.Core/Internal/BaseRabbitMQOptions.cs rename to src/EasyCaching.Core/Configurations/BaseRabbitMQOptions.cs index 8f012a56..e3dee99f 100644 --- a/src/EasyCaching.Core/Internal/BaseRabbitMQOptions.cs +++ b/src/EasyCaching.Core/Configurations/BaseRabbitMQOptions.cs @@ -1,4 +1,4 @@ -namespace EasyCaching.Core.Internal +namespace EasyCaching.Core.Configurations { public class BaseRabbitMQOptions { diff --git a/src/EasyCaching.Core/Internal/BaseRedisOptions.cs b/src/EasyCaching.Core/Configurations/BaseRedisOptions.cs similarity index 98% rename from src/EasyCaching.Core/Internal/BaseRedisOptions.cs rename to src/EasyCaching.Core/Configurations/BaseRedisOptions.cs index 5166d34e..79ddf13c 100644 --- a/src/EasyCaching.Core/Internal/BaseRedisOptions.cs +++ b/src/EasyCaching.Core/Configurations/BaseRedisOptions.cs @@ -1,4 +1,4 @@ -namespace EasyCaching.Core.Internal +namespace EasyCaching.Core.Configurations { using System.Collections.Generic; diff --git a/src/EasyCaching.Core/Configurations/EasyCachingApplicationBuliderExtensions.cs b/src/EasyCaching.Core/Configurations/EasyCachingApplicationBuliderExtensions.cs index 4929d1dd..c7daae67 100644 --- a/src/EasyCaching.Core/Configurations/EasyCachingApplicationBuliderExtensions.cs +++ b/src/EasyCaching.Core/Configurations/EasyCachingApplicationBuliderExtensions.cs @@ -1,7 +1,7 @@ namespace EasyCaching.Core { + using EasyCaching.Core.Configurations; using Microsoft.AspNetCore.Builder; - using System; public static class EasyCachingApplicationBuliderExtensions { @@ -12,10 +12,7 @@ public static class EasyCachingApplicationBuliderExtensions /// App. public static IApplicationBuilder UseEasyCaching(this IApplicationBuilder app) { - if (app == null) - { - throw new ArgumentNullException(nameof(app)); - } + ArgumentCheck.NotNull(app, nameof(app)); var options = app.ApplicationServices.GetService(typeof(EasyCachingOptions)); diff --git a/src/EasyCaching.Core/Configurations/EasyCachingOptions.cs b/src/EasyCaching.Core/Configurations/EasyCachingOptions.cs index 09bac17a..4a972435 100644 --- a/src/EasyCaching.Core/Configurations/EasyCachingOptions.cs +++ b/src/EasyCaching.Core/Configurations/EasyCachingOptions.cs @@ -1,4 +1,4 @@ -namespace EasyCaching.Core +namespace EasyCaching.Core.Configurations { using System.Collections.Generic; @@ -27,7 +27,7 @@ public EasyCachingOptions() /// Extension. public void RegisterExtension(IEasyCachingOptionsExtension extension) { - Internal.ArgumentCheck.NotNull(extension, nameof(extension)); + ArgumentCheck.NotNull(extension, nameof(extension)); Extensions.Add(extension); } diff --git a/src/EasyCaching.Core/Configurations/EasyCachingServiceCollectionExtensions.cs b/src/EasyCaching.Core/Configurations/EasyCachingServiceCollectionExtensions.cs index b6c5f856..2e433b4a 100644 --- a/src/EasyCaching.Core/Configurations/EasyCachingServiceCollectionExtensions.cs +++ b/src/EasyCaching.Core/Configurations/EasyCachingServiceCollectionExtensions.cs @@ -1,13 +1,14 @@ namespace EasyCaching.Core { - using Microsoft.Extensions.DependencyInjection; using System; + using EasyCaching.Core.Configurations; + using Microsoft.Extensions.DependencyInjection; /// /// EasyCaching service collection extensions. /// public static class EasyCachingServiceCollectionExtensions - { + { /// /// Adds the easycaching. /// @@ -16,10 +17,7 @@ public static class EasyCachingServiceCollectionExtensions /// Setup action. public static IServiceCollection AddEasyCaching(this IServiceCollection services, Action setupAction) { - if (setupAction == null) - { - throw new ArgumentNullException(nameof(setupAction)); - } + ArgumentCheck.NotNull(setupAction, nameof(setupAction)); //Options and extension service var options = new EasyCachingOptions(); @@ -29,7 +27,7 @@ public static IServiceCollection AddEasyCaching(this IServiceCollection services serviceExtension.AddServices(services); } services.AddSingleton(options); - + return services; } } diff --git a/src/EasyCaching.Core/Configurations/IEasyCachingOptionsExtension.cs b/src/EasyCaching.Core/Configurations/IEasyCachingOptionsExtension.cs index e864df0e..4b4222e8 100644 --- a/src/EasyCaching.Core/Configurations/IEasyCachingOptionsExtension.cs +++ b/src/EasyCaching.Core/Configurations/IEasyCachingOptionsExtension.cs @@ -1,4 +1,4 @@ -namespace EasyCaching.Core +namespace EasyCaching.Core.Configurations { using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; diff --git a/src/EasyCaching.Core/Internal/ServerEndPoint.cs b/src/EasyCaching.Core/Configurations/ServerEndPoint.cs similarity index 87% rename from src/EasyCaching.Core/Internal/ServerEndPoint.cs rename to src/EasyCaching.Core/Configurations/ServerEndPoint.cs index 90cd817b..35c1d7c2 100644 --- a/src/EasyCaching.Core/Internal/ServerEndPoint.cs +++ b/src/EasyCaching.Core/Configurations/ServerEndPoint.cs @@ -1,4 +1,4 @@ -namespace EasyCaching.Core.Internal +namespace EasyCaching.Core.Configurations { /// /// Defines an endpoint. @@ -6,7 +6,7 @@ public class ServerEndPoint { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Host. /// Port. @@ -19,7 +19,7 @@ public ServerEndPoint(string host, int port) } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// public ServerEndPoint() { diff --git a/src/EasyCaching.Core/EasyCaching.Core.csproj b/src/EasyCaching.Core/EasyCaching.Core.csproj index 0536649c..72b1a803 100644 --- a/src/EasyCaching.Core/EasyCaching.Core.csproj +++ b/src/EasyCaching.Core/EasyCaching.Core.csproj @@ -26,6 +26,8 @@ + + diff --git a/src/EasyCaching.Core/IEasyCachingProviderFactory.cs b/src/EasyCaching.Core/IEasyCachingProviderFactory.cs deleted file mode 100644 index 1badf221..00000000 --- a/src/EasyCaching.Core/IEasyCachingProviderFactory.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace EasyCaching.Core -{ - using System.Collections.Generic; - using System.Linq; - - public interface IEasyCachingProviderFactory - { - IEasyCachingProvider GetCachingProvider(string name); - } - - public class DefaultEasyCachingProviderFactory : IEasyCachingProviderFactory - { - private readonly IEnumerable _cachingProviders; - - public DefaultEasyCachingProviderFactory(IEnumerable cachingProviders) - { - this._cachingProviders = cachingProviders; - } - - public IEasyCachingProvider GetCachingProvider(string name) - { - Internal.ArgumentCheck.NotNullOrWhiteSpace(name, nameof(name)); - - var provider = _cachingProviders.FirstOrDefault(x => x.Name.Equals(name, System.StringComparison.OrdinalIgnoreCase)); - - if (provider == null) throw new System.ArgumentException("can not find a match caching provider!"); - - return provider; - } - } -} diff --git a/src/EasyCaching.Core/IHybridCachingProvider.cs b/src/EasyCaching.Core/IHybridCachingProvider.cs index 2b33ba49..749fafce 100644 --- a/src/EasyCaching.Core/IHybridCachingProvider.cs +++ b/src/EasyCaching.Core/IHybridCachingProvider.cs @@ -1,31 +1,93 @@ -using System; -using System.Threading.Tasks; - -namespace EasyCaching.Core +namespace EasyCaching.Core { + using System; + using System.Threading.Tasks; + /// /// Hybrid caching provider. /// - public interface IHybridCachingProvider //: IEasyCachingProvider + public interface IHybridCachingProvider { + /// + /// Set the specified cacheKey, cacheValue and expiration. + /// + /// Cache key. + /// Cache value. + /// Expiration. + /// The 1st type parameter. void Set(string cacheKey, T cacheValue, TimeSpan expiration); + /// + /// Sets the specified cacheKey, cacheValue and expiration async. + /// + /// The async. + /// Cache key. + /// Cache value. + /// Expiration. + /// The 1st type parameter. Task SetAsync(string cacheKey, T cacheValue, TimeSpan expiration); + /// + /// Get the specified cacheKey. + /// + /// The get. + /// Cache key. + /// The 1st type parameter. CacheValue Get(string cacheKey); + /// + /// Get the specified cacheKey async. + /// + /// The async. + /// Cache key. + /// The 1st type parameter. Task> GetAsync(string cacheKey); + /// + /// Remove the specified cacheKey. + /// + /// Cache key. void Remove(string cacheKey); + /// + /// Remove the specified cacheKey async. + /// + /// The async. + /// Cache key. Task RemoveAsync(string cacheKey); + /// + /// Exists the specified cacheKey async. + /// + /// The async. + /// Cache key. Task ExistsAsync(string cacheKey); + /// + /// Exists the specified cacheKey. + /// + /// The exists. + /// Cache key. bool Exists(string cacheKey); + /// + /// Tries the set. + /// + /// true, if set was tryed, false otherwise. + /// Cache key. + /// Cache value. + /// Expiration. + /// The 1st type parameter. bool TrySet(string cacheKey, T cacheValue, TimeSpan expiration); + /// + /// Tries the set async. + /// + /// The set async. + /// Cache key. + /// Cache value. + /// Expiration. + /// The 1st type parameter. Task TrySetAsync(string cacheKey, T cacheValue, TimeSpan expiration); } } diff --git a/src/EasyCaching.Core/IRedisCachingProvider.cs b/src/EasyCaching.Core/IRedisCachingProvider.cs index 494e4adc..8127de68 100644 --- a/src/EasyCaching.Core/IRedisCachingProvider.cs +++ b/src/EasyCaching.Core/IRedisCachingProvider.cs @@ -4,6 +4,12 @@ using System.Collections.Generic; using System.Threading.Tasks; + /// + /// Redis caching provider. + /// + /// + /// Contains some features of redis + /// public interface IRedisCachingProvider : IEasyCachingProvider { #region Hashes diff --git a/src/EasyCaching.Core/Interceptor/DefaultEasyCachingKeyGenerator.cs b/src/EasyCaching.Core/Interceptor/DefaultEasyCachingKeyGenerator.cs index 8e4d1762..fb25f656 100644 --- a/src/EasyCaching.Core/Interceptor/DefaultEasyCachingKeyGenerator.cs +++ b/src/EasyCaching.Core/Interceptor/DefaultEasyCachingKeyGenerator.cs @@ -1,11 +1,9 @@ -namespace EasyCaching.Core +namespace EasyCaching.Core.Interceptor { - using EasyCaching.Core.Internal; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; - using System.Security.Cryptography; using System.Text; /// diff --git a/src/EasyCaching.Core/Interceptor/EasyCachingInterceptorAttribute.cs b/src/EasyCaching.Core/Interceptor/EasyCachingInterceptorAttribute.cs index e660a6b7..80880129 100644 --- a/src/EasyCaching.Core/Interceptor/EasyCachingInterceptorAttribute.cs +++ b/src/EasyCaching.Core/Interceptor/EasyCachingInterceptorAttribute.cs @@ -1,4 +1,4 @@ -namespace EasyCaching.Core.Internal +namespace EasyCaching.Core.Interceptor { using System; diff --git a/src/EasyCaching.Core/Interceptor/ICachable.cs b/src/EasyCaching.Core/Interceptor/ICachable.cs index fb71c53e..591587bc 100644 --- a/src/EasyCaching.Core/Interceptor/ICachable.cs +++ b/src/EasyCaching.Core/Interceptor/ICachable.cs @@ -1,4 +1,4 @@ -namespace EasyCaching.Core.Internal +namespace EasyCaching.Core.Interceptor { /// /// Cachable. diff --git a/src/EasyCaching.Core/Interceptor/IEasyCachingKeyGenerator.cs b/src/EasyCaching.Core/Interceptor/IEasyCachingKeyGenerator.cs index ed454970..a091333a 100644 --- a/src/EasyCaching.Core/Interceptor/IEasyCachingKeyGenerator.cs +++ b/src/EasyCaching.Core/Interceptor/IEasyCachingKeyGenerator.cs @@ -1,4 +1,4 @@ -namespace EasyCaching.Core +namespace EasyCaching.Core.Interceptor { using System.Reflection; diff --git a/src/EasyCaching.Core/Internal/ArgumentCheck.cs b/src/EasyCaching.Core/Internal/ArgumentCheck.cs index f7b84ac4..1b6d3000 100644 --- a/src/EasyCaching.Core/Internal/ArgumentCheck.cs +++ b/src/EasyCaching.Core/Internal/ArgumentCheck.cs @@ -1,4 +1,4 @@ -namespace EasyCaching.Core.Internal +namespace EasyCaching.Core { using System; using System.Collections; diff --git a/src/EasyCaching.Core/CacheValue.cs b/src/EasyCaching.Core/Internal/CacheValue.cs similarity index 100% rename from src/EasyCaching.Core/CacheValue.cs rename to src/EasyCaching.Core/Internal/CacheValue.cs diff --git a/src/EasyCaching.Core/CachingProviderType.cs b/src/EasyCaching.Core/Internal/CachingProviderType.cs similarity index 100% rename from src/EasyCaching.Core/CachingProviderType.cs rename to src/EasyCaching.Core/Internal/CachingProviderType.cs diff --git a/src/EasyCaching.Core/EasyCachingConstValue.cs b/src/EasyCaching.Core/Internal/EasyCachingConstValue.cs similarity index 100% rename from src/EasyCaching.Core/EasyCachingConstValue.cs rename to src/EasyCaching.Core/Internal/EasyCachingConstValue.cs diff --git a/src/EasyCaching.Core/ProviderFactory/DefaultEasyCachingProviderFactory.cs b/src/EasyCaching.Core/ProviderFactory/DefaultEasyCachingProviderFactory.cs new file mode 100644 index 00000000..c0341e41 --- /dev/null +++ b/src/EasyCaching.Core/ProviderFactory/DefaultEasyCachingProviderFactory.cs @@ -0,0 +1,42 @@ +namespace EasyCaching.Core +{ + using System; + using System.Collections.Generic; + using System.Linq; + + /// + /// Default easycaching provider factory. + /// + public class DefaultEasyCachingProviderFactory : IEasyCachingProviderFactory + { + /// + /// The caching providers. + /// + private readonly IEnumerable _cachingProviders; + + /// + /// Initializes a new instance of the class. + /// + /// Caching providers. + public DefaultEasyCachingProviderFactory(IEnumerable cachingProviders) + { + this._cachingProviders = cachingProviders; + } + + /// + /// Gets the caching provider. + /// + /// The caching provider. + /// Name. + public IEasyCachingProvider GetCachingProvider(string name) + { + ArgumentCheck.NotNullOrWhiteSpace(name, nameof(name)); + + var provider = _cachingProviders.FirstOrDefault(x => x.Name.Equals(name, StringComparison.OrdinalIgnoreCase)); + + if (provider == null) throw new ArgumentException("can not find a match caching provider!"); + + return provider; + } + } +} diff --git a/src/EasyCaching.Core/ProviderFactory/IEasyCachingProviderFactory.cs b/src/EasyCaching.Core/ProviderFactory/IEasyCachingProviderFactory.cs new file mode 100644 index 00000000..748e4c4d --- /dev/null +++ b/src/EasyCaching.Core/ProviderFactory/IEasyCachingProviderFactory.cs @@ -0,0 +1,15 @@ +namespace EasyCaching.Core +{ + /// + /// EasyCaching provider factory. + /// + public interface IEasyCachingProviderFactory + { + /// + /// Gets the caching provider. + /// + /// The caching provider. + /// Name. + IEasyCachingProvider GetCachingProvider(string name); + } +} diff --git a/src/EasyCaching.Core/Serialization/DefaultBinaryFormatterSerializer.cs b/src/EasyCaching.Core/Serialization/DefaultBinaryFormatterSerializer.cs index 7dd39e6f..1cc5752e 100644 --- a/src/EasyCaching.Core/Serialization/DefaultBinaryFormatterSerializer.cs +++ b/src/EasyCaching.Core/Serialization/DefaultBinaryFormatterSerializer.cs @@ -1,4 +1,4 @@ -namespace EasyCaching.Core +namespace EasyCaching.Core.Serialization { using System; using System.IO; diff --git a/src/EasyCaching.Core/Serialization/IEasyCachingSerializer.cs b/src/EasyCaching.Core/Serialization/IEasyCachingSerializer.cs index b68bc4e0..12ccc71c 100644 --- a/src/EasyCaching.Core/Serialization/IEasyCachingSerializer.cs +++ b/src/EasyCaching.Core/Serialization/IEasyCachingSerializer.cs @@ -1,4 +1,4 @@ -namespace EasyCaching.Core +namespace EasyCaching.Core.Serialization { using System; diff --git a/src/EasyCaching.Core/CacheStatsCounter.cs b/src/EasyCaching.Core/Stats/CacheStats.cs similarity index 61% rename from src/EasyCaching.Core/CacheStatsCounter.cs rename to src/EasyCaching.Core/Stats/CacheStats.cs index 94fac245..7938d4aa 100644 --- a/src/EasyCaching.Core/CacheStatsCounter.cs +++ b/src/EasyCaching.Core/Stats/CacheStats.cs @@ -1,60 +1,60 @@ namespace EasyCaching.Core { using System.Collections.Concurrent; - using System.Threading; /// - /// Cache stats counter. + /// Cache stats. /// - public class CacheStatsCounter - { - private long[] _counters = new long[2]; - - public void Increment(StatsType statsType) - { - Interlocked.Increment(ref _counters[(int)statsType]); - } - - public long Get(StatsType statsType) - { - return Interlocked.Read(ref _counters[(int)statsType]); - } - } - - public enum StatsType - { - Hit = 0, - - Missed = 1, - } - public class CacheStats { + /// + /// The counters. + /// private readonly ConcurrentDictionary _counters; + /// + /// The default key. + /// private const string DEFAULT_KEY = "easycahing_catche_stats"; - + /// + /// Initializes a new instance of the class. + /// public CacheStats() { _counters = new ConcurrentDictionary(); } + /// + /// Ons the hit. + /// public void OnHit() { GetCounter().Increment(StatsType.Hit); } + /// + /// Ons the miss. + /// public void OnMiss() { GetCounter().Increment(StatsType.Missed); } + /// + /// Gets the statistic. + /// + /// The statistic. + /// Stats type. public long GetStatistic(StatsType statsType) { return GetCounter().Get(statsType); } + /// + /// Gets the counter. + /// + /// The counter. private CacheStatsCounter GetCounter() { if (!_counters.TryGetValue(DEFAULT_KEY, out CacheStatsCounter counter)) diff --git a/src/EasyCaching.Core/Stats/CacheStatsCounter.cs b/src/EasyCaching.Core/Stats/CacheStatsCounter.cs new file mode 100644 index 00000000..b2e5a8e5 --- /dev/null +++ b/src/EasyCaching.Core/Stats/CacheStatsCounter.cs @@ -0,0 +1,34 @@ +namespace EasyCaching.Core +{ + using System.Threading; + + /// + /// Cache stats counter. + /// + public class CacheStatsCounter + { + /// + /// The counters. + /// + private long[] _counters = new long[2]; + + /// + /// Increment the specified statsType. + /// + /// Stats type. + public void Increment(StatsType statsType) + { + Interlocked.Increment(ref _counters[(int)statsType]); + } + + /// + /// Get the specified statsType. + /// + /// The get. + /// Stats type. + public long Get(StatsType statsType) + { + return Interlocked.Read(ref _counters[(int)statsType]); + } + } +} diff --git a/src/EasyCaching.Core/Stats/StatsType.cs b/src/EasyCaching.Core/Stats/StatsType.cs new file mode 100644 index 00000000..56f1ad5a --- /dev/null +++ b/src/EasyCaching.Core/Stats/StatsType.cs @@ -0,0 +1,18 @@ +namespace EasyCaching.Core +{ + /// + /// Stats type. + /// + public enum StatsType + { + /// + /// The hit. + /// + Hit = 0, + + /// + /// The missed. + /// + Missed = 1, + } +} diff --git a/src/EasyCaching.HybridCache/Configurations/EasyCachingOptionsExtensions.cs b/src/EasyCaching.HybridCache/Configurations/EasyCachingOptionsExtensions.cs index f5612b25..c8f8c992 100644 --- a/src/EasyCaching.HybridCache/Configurations/EasyCachingOptionsExtensions.cs +++ b/src/EasyCaching.HybridCache/Configurations/EasyCachingOptionsExtensions.cs @@ -1,7 +1,7 @@ namespace EasyCaching.HybridCache { using System; - using EasyCaching.Core; + using EasyCaching.Core.Configurations; /// /// EasyCaching options extensions. diff --git a/src/EasyCaching.HybridCache/Configurations/HybridCacheOptionsExtension.cs b/src/EasyCaching.HybridCache/Configurations/HybridCacheOptionsExtension.cs index c714fcfb..9cc890ff 100644 --- a/src/EasyCaching.HybridCache/Configurations/HybridCacheOptionsExtension.cs +++ b/src/EasyCaching.HybridCache/Configurations/HybridCacheOptionsExtension.cs @@ -2,6 +2,7 @@ { using System; using EasyCaching.Core; + using EasyCaching.Core.Configurations; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; diff --git a/src/EasyCaching.HybridCache/HybridCacheServiceCollectionExtensions.cs b/src/EasyCaching.HybridCache/HybridCacheServiceCollectionExtensions.cs index b6ac9599..a0eb1e4b 100644 --- a/src/EasyCaching.HybridCache/HybridCacheServiceCollectionExtensions.cs +++ b/src/EasyCaching.HybridCache/HybridCacheServiceCollectionExtensions.cs @@ -1,10 +1,9 @@ namespace EasyCaching.HybridCache { using EasyCaching.Core; - using EasyCaching.Core.Internal; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; - + /// /// Hybrid cache service collection extensions. /// diff --git a/src/EasyCaching.HybridCache/HybridCachingProvider.cs b/src/EasyCaching.HybridCache/HybridCachingProvider.cs index 996c0082..445d16f5 100644 --- a/src/EasyCaching.HybridCache/HybridCachingProvider.cs +++ b/src/EasyCaching.HybridCache/HybridCachingProvider.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.Logging; + using EasyCaching.Core.Bus; /// /// Hybrid caching provider. diff --git a/src/EasyCaching.InMemory/Configurations/EasyCachingOptionsExtensions.cs b/src/EasyCaching.InMemory/Configurations/EasyCachingOptionsExtensions.cs index 75bcb05c..e6930099 100644 --- a/src/EasyCaching.InMemory/Configurations/EasyCachingOptionsExtensions.cs +++ b/src/EasyCaching.InMemory/Configurations/EasyCachingOptionsExtensions.cs @@ -1,6 +1,7 @@ namespace EasyCaching.InMemory { using EasyCaching.Core; + using EasyCaching.Core.Configurations; using Microsoft.Extensions.Configuration; using System; diff --git a/src/EasyCaching.InMemory/Configurations/InMemoryOptions.cs b/src/EasyCaching.InMemory/Configurations/InMemoryOptions.cs index 9f92d6fb..b7c7a4ea 100644 --- a/src/EasyCaching.InMemory/Configurations/InMemoryOptions.cs +++ b/src/EasyCaching.InMemory/Configurations/InMemoryOptions.cs @@ -1,7 +1,7 @@ namespace EasyCaching.InMemory { using EasyCaching.Core; - using EasyCaching.Core.Internal; + using EasyCaching.Core.Configurations; public class InMemoryOptions : BaseProviderOptions { diff --git a/src/EasyCaching.InMemory/Configurations/InMemoryOptionsExtension.cs b/src/EasyCaching.InMemory/Configurations/InMemoryOptionsExtension.cs index 89b0949c..bfba4dc0 100644 --- a/src/EasyCaching.InMemory/Configurations/InMemoryOptionsExtension.cs +++ b/src/EasyCaching.InMemory/Configurations/InMemoryOptionsExtension.cs @@ -1,6 +1,7 @@ namespace EasyCaching.InMemory { using EasyCaching.Core; + using EasyCaching.Core.Configurations; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using System; diff --git a/src/EasyCaching.Interceptor.AspectCore/AspectCoreInterceptorServiceCollectionExtensions.cs b/src/EasyCaching.Interceptor.AspectCore/AspectCoreInterceptorServiceCollectionExtensions.cs index 971be74b..e62a0194 100644 --- a/src/EasyCaching.Interceptor.AspectCore/AspectCoreInterceptorServiceCollectionExtensions.cs +++ b/src/EasyCaching.Interceptor.AspectCore/AspectCoreInterceptorServiceCollectionExtensions.cs @@ -10,6 +10,7 @@ using System; using System.Linq; using System.Reflection; + using EasyCaching.Core.Interceptor; /// /// Aspectcore interceptor service collection extensions. diff --git a/src/EasyCaching.Interceptor.AspectCore/EasyCachingInterceptor.cs b/src/EasyCaching.Interceptor.AspectCore/EasyCachingInterceptor.cs index 5219ec55..3d7b11c5 100644 --- a/src/EasyCaching.Interceptor.AspectCore/EasyCachingInterceptor.cs +++ b/src/EasyCaching.Interceptor.AspectCore/EasyCachingInterceptor.cs @@ -6,7 +6,7 @@ using System.Reflection; using System.Threading.Tasks; using EasyCaching.Core; - using EasyCaching.Core.Internal; + using EasyCaching.Core.Interceptor; using global::AspectCore.DynamicProxy; using global::AspectCore.Injector; diff --git a/src/EasyCaching.Interceptor.Castle/CastleInterceptorServiceCollectionExtensions.cs b/src/EasyCaching.Interceptor.Castle/CastleInterceptorServiceCollectionExtensions.cs index a0ce85c5..f6a43925 100644 --- a/src/EasyCaching.Interceptor.Castle/CastleInterceptorServiceCollectionExtensions.cs +++ b/src/EasyCaching.Interceptor.Castle/CastleInterceptorServiceCollectionExtensions.cs @@ -1,15 +1,14 @@ namespace EasyCaching.Interceptor.Castle { + using System; + using System.Linq; + using System.Reflection; using Autofac; using Autofac.Extensions.DependencyInjection; using Autofac.Extras.DynamicProxy; - using EasyCaching.Core; - using EasyCaching.Core.Internal; + using EasyCaching.Core.Interceptor; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; - using System; - using System.Linq; - using System.Reflection; /// /// Castle interceptor service collection extensions. diff --git a/src/EasyCaching.Interceptor.Castle/EasyCachingInterceptor.cs b/src/EasyCaching.Interceptor.Castle/EasyCachingInterceptor.cs index 2a5db4ea..f61a52de 100644 --- a/src/EasyCaching.Interceptor.Castle/EasyCachingInterceptor.cs +++ b/src/EasyCaching.Interceptor.Castle/EasyCachingInterceptor.cs @@ -1,10 +1,10 @@ namespace EasyCaching.Interceptor.Castle { - using EasyCaching.Core; - using EasyCaching.Core.Internal; - using global::Castle.DynamicProxy; using System; using System.Linq; + using EasyCaching.Core; + using EasyCaching.Core.Interceptor; + using global::Castle.DynamicProxy; /// /// Easycaching interceptor. diff --git a/src/EasyCaching.Memcached/Configurations/EasyCachingOptionsExtensions.cs b/src/EasyCaching.Memcached/Configurations/EasyCachingOptionsExtensions.cs index 075da45b..eaee4b59 100644 --- a/src/EasyCaching.Memcached/Configurations/EasyCachingOptionsExtensions.cs +++ b/src/EasyCaching.Memcached/Configurations/EasyCachingOptionsExtensions.cs @@ -1,6 +1,7 @@ namespace EasyCaching.Memcached { using EasyCaching.Core; + using EasyCaching.Core.Configurations; using Microsoft.Extensions.Configuration; using System; diff --git a/src/EasyCaching.Memcached/Configurations/EasyCachingTranscoder.cs b/src/EasyCaching.Memcached/Configurations/EasyCachingTranscoder.cs index 5fab70f1..74d5a54c 100755 --- a/src/EasyCaching.Memcached/Configurations/EasyCachingTranscoder.cs +++ b/src/EasyCaching.Memcached/Configurations/EasyCachingTranscoder.cs @@ -1,6 +1,7 @@ namespace EasyCaching.Memcached { - using EasyCaching.Core; + using EasyCaching.Core; + using EasyCaching.Core.Serialization; using Enyim.Caching.Memcached; using System; diff --git a/src/EasyCaching.Memcached/Configurations/MemcachedOptions.cs b/src/EasyCaching.Memcached/Configurations/MemcachedOptions.cs index d4160bca..53d032ed 100644 --- a/src/EasyCaching.Memcached/Configurations/MemcachedOptions.cs +++ b/src/EasyCaching.Memcached/Configurations/MemcachedOptions.cs @@ -1,7 +1,7 @@ namespace EasyCaching.Memcached { using EasyCaching.Core; - using EasyCaching.Core.Internal; + using EasyCaching.Core.Configurations; public class MemcachedOptions : BaseProviderOptions { diff --git a/src/EasyCaching.Memcached/Configurations/MemcachedOptionsExtension.cs b/src/EasyCaching.Memcached/Configurations/MemcachedOptionsExtension.cs index 0e7d2b5b..9fa42f23 100644 --- a/src/EasyCaching.Memcached/Configurations/MemcachedOptionsExtension.cs +++ b/src/EasyCaching.Memcached/Configurations/MemcachedOptionsExtension.cs @@ -1,6 +1,10 @@ namespace EasyCaching.Memcached { + using System; + using System.Linq; using EasyCaching.Core; + using EasyCaching.Core.Configurations; + using EasyCaching.Core.Serialization; using Enyim.Caching; using Enyim.Caching.Configuration; using Enyim.Caching.Memcached; @@ -9,8 +13,6 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; - using System; - using System.Linq; /// /// Memcached options extension. diff --git a/src/EasyCaching.Memcached/MemcachedServiceCollectionExtensions.cs b/src/EasyCaching.Memcached/MemcachedServiceCollectionExtensions.cs index 9ce1f37d..df95d831 100644 --- a/src/EasyCaching.Memcached/MemcachedServiceCollectionExtensions.cs +++ b/src/EasyCaching.Memcached/MemcachedServiceCollectionExtensions.cs @@ -1,7 +1,9 @@ namespace EasyCaching.Memcached { + using System; + using System.Linq; using EasyCaching.Core; - using EasyCaching.Core.Internal; + using EasyCaching.Core.Serialization; using Enyim.Caching.Configuration; using Enyim.Caching.Memcached; using Microsoft.Extensions.Configuration; @@ -9,8 +11,6 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; - using System; - using System.Linq; /// /// Memcached service collection extensions. diff --git a/src/EasyCaching.Redis/Configurations/EasyCachingOptionsExtensions.cs b/src/EasyCaching.Redis/Configurations/EasyCachingOptionsExtensions.cs index 11f53788..dcbc61bb 100644 --- a/src/EasyCaching.Redis/Configurations/EasyCachingOptionsExtensions.cs +++ b/src/EasyCaching.Redis/Configurations/EasyCachingOptionsExtensions.cs @@ -1,6 +1,7 @@ namespace EasyCaching.Redis { using EasyCaching.Core; + using EasyCaching.Core.Configurations; using Microsoft.Extensions.Configuration; using System; diff --git a/src/EasyCaching.Redis/Configurations/RedisDBOptions.cs b/src/EasyCaching.Redis/Configurations/RedisDBOptions.cs index 4b92b426..bf0ab0aa 100644 --- a/src/EasyCaching.Redis/Configurations/RedisDBOptions.cs +++ b/src/EasyCaching.Redis/Configurations/RedisDBOptions.cs @@ -1,6 +1,6 @@ namespace EasyCaching.Redis { - using EasyCaching.Core.Internal; + using EasyCaching.Core.Configurations; /// /// Redis cache options. diff --git a/src/EasyCaching.Redis/Configurations/RedisOptions.cs b/src/EasyCaching.Redis/Configurations/RedisOptions.cs index ab764b63..887118f2 100644 --- a/src/EasyCaching.Redis/Configurations/RedisOptions.cs +++ b/src/EasyCaching.Redis/Configurations/RedisOptions.cs @@ -1,7 +1,7 @@ namespace EasyCaching.Redis { using EasyCaching.Core; - using EasyCaching.Core.Internal; + using EasyCaching.Core.Configurations; public class RedisOptions: BaseProviderOptions { diff --git a/src/EasyCaching.Redis/Configurations/RedisOptionsExtension.cs b/src/EasyCaching.Redis/Configurations/RedisOptionsExtension.cs index 67b40477..35f50af1 100755 --- a/src/EasyCaching.Redis/Configurations/RedisOptionsExtension.cs +++ b/src/EasyCaching.Redis/Configurations/RedisOptionsExtension.cs @@ -1,6 +1,8 @@ namespace EasyCaching.Redis { using EasyCaching.Core; + using EasyCaching.Core.Configurations; + using EasyCaching.Core.Serialization; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; diff --git a/src/EasyCaching.Redis/DefaultRedisCachingProvider.cs b/src/EasyCaching.Redis/DefaultRedisCachingProvider.cs index 30bc4bb9..f1e1c1f6 100755 --- a/src/EasyCaching.Redis/DefaultRedisCachingProvider.cs +++ b/src/EasyCaching.Redis/DefaultRedisCachingProvider.cs @@ -1,14 +1,14 @@ namespace EasyCaching.Redis { - using EasyCaching.Core; - using EasyCaching.Core.Internal; - using Microsoft.Extensions.Logging; - using Microsoft.Extensions.Options; - using StackExchange.Redis; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; + using EasyCaching.Core; + using EasyCaching.Core.Serialization; + using Microsoft.Extensions.Logging; + using Microsoft.Extensions.Options; + using StackExchange.Redis; /// /// Default redis caching provider. diff --git a/src/EasyCaching.Redis/RedisCacheServiceCollectionExtensions.cs b/src/EasyCaching.Redis/RedisCacheServiceCollectionExtensions.cs index cafb9333..2b0622b1 100644 --- a/src/EasyCaching.Redis/RedisCacheServiceCollectionExtensions.cs +++ b/src/EasyCaching.Redis/RedisCacheServiceCollectionExtensions.cs @@ -1,13 +1,13 @@ namespace EasyCaching.Redis { + using System; using EasyCaching.Core; - using EasyCaching.Core.Internal; + using EasyCaching.Core.Serialization; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; - using System; /// /// Redis cache service collection extensions. diff --git a/src/EasyCaching.ResponseCaching/EasyCachingResponseCachingExtensions.cs b/src/EasyCaching.ResponseCaching/EasyCachingResponseCachingExtensions.cs index 49214b39..d0cd9914 100644 --- a/src/EasyCaching.ResponseCaching/EasyCachingResponseCachingExtensions.cs +++ b/src/EasyCaching.ResponseCaching/EasyCachingResponseCachingExtensions.cs @@ -1,6 +1,6 @@ namespace EasyCaching.ResponseCaching { - using EasyCaching.Core.Internal; + using EasyCaching.Core; using Microsoft.AspNetCore.Builder; /// diff --git a/src/EasyCaching.SQLite/Configurations/EasyCachingOptionsExtensions.cs b/src/EasyCaching.SQLite/Configurations/EasyCachingOptionsExtensions.cs index d033e6fa..cb483505 100644 --- a/src/EasyCaching.SQLite/Configurations/EasyCachingOptionsExtensions.cs +++ b/src/EasyCaching.SQLite/Configurations/EasyCachingOptionsExtensions.cs @@ -1,8 +1,9 @@ namespace EasyCaching.SQLite { + using System; using EasyCaching.Core; + using EasyCaching.Core.Configurations; using Microsoft.Extensions.Configuration; - using System; /// /// Easy caching options extensions. diff --git a/src/EasyCaching.SQLite/Configurations/SQLiteDBOptions.cs b/src/EasyCaching.SQLite/Configurations/SQLiteDBOptions.cs index 3dd2f5b6..a5c8dab1 100644 --- a/src/EasyCaching.SQLite/Configurations/SQLiteDBOptions.cs +++ b/src/EasyCaching.SQLite/Configurations/SQLiteDBOptions.cs @@ -1,8 +1,8 @@ namespace EasyCaching.SQLite { - using EasyCaching.Core.Internal; - using Microsoft.Data.Sqlite; using System.IO; + using EasyCaching.Core; + using Microsoft.Data.Sqlite; /// /// SQLite cache option. diff --git a/src/EasyCaching.SQLite/Configurations/SQLiteOptions.cs b/src/EasyCaching.SQLite/Configurations/SQLiteOptions.cs index 0da87af3..bade09e0 100644 --- a/src/EasyCaching.SQLite/Configurations/SQLiteOptions.cs +++ b/src/EasyCaching.SQLite/Configurations/SQLiteOptions.cs @@ -1,7 +1,7 @@ namespace EasyCaching.SQLite { using EasyCaching.Core; - using EasyCaching.Core.Internal; + using EasyCaching.Core.Configurations; public class SQLiteOptions: BaseProviderOptions { diff --git a/src/EasyCaching.SQLite/Configurations/SQLiteOptionsExtension.cs b/src/EasyCaching.SQLite/Configurations/SQLiteOptionsExtension.cs index ea664cc2..1705958f 100644 --- a/src/EasyCaching.SQLite/Configurations/SQLiteOptionsExtension.cs +++ b/src/EasyCaching.SQLite/Configurations/SQLiteOptionsExtension.cs @@ -2,6 +2,7 @@ { using Dapper; using EasyCaching.Core; + using EasyCaching.Core.Configurations; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; diff --git a/src/EasyCaching.SQLite/SQLiteCacheServiceCollectionExtensions.cs b/src/EasyCaching.SQLite/SQLiteCacheServiceCollectionExtensions.cs index f975b1a4..459f4103 100644 --- a/src/EasyCaching.SQLite/SQLiteCacheServiceCollectionExtensions.cs +++ b/src/EasyCaching.SQLite/SQLiteCacheServiceCollectionExtensions.cs @@ -2,7 +2,6 @@ { using System; using EasyCaching.Core; - using EasyCaching.Core.Internal; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; diff --git a/src/EasyCaching.Serialization.Json/Configurations/EasyCachingOptionsExtensions.cs b/src/EasyCaching.Serialization.Json/Configurations/EasyCachingOptionsExtensions.cs index e10965e8..1d772336 100644 --- a/src/EasyCaching.Serialization.Json/Configurations/EasyCachingOptionsExtensions.cs +++ b/src/EasyCaching.Serialization.Json/Configurations/EasyCachingOptionsExtensions.cs @@ -1,7 +1,7 @@ namespace EasyCaching.Serialization.Json { - using EasyCaching.Core; using System; + using EasyCaching.Core.Configurations; /// /// EasyCaching options extensions. diff --git a/src/EasyCaching.Serialization.Json/Configurations/JsonOptionsExtension.cs b/src/EasyCaching.Serialization.Json/Configurations/JsonOptionsExtension.cs index 46eef900..f2a03b50 100644 --- a/src/EasyCaching.Serialization.Json/Configurations/JsonOptionsExtension.cs +++ b/src/EasyCaching.Serialization.Json/Configurations/JsonOptionsExtension.cs @@ -1,9 +1,10 @@ namespace EasyCaching.Serialization.Json { - using EasyCaching.Core; + using System; + using EasyCaching.Core.Configurations; + using EasyCaching.Core.Serialization; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; - using System; /// /// Json options extension. diff --git a/src/EasyCaching.Serialization.Json/DefaultJsonSerializer.cs b/src/EasyCaching.Serialization.Json/DefaultJsonSerializer.cs index b2aad729..d6689a8c 100644 --- a/src/EasyCaching.Serialization.Json/DefaultJsonSerializer.cs +++ b/src/EasyCaching.Serialization.Json/DefaultJsonSerializer.cs @@ -1,11 +1,10 @@ namespace EasyCaching.Serialization.Json { using System; - using System.Collections.Concurrent; using System.IO; using System.Text; - using EasyCaching.Core; using EasyCaching.Core.Internal; + using EasyCaching.Core.Serialization; using Microsoft.Extensions.Options; using Newtonsoft.Json; diff --git a/src/EasyCaching.Serialization.Json/JsonSerializerServiceCollectionExtensions.cs b/src/EasyCaching.Serialization.Json/JsonSerializerServiceCollectionExtensions.cs index 0e1d2d60..30cd2af9 100644 --- a/src/EasyCaching.Serialization.Json/JsonSerializerServiceCollectionExtensions.cs +++ b/src/EasyCaching.Serialization.Json/JsonSerializerServiceCollectionExtensions.cs @@ -1,6 +1,7 @@ namespace EasyCaching.Serialization.Json { using EasyCaching.Core; + using EasyCaching.Core.Serialization; using Microsoft.Extensions.DependencyInjection; using System; diff --git a/src/EasyCaching.Serialization.MessagePack/Configurations/EasyCachingOptionsExtensions.cs b/src/EasyCaching.Serialization.MessagePack/Configurations/EasyCachingOptionsExtensions.cs index a891e164..d432e6cb 100644 --- a/src/EasyCaching.Serialization.MessagePack/Configurations/EasyCachingOptionsExtensions.cs +++ b/src/EasyCaching.Serialization.MessagePack/Configurations/EasyCachingOptionsExtensions.cs @@ -1,6 +1,6 @@ namespace EasyCaching.Serialization.MessagePack { - using EasyCaching.Core; + using EasyCaching.Core.Configurations; /// /// Easy caching options extensions. diff --git a/src/EasyCaching.Serialization.MessagePack/Configurations/MessagePackOptionsExtension.cs b/src/EasyCaching.Serialization.MessagePack/Configurations/MessagePackOptionsExtension.cs index 0b6a286e..2202816d 100644 --- a/src/EasyCaching.Serialization.MessagePack/Configurations/MessagePackOptionsExtension.cs +++ b/src/EasyCaching.Serialization.MessagePack/Configurations/MessagePackOptionsExtension.cs @@ -1,6 +1,7 @@ namespace EasyCaching.Serialization.MessagePack { - using EasyCaching.Core; + using EasyCaching.Core.Configurations; + using EasyCaching.Core.Serialization; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; diff --git a/src/EasyCaching.Serialization.MessagePack/DefaultMessagePackSerializer.cs b/src/EasyCaching.Serialization.MessagePack/DefaultMessagePackSerializer.cs index ec9ab39a..56f05576 100644 --- a/src/EasyCaching.Serialization.MessagePack/DefaultMessagePackSerializer.cs +++ b/src/EasyCaching.Serialization.MessagePack/DefaultMessagePackSerializer.cs @@ -1,10 +1,10 @@ namespace EasyCaching.Serialization.MessagePack { - using EasyCaching.Core; using System; + using EasyCaching.Core.Serialization; using global::MessagePack; - using global::MessagePack.Resolvers; - + using global::MessagePack.Resolvers; + /// /// Default messagepack serializer. /// diff --git a/src/EasyCaching.Serialization.MessagePack/MessagePackSerializerServiceCollectionExtensions.cs b/src/EasyCaching.Serialization.MessagePack/MessagePackSerializerServiceCollectionExtensions.cs index dc32db2a..63cd23cc 100644 --- a/src/EasyCaching.Serialization.MessagePack/MessagePackSerializerServiceCollectionExtensions.cs +++ b/src/EasyCaching.Serialization.MessagePack/MessagePackSerializerServiceCollectionExtensions.cs @@ -1,8 +1,8 @@ namespace EasyCaching.Serialization.MessagePack { - using EasyCaching.Core; - using Microsoft.Extensions.DependencyInjection; using System; + using EasyCaching.Core.Serialization; + using Microsoft.Extensions.DependencyInjection; public static class MessagePackSerializerServiceCollectionExtensions { diff --git a/src/EasyCaching.Serialization.Protobuf/Configurations/EasyCachingOptionsExtensions.cs b/src/EasyCaching.Serialization.Protobuf/Configurations/EasyCachingOptionsExtensions.cs index ceeced95..4977243f 100644 --- a/src/EasyCaching.Serialization.Protobuf/Configurations/EasyCachingOptionsExtensions.cs +++ b/src/EasyCaching.Serialization.Protobuf/Configurations/EasyCachingOptionsExtensions.cs @@ -1,6 +1,6 @@ namespace EasyCaching.Serialization.Protobuf { - using EasyCaching.Core; + using EasyCaching.Core.Configurations; /// /// EasyCaching options extensions. diff --git a/src/EasyCaching.Serialization.Protobuf/Configurations/ProtobufOptionsExtension.cs b/src/EasyCaching.Serialization.Protobuf/Configurations/ProtobufOptionsExtension.cs index 2c2eea87..5adedf3d 100644 --- a/src/EasyCaching.Serialization.Protobuf/Configurations/ProtobufOptionsExtension.cs +++ b/src/EasyCaching.Serialization.Protobuf/Configurations/ProtobufOptionsExtension.cs @@ -1,6 +1,7 @@ namespace EasyCaching.Serialization.Protobuf { - using EasyCaching.Core; + using EasyCaching.Core.Configurations; + using EasyCaching.Core.Serialization; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; diff --git a/src/EasyCaching.Serialization.Protobuf/DefaultProtobufSerializer.cs b/src/EasyCaching.Serialization.Protobuf/DefaultProtobufSerializer.cs index 99c6f323..2e7b6f40 100644 --- a/src/EasyCaching.Serialization.Protobuf/DefaultProtobufSerializer.cs +++ b/src/EasyCaching.Serialization.Protobuf/DefaultProtobufSerializer.cs @@ -1,12 +1,11 @@ namespace EasyCaching.Serialization.Protobuf { - using EasyCaching.Core; - using EasyCaching.Core.Internal; - using ProtoBuf; using System; - using System.Collections.Concurrent; using System.IO; using System.Text; + using EasyCaching.Core.Internal; + using EasyCaching.Core.Serialization; + using ProtoBuf; /// /// Default protobuf serializer. diff --git a/src/EasyCaching.Serialization.Protobuf/ProtobufSerializerServiceCollectionExtensions.cs b/src/EasyCaching.Serialization.Protobuf/ProtobufSerializerServiceCollectionExtensions.cs index 1412b67d..fc2012d7 100644 --- a/src/EasyCaching.Serialization.Protobuf/ProtobufSerializerServiceCollectionExtensions.cs +++ b/src/EasyCaching.Serialization.Protobuf/ProtobufSerializerServiceCollectionExtensions.cs @@ -1,8 +1,8 @@ namespace EasyCaching.Serialization.Protobuf { - using EasyCaching.Core; - using Microsoft.Extensions.DependencyInjection; using System; + using EasyCaching.Core.Serialization; + using Microsoft.Extensions.DependencyInjection; /// /// Protobuf serializer service collection extensions. diff --git a/test/EasyCaching.PerformanceTests/SerializerBenchmark.cs b/test/EasyCaching.PerformanceTests/SerializerBenchmark.cs index f193ace9..497d1956 100644 --- a/test/EasyCaching.PerformanceTests/SerializerBenchmark.cs +++ b/test/EasyCaching.PerformanceTests/SerializerBenchmark.cs @@ -2,6 +2,7 @@ { using BenchmarkDotNet.Attributes; using EasyCaching.Core; + using EasyCaching.Core.Serialization; using EasyCaching.Serialization.Json; using EasyCaching.Serialization.MessagePack; using EasyCaching.Serialization.Protobuf; diff --git a/test/EasyCaching.UnitTests/CachingTests/RedisCachingProviderTest.cs b/test/EasyCaching.UnitTests/CachingTests/RedisCachingProviderTest.cs index 20579c58..042757ec 100644 --- a/test/EasyCaching.UnitTests/CachingTests/RedisCachingProviderTest.cs +++ b/test/EasyCaching.UnitTests/CachingTests/RedisCachingProviderTest.cs @@ -1,6 +1,7 @@ namespace EasyCaching.UnitTests { using EasyCaching.Core; + using EasyCaching.Core.Configurations; using EasyCaching.Core.Internal; using EasyCaching.Redis; using Microsoft.Extensions.DependencyInjection; diff --git a/test/EasyCaching.UnitTests/CachingTests/SERedisFeatureCachingProviderTest.cs b/test/EasyCaching.UnitTests/CachingTests/SERedisFeatureCachingProviderTest.cs index eca1c6e8..0159ca71 100644 --- a/test/EasyCaching.UnitTests/CachingTests/SERedisFeatureCachingProviderTest.cs +++ b/test/EasyCaching.UnitTests/CachingTests/SERedisFeatureCachingProviderTest.cs @@ -1,6 +1,7 @@ namespace EasyCaching.UnitTests { - using EasyCaching.Core; + using EasyCaching.Core; + using EasyCaching.Core.Configurations; using EasyCaching.Core.Internal; using EasyCaching.Redis; using Microsoft.Extensions.DependencyInjection; diff --git a/test/EasyCaching.UnitTests/Core/ArgumentCheckTest.cs b/test/EasyCaching.UnitTests/Core/ArgumentCheckTest.cs index d445cd47..5cf7ce7c 100644 --- a/test/EasyCaching.UnitTests/Core/ArgumentCheckTest.cs +++ b/test/EasyCaching.UnitTests/Core/ArgumentCheckTest.cs @@ -1,6 +1,6 @@ namespace EasyCaching.UnitTests { - using EasyCaching.Core.Internal; + using EasyCaching.Core; using System; using Xunit; using System.Collections.Generic; diff --git a/test/EasyCaching.UnitTests/Core/DefaultEasyCachingKeyGeneratorTest.cs b/test/EasyCaching.UnitTests/Core/DefaultEasyCachingKeyGeneratorTest.cs index 0035e43e..cb7e00fe 100644 --- a/test/EasyCaching.UnitTests/Core/DefaultEasyCachingKeyGeneratorTest.cs +++ b/test/EasyCaching.UnitTests/Core/DefaultEasyCachingKeyGeneratorTest.cs @@ -4,8 +4,7 @@ using System.Reflection; using System.Security.Cryptography; using System.Text; - using EasyCaching.Core; - using EasyCaching.Core.Internal; + using EasyCaching.Core.Interceptor; using Xunit; public class DefaultEasyCachingKeyGeneratorTest diff --git a/test/EasyCaching.UnitTests/Infrastructure/IExampleService.cs b/test/EasyCaching.UnitTests/Infrastructure/IExampleService.cs index ac86f610..2d046cf1 100644 --- a/test/EasyCaching.UnitTests/Infrastructure/IExampleService.cs +++ b/test/EasyCaching.UnitTests/Infrastructure/IExampleService.cs @@ -1,9 +1,9 @@ namespace EasyCaching.UnitTests.Infrastructure { - using EasyCaching.Core.Internal; using System; - using System.Threading.Tasks; using System.Collections.Generic; + using System.Threading.Tasks; + using EasyCaching.Core.Interceptor; public interface ICastleExampleService { diff --git a/test/EasyCaching.UnitTests/InterceptorTests/AspectCoreInterceptorTest.cs b/test/EasyCaching.UnitTests/InterceptorTests/AspectCoreInterceptorTest.cs index 05bb08a6..9f5bb329 100755 --- a/test/EasyCaching.UnitTests/InterceptorTests/AspectCoreInterceptorTest.cs +++ b/test/EasyCaching.UnitTests/InterceptorTests/AspectCoreInterceptorTest.cs @@ -1,16 +1,15 @@ namespace EasyCaching.UnitTests { - using AspectCore.Configuration; - using AspectCore.Injector; + using System; + using System.Linq; + using System.Threading; + using System.Threading.Tasks; using EasyCaching.Core; + using EasyCaching.Core.Interceptor; using EasyCaching.InMemory; using EasyCaching.Interceptor.AspectCore; using EasyCaching.UnitTests.Infrastructure; using Microsoft.Extensions.DependencyInjection; - using System; - using System.Linq; - using System.Threading; - using System.Threading.Tasks; using Xunit; public abstract class BaseAspectCoreInterceptorTest diff --git a/test/EasyCaching.UnitTests/InterceptorTests/CastleInterceptorTest.cs b/test/EasyCaching.UnitTests/InterceptorTests/CastleInterceptorTest.cs index 1b9a40eb..d505070d 100755 --- a/test/EasyCaching.UnitTests/InterceptorTests/CastleInterceptorTest.cs +++ b/test/EasyCaching.UnitTests/InterceptorTests/CastleInterceptorTest.cs @@ -1,20 +1,20 @@ namespace EasyCaching.UnitTests { - using EasyCaching.Core.Internal; - using EasyCaching.UnitTests.Infrastructure; - using EasyCaching.Interceptor.Castle; - using EasyCaching.InMemory; using System; + using System.Collections.Generic; + using System.Linq; + using System.Reflection; using System.Threading; - using Xunit; - using Microsoft.Extensions.DependencyInjection; - using EasyCaching.Core; + using System.Threading.Tasks; using Autofac; - using System.Reflection; using Autofac.Extras.DynamicProxy; - using System.Threading.Tasks; - using System.Linq; - using System.Collections.Generic; + using EasyCaching.Core; + using EasyCaching.Core.Interceptor; + using EasyCaching.InMemory; + using EasyCaching.Interceptor.Castle; + using EasyCaching.UnitTests.Infrastructure; + using Microsoft.Extensions.DependencyInjection; + using Xunit; public abstract class BaseCastleInterceptorTest { diff --git a/test/EasyCaching.UnitTests/SerializerTests/BaseSerializerTest.cs b/test/EasyCaching.UnitTests/SerializerTests/BaseSerializerTest.cs index abcbe5f5..49dbcda4 100644 --- a/test/EasyCaching.UnitTests/SerializerTests/BaseSerializerTest.cs +++ b/test/EasyCaching.UnitTests/SerializerTests/BaseSerializerTest.cs @@ -1,9 +1,9 @@ namespace EasyCaching.UnitTests { - using EasyCaching.Core; using System; - using Xunit; + using EasyCaching.Core.Serialization; using ProtoBuf; + using Xunit; public abstract class BaseSerializerTest { diff --git a/test/EasyCaching.UnitTests/SerializerTests/BinaryFormatterSerializerTest.cs b/test/EasyCaching.UnitTests/SerializerTests/BinaryFormatterSerializerTest.cs index 8aa77e54..829b5878 100644 --- a/test/EasyCaching.UnitTests/SerializerTests/BinaryFormatterSerializerTest.cs +++ b/test/EasyCaching.UnitTests/SerializerTests/BinaryFormatterSerializerTest.cs @@ -1,6 +1,6 @@ namespace EasyCaching.UnitTests { - using EasyCaching.Core; + using EasyCaching.Core.Serialization; public class BinaryFormatterSerializerTest : BaseSerializerTest { diff --git a/test/EasyCaching.UnitTests/SerializerTests/SerializerServiceCollectionExtensionsTest.cs b/test/EasyCaching.UnitTests/SerializerTests/SerializerServiceCollectionExtensionsTest.cs index 55137c19..7e466e4d 100644 --- a/test/EasyCaching.UnitTests/SerializerTests/SerializerServiceCollectionExtensionsTest.cs +++ b/test/EasyCaching.UnitTests/SerializerTests/SerializerServiceCollectionExtensionsTest.cs @@ -7,6 +7,7 @@ using Microsoft.Extensions.DependencyInjection; using System; using Xunit; + using EasyCaching.Core.Serialization; public class SerializerServiceCollectionExtensionsTest { From 296b2b853f3f010f89bb6aa2b9df327bbf553728 Mon Sep 17 00:00:00 2001 From: catcherwong Date: Sun, 3 Feb 2019 08:31:34 +0800 Subject: [PATCH 08/20] :ok_hand: Add identifier of Hybrid and EasyCachingMessage. --- .../EasyCachingOptionsExtensions.cs | 12 ++++----- .../Bus/EasyCachingMessage.cs | 6 +++++ .../HybridCachingProvider.cs | 25 ++++++++++++------- 3 files changed, 27 insertions(+), 16 deletions(-) rename src/EasyCaching.Bus.Redis/{ => Configurations}/EasyCachingOptionsExtensions.cs (84%) diff --git a/src/EasyCaching.Bus.Redis/EasyCachingOptionsExtensions.cs b/src/EasyCaching.Bus.Redis/Configurations/EasyCachingOptionsExtensions.cs similarity index 84% rename from src/EasyCaching.Bus.Redis/EasyCachingOptionsExtensions.cs rename to src/EasyCaching.Bus.Redis/Configurations/EasyCachingOptionsExtensions.cs index db87cd78..0c5192e5 100644 --- a/src/EasyCaching.Bus.Redis/EasyCachingOptionsExtensions.cs +++ b/src/EasyCaching.Bus.Redis/Configurations/EasyCachingOptionsExtensions.cs @@ -1,9 +1,8 @@ namespace EasyCaching.Bus.Redis { - using EasyCaching.Core; + using System; using EasyCaching.Core.Configurations; using Microsoft.Extensions.Configuration; - using System; /// /// EasyCaching options extensions. @@ -11,12 +10,12 @@ public static class EasyCachingOptionsExtensions { /// - /// Uses the redis bus. + /// Withs the redis bus. /// /// The redis bus. /// Options. /// Configure. - public static EasyCachingOptions UseRedisBus(this EasyCachingOptions options, Action configure) + public static EasyCachingOptions WithRedisBus(this EasyCachingOptions options, Action configure) { if (configure == null) { @@ -27,15 +26,14 @@ public static EasyCachingOptions UseRedisBus(this EasyCachingOptions options, Ac return options; } - /// - /// Uses the redis bus. + /// Withs the redis bus. /// /// The redis bus. /// Options. /// Configuration. /// Section name. - public static EasyCachingOptions UseRedisBus(this EasyCachingOptions options, IConfiguration configuration, string sectionName = "redisbus") + public static EasyCachingOptions WithRedisBus(this EasyCachingOptions options, IConfiguration configuration, string sectionName = "redisbus") { var dbConfig = configuration.GetSection(sectionName); var redisOptions = new RedisBusOptions(); diff --git a/src/EasyCaching.Core/Bus/EasyCachingMessage.cs b/src/EasyCaching.Core/Bus/EasyCachingMessage.cs index 9284dc9f..c8b86729 100644 --- a/src/EasyCaching.Core/Bus/EasyCachingMessage.cs +++ b/src/EasyCaching.Core/Bus/EasyCachingMessage.cs @@ -8,6 +8,12 @@ [Serializable] public class EasyCachingMessage { + /// + /// Gets or sets the identifier. + /// + /// The identifier. + public string Id { get; set; } + /// /// Gets or sets the cache keys. /// diff --git a/src/EasyCaching.HybridCache/HybridCachingProvider.cs b/src/EasyCaching.HybridCache/HybridCachingProvider.cs index 445d16f5..6475e07e 100644 --- a/src/EasyCaching.HybridCache/HybridCachingProvider.cs +++ b/src/EasyCaching.HybridCache/HybridCachingProvider.cs @@ -1,14 +1,13 @@ namespace EasyCaching.HybridCache { - using EasyCaching.Core; - using EasyCaching.Core.Internal; - using Microsoft.Extensions.Options; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; - using Microsoft.Extensions.Logging; + using EasyCaching.Core; using EasyCaching.Core.Bus; + using Microsoft.Extensions.Logging; + using Microsoft.Extensions.Options; /// /// Hybrid caching provider. @@ -35,6 +34,10 @@ public class HybridCachingProvider : IHybridCachingProvider /// The logger. /// private readonly ILogger _logger; + /// + /// The cache identifier. + /// + private readonly string _cacheId = Guid.NewGuid().ToString("N"); /// /// Initializes a new instance of the class. @@ -80,6 +83,10 @@ IOptions optionsAccs /// Message. private void OnMessage(EasyCachingMessage message) { + // each clients will recive the message, current client should ignore. + if (string.IsNullOrWhiteSpace(message.Id) && message.Id.Equals(_cacheId, StringComparison.OrdinalIgnoreCase)) + return; + foreach (var item in message.CacheKeys) { _localCache.Remove(item); @@ -132,7 +139,7 @@ public CacheValue Get(string cacheKey) return cacheValue; } - if(_options.EnableLogging) + if (_options.EnableLogging) { _logger.LogTrace($"local cache can not get the value of {cacheKey}"); } @@ -205,7 +212,7 @@ public void Remove(string cacheKey) _localCache.Remove(cacheKey); //send message to bus - _bus.Publish(_options.TopicName, new EasyCachingMessage { CacheKeys = new string[] { cacheKey } }); + _bus.Publish(_options.TopicName, new EasyCachingMessage { Id = _cacheId, CacheKeys = new string[] { cacheKey } }); } /// @@ -221,7 +228,7 @@ public async Task RemoveAsync(string cacheKey) await _localCache.RemoveAsync(cacheKey); //send message to bus - await _bus.PublishAsync(_options.TopicName, new EasyCachingMessage { CacheKeys = new string[] { cacheKey } }); + await _bus.PublishAsync(_options.TopicName, new EasyCachingMessage { Id = _cacheId, CacheKeys = new string[] { cacheKey } }); } /// @@ -239,7 +246,7 @@ public void Set(string cacheKey, T cacheValue, TimeSpan expiration) _distributedCache.Set(cacheKey, cacheValue, expiration); //send message to bus - _bus.Publish(_options.TopicName, new EasyCachingMessage { CacheKeys = new string[] { cacheKey } }); + _bus.Publish(_options.TopicName, new EasyCachingMessage { Id = _cacheId, CacheKeys = new string[] { cacheKey } }); } /// @@ -258,7 +265,7 @@ public async Task SetAsync(string cacheKey, T cacheValue, TimeSpan expiration await _distributedCache.SetAsync(cacheKey, cacheValue, expiration); //send message to bus - await _bus.PublishAsync(_options.TopicName, new EasyCachingMessage { CacheKeys = new string[] { cacheKey } }); + await _bus.PublishAsync(_options.TopicName, new EasyCachingMessage { Id = _cacheId, CacheKeys = new string[] { cacheKey } }); } /// From d95d2113ab4deebdc03ac54ee99e85c2d1a821b7 Mon Sep 17 00:00:00 2001 From: catcherwong Date: Sun, 3 Feb 2019 20:52:17 +0800 Subject: [PATCH 09/20] :bulb: Documenting source code. --- .../Configurations/RedisBusOptions.cs | 7 +++++++ .../Configurations/RedisBusOptionsExtension.cs | 10 ++++++++++ .../Configurations/RedisSubscriberProvider.cs | 2 +- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/EasyCaching.Bus.Redis/Configurations/RedisBusOptions.cs b/src/EasyCaching.Bus.Redis/Configurations/RedisBusOptions.cs index dff9b98b..46bcdb6f 100644 --- a/src/EasyCaching.Bus.Redis/Configurations/RedisBusOptions.cs +++ b/src/EasyCaching.Bus.Redis/Configurations/RedisBusOptions.cs @@ -2,8 +2,15 @@ { using EasyCaching.Core.Configurations; + /// + /// Redis bus options. + /// public class RedisBusOptions : BaseRedisOptions { + /// + /// Gets or sets the database. + /// + /// The database. public int Database { get; set; } = 0; } } diff --git a/src/EasyCaching.Bus.Redis/Configurations/RedisBusOptionsExtension.cs b/src/EasyCaching.Bus.Redis/Configurations/RedisBusOptionsExtension.cs index ec4b0f9f..a8333f7e 100644 --- a/src/EasyCaching.Bus.Redis/Configurations/RedisBusOptionsExtension.cs +++ b/src/EasyCaching.Bus.Redis/Configurations/RedisBusOptionsExtension.cs @@ -8,10 +8,20 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; + /// + /// Redis bus options extension. + /// internal sealed class RedisBusOptionsExtension : IEasyCachingOptionsExtension { + /// + /// The configure. + /// private readonly Action configure; + /// + /// Initializes a new instance of the class. + /// + /// Configure. public RedisBusOptionsExtension(Action configure) { this.configure = configure; diff --git a/src/EasyCaching.Bus.Redis/Configurations/RedisSubscriberProvider.cs b/src/EasyCaching.Bus.Redis/Configurations/RedisSubscriberProvider.cs index 4bc0769b..77a978d1 100644 --- a/src/EasyCaching.Bus.Redis/Configurations/RedisSubscriberProvider.cs +++ b/src/EasyCaching.Bus.Redis/Configurations/RedisSubscriberProvider.cs @@ -20,7 +20,7 @@ public class RedisSubscriberProvider : IRedisSubscriberProvider private readonly Lazy _connectionMultiplexer; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Options. public RedisSubscriberProvider(IOptions options) From 0d8bfb6a8ed7e0f5402628e3f97a20cd89a67dfc Mon Sep 17 00:00:00 2001 From: catcherwong Date: Mon, 4 Feb 2019 09:29:23 +0800 Subject: [PATCH 10/20] :sparkles: RabbitMQ Bus. --- .../ConnectionPooledObjectPolicy.cs | 58 ++++++ .../EasyCachingOptionsExtensions.cs | 61 +++++++ .../RabbitMQBusOptions.cs | 8 +- .../RabbitMQBusOptionsExtension.cs | 55 ++++++ .../ConnectionChannelPool.cs | 168 ------------------ .../DefaultRabbitMQBus.cs | 167 +++++++++-------- .../EasyCaching.Bus.RabbitMQ.csproj | 9 + .../IConnectionChannelPool.cs | 29 --- .../RabbitMQBusServiceCollectionExtensions.cs | 38 ---- 9 files changed, 285 insertions(+), 308 deletions(-) create mode 100644 src/EasyCaching.Bus.RabbitMQ/Configurations/ConnectionPooledObjectPolicy.cs create mode 100644 src/EasyCaching.Bus.RabbitMQ/Configurations/EasyCachingOptionsExtensions.cs rename src/EasyCaching.Bus.RabbitMQ/{ => Configurations}/RabbitMQBusOptions.cs (51%) create mode 100644 src/EasyCaching.Bus.RabbitMQ/Configurations/RabbitMQBusOptionsExtension.cs delete mode 100644 src/EasyCaching.Bus.RabbitMQ/ConnectionChannelPool.cs delete mode 100644 src/EasyCaching.Bus.RabbitMQ/IConnectionChannelPool.cs delete mode 100644 src/EasyCaching.Bus.RabbitMQ/RabbitMQBusServiceCollectionExtensions.cs diff --git a/src/EasyCaching.Bus.RabbitMQ/Configurations/ConnectionPooledObjectPolicy.cs b/src/EasyCaching.Bus.RabbitMQ/Configurations/ConnectionPooledObjectPolicy.cs new file mode 100644 index 00000000..25fe3c83 --- /dev/null +++ b/src/EasyCaching.Bus.RabbitMQ/Configurations/ConnectionPooledObjectPolicy.cs @@ -0,0 +1,58 @@ +namespace EasyCaching.Bus.RabbitMQ +{ + using Microsoft.Extensions.ObjectPool; + using Microsoft.Extensions.Options; + using global::RabbitMQ.Client; + + /// + /// Connection pooled object policy. + /// + public class ConnectionPooledObjectPolicy : IPooledObjectPolicy + { + /// + /// The options. + /// + private readonly RabbitMQBusOptions _options; + + /// + /// Initializes a new instance of the class. + /// + /// Options accs. + public ConnectionPooledObjectPolicy(IOptions optionsAccs) + { + this._options = optionsAccs.Value; + } + + /// + /// Create this instance. + /// + /// The create. + public IConnection Create() + { + var factory = new ConnectionFactory + { + HostName = _options.HostName, + UserName = _options.UserName, + Port = _options.Port, + Password = _options.Password, + VirtualHost = _options.VirtualHost, + RequestedConnectionTimeout = _options.RequestedConnectionTimeout, + SocketReadTimeout = _options.SocketReadTimeout, + SocketWriteTimeout = _options.SocketWriteTimeout + }; + + var connection = factory.CreateConnection(); + return connection; + } + + /// + /// Return the specified connection. + /// + /// The return. + /// Connection. + public bool Return(IConnection connection) + { + return true; + } + } +} \ No newline at end of file diff --git a/src/EasyCaching.Bus.RabbitMQ/Configurations/EasyCachingOptionsExtensions.cs b/src/EasyCaching.Bus.RabbitMQ/Configurations/EasyCachingOptionsExtensions.cs new file mode 100644 index 00000000..5ff72af2 --- /dev/null +++ b/src/EasyCaching.Bus.RabbitMQ/Configurations/EasyCachingOptionsExtensions.cs @@ -0,0 +1,61 @@ +namespace EasyCaching.Bus.RabbitMQ +{ + using System; + using EasyCaching.Core.Configurations; + using Microsoft.Extensions.Configuration; + + /// + /// EasyCaching options extensions. + /// + public static class EasyCachingOptionsExtensions + { + /// + /// Withs the RabbitMQ Bus. + /// + /// The rabbit MQB us. + /// Options. + /// Configure. + public static EasyCachingOptions WithRabbitMQBus(this EasyCachingOptions options, Action configure) + { + if (configure == null) + { + throw new ArgumentNullException(nameof(configure)); + } + + options.RegisterExtension(new RabbitMQBusOptionsExtension(configure)); + return options; + } + + /// + /// Withs the RabbitMQ Bus. + /// + /// The rabbit MQB us. + /// Options. + /// Configuration. + /// Section name. + public static EasyCachingOptions WithRabbitMQBus(this EasyCachingOptions options, IConfiguration configuration, string sectionName = "rabbitmqbus") + { + var dbConfig = configuration.GetSection(sectionName); + var busOptions = new RabbitMQBusOptions(); + dbConfig.Bind(busOptions); + + void configure(RabbitMQBusOptions x) + { + x.HostName = busOptions.HostName; + x.Password = busOptions.Password; + x.Port = busOptions.Port; + x.QueueMessageExpires = busOptions.QueueMessageExpires; + x.RequestedConnectionTimeout = busOptions.RequestedConnectionTimeout; + x.RouteKey = busOptions.RouteKey; + x.SocketReadTimeout = busOptions.SocketReadTimeout; + x.SocketWriteTimeout = busOptions.SocketWriteTimeout; + x.TopicExchangeName = busOptions.TopicExchangeName; + x.UserName = busOptions.UserName; + x.VirtualHost = busOptions.VirtualHost; + } + + options.RegisterExtension(new RabbitMQBusOptionsExtension(configure)); + return options; + } + } +} diff --git a/src/EasyCaching.Bus.RabbitMQ/RabbitMQBusOptions.cs b/src/EasyCaching.Bus.RabbitMQ/Configurations/RabbitMQBusOptions.cs similarity index 51% rename from src/EasyCaching.Bus.RabbitMQ/RabbitMQBusOptions.cs rename to src/EasyCaching.Bus.RabbitMQ/Configurations/RabbitMQBusOptions.cs index 63bb04c3..4a18f89a 100644 --- a/src/EasyCaching.Bus.RabbitMQ/RabbitMQBusOptions.cs +++ b/src/EasyCaching.Bus.RabbitMQ/Configurations/RabbitMQBusOptions.cs @@ -1,12 +1,16 @@ namespace EasyCaching.Bus.RabbitMQ { using EasyCaching.Core.Configurations; - using EasyCaching.Core.Internal; /// /// RabbitMQ Bus options. /// public class RabbitMQBusOptions : BaseRabbitMQOptions - { + { + /// + /// Gets or sets the route key. + /// + /// The route key. + public string RouteKey { get; set; } = "easycaching.subscriber.*"; } } diff --git a/src/EasyCaching.Bus.RabbitMQ/Configurations/RabbitMQBusOptionsExtension.cs b/src/EasyCaching.Bus.RabbitMQ/Configurations/RabbitMQBusOptionsExtension.cs new file mode 100644 index 00000000..d0c88067 --- /dev/null +++ b/src/EasyCaching.Bus.RabbitMQ/Configurations/RabbitMQBusOptionsExtension.cs @@ -0,0 +1,55 @@ +namespace EasyCaching.Bus.RabbitMQ +{ + using System; + using EasyCaching.Core.Bus; + using EasyCaching.Core.Configurations; + using EasyCaching.Core.Serialization; + using global::RabbitMQ.Client; + using Microsoft.AspNetCore.Builder; + using Microsoft.Extensions.DependencyInjection; + using Microsoft.Extensions.DependencyInjection.Extensions; + using Microsoft.Extensions.ObjectPool; + + /// + /// RabbitMQ Bus options extension. + /// + public class RabbitMQBusOptionsExtension : IEasyCachingOptionsExtension + { + /// + /// The configure. + /// + private readonly Action configure; + + /// + /// Initializes a new instance of the class. + /// + /// Configure. + public RabbitMQBusOptionsExtension(Action configure) + { + this.configure = configure; + } + + /// + /// Adds the services. + /// + /// Services. + public void AddServices(IServiceCollection services) + { + services.AddOptions(); + services.Configure(configure); + + services.TryAddSingleton(); + services.AddSingleton, ConnectionPooledObjectPolicy>(); + services.AddSingleton(); + } + + /// + /// Withs the services. + /// + /// Services. + public void WithServices(IApplicationBuilder services) + { + // Method intentionally left empty. + } + } +} diff --git a/src/EasyCaching.Bus.RabbitMQ/ConnectionChannelPool.cs b/src/EasyCaching.Bus.RabbitMQ/ConnectionChannelPool.cs deleted file mode 100644 index ff6795da..00000000 --- a/src/EasyCaching.Bus.RabbitMQ/ConnectionChannelPool.cs +++ /dev/null @@ -1,168 +0,0 @@ -namespace EasyCaching.Bus.RabbitMQ -{ - using System; - using System.Collections.Concurrent; - using System.Threading; - using global::RabbitMQ.Client; - - /// - /// Connection channel pool. - /// - public class ConnectionChannelPool : IConnectionChannelPool, IDisposable - { - /// - /// The default size of the pool. - /// - private const int DefaultPoolSize = 15; - /// - /// The connection activator. - /// - private readonly Func _connectionActivator; - /// - /// The pool. - /// - private readonly ConcurrentQueue _pool = new ConcurrentQueue(); - /// - /// The connection. - /// - private IConnection _connection; - /// - /// The count. - /// - private int _count; - /// - /// The size of the max. - /// - private int _maxSize; - - /// - /// Initializes a new instance of the class. - /// - /// Options. - public ConnectionChannelPool(RabbitMQBusOptions options) - { - _maxSize = DefaultPoolSize; - - _connectionActivator = CreateConnection(options); - } - - /// - /// - /// - /// - IModel IConnectionChannelPool.Rent() - { - return Rent(); - } - - /// - /// Easies the caching. bus. rabbit MQ . IC onnection channel pool. return. - /// - /// true, if caching. bus. rabbit MQ . IC onnection channel pool. return was easyed, false otherwise. - /// Connection. - bool IConnectionChannelPool.Return(IModel connection) - { - return Return(connection); - } - - /// - /// Gets the connection. - /// - /// The connection. - public IConnection GetConnection() - { - if (_connection != null && _connection.IsOpen) - return _connection; - _connection = _connectionActivator(); - _connection.ConnectionShutdown += RabbitMQ_ConnectionShutdown; - return _connection; - } - - /// - /// Releases all resource used by the object. - /// - /// Call when you are finished using the - /// . The method leaves the - /// in an unusable state. After calling - /// , you must release all references to the - /// so the garbage collector can reclaim the - /// memory that the was occupying. - public void Dispose() - { - _maxSize = 0; - - while (_pool.TryDequeue(out var context)) - context.Dispose(); - } - - /// - /// Creates the connection. - /// - /// The connection. - /// Options. - private static Func CreateConnection(RabbitMQBusOptions options) - { - var factory = new ConnectionFactory - { - HostName = options.HostName, - UserName = options.UserName, - Port = options.Port, - Password = options.Password, - VirtualHost = options.VirtualHost, - RequestedConnectionTimeout = options.RequestedConnectionTimeout, - SocketReadTimeout = options.SocketReadTimeout, - SocketWriteTimeout = options.SocketWriteTimeout - }; - - return () => factory.CreateConnection(); - } - - /// - /// Rabbits the mq connection shutdown. - /// - /// Sender. - /// E. - private void RabbitMQ_ConnectionShutdown(object sender, ShutdownEventArgs e) - { - Console.WriteLine("closed!"); - } - - /// - /// Rent this instance. - /// - /// The rent. - public virtual IModel Rent() - { - if (_pool.TryDequeue(out var model)) - { - Interlocked.Decrement(ref _count); - - return model; - } - - model = GetConnection().CreateModel(); - - return model; - } - - /// - /// Return the specified connection. - /// - /// The return. - /// Connection. - public virtual bool Return(IModel connection) - { - if (Interlocked.Increment(ref _count) <= _maxSize) - { - _pool.Enqueue(connection); - - return true; - } - - Interlocked.Decrement(ref _count); - - return false; - } - } - -} diff --git a/src/EasyCaching.Bus.RabbitMQ/DefaultRabbitMQBus.cs b/src/EasyCaching.Bus.RabbitMQ/DefaultRabbitMQBus.cs index 4e3489f4..1b44be6c 100644 --- a/src/EasyCaching.Bus.RabbitMQ/DefaultRabbitMQBus.cs +++ b/src/EasyCaching.Bus.RabbitMQ/DefaultRabbitMQBus.cs @@ -1,15 +1,13 @@ namespace EasyCaching.Bus.RabbitMQ { - using EasyCaching.Core; - using EasyCaching.Core.Internal; using System; - using System.Threading.Tasks; - using System.Collections.Generic; - using global::RabbitMQ.Client.Events; - using global::RabbitMQ.Client; using System.Threading; + using System.Threading.Tasks; using EasyCaching.Core.Bus; using EasyCaching.Core.Serialization; + using global::RabbitMQ.Client; + using global::RabbitMQ.Client.Events; + using Microsoft.Extensions.ObjectPool; /// /// Default RabbitMQ Bus. @@ -17,24 +15,29 @@ public class DefaultRabbitMQBus : IEasyCachingBus { /// - /// The connection channel pool. + /// The subscriber connection. /// - private readonly IConnectionChannelPool _connectionChannelPool; + private readonly IConnection _subConnection; /// - /// The rabbitMQ Bus options. + /// The publish connection pool. /// - private readonly RabbitMQBusOptions _rabbitMQBusOptions; + private readonly ObjectPool _pubConnectionPool; /// - /// The serializer. + /// The handler. /// - private readonly IEasyCachingSerializer _serializer; + private Action _handler; /// - /// The local caching provider. + /// The rabbitMQ Bus options. /// - private readonly IEasyCachingProvider _localCachingProvider; + private readonly RabbitMQBusOptions _options; + + /// + /// The serializer. + /// + private readonly IEasyCachingSerializer _serializer; /// /// Initializes a new instance of the class. @@ -44,32 +47,46 @@ public class DefaultRabbitMQBus : IEasyCachingBus /// Serializer. /// Local caching provider. public DefaultRabbitMQBus( - IConnectionChannelPool connectionChannelPool, - RabbitMQBusOptions rabbitMQOptions, - IEasyCachingSerializer serializer, - IEasyCachingProvider localCachingProvider) + IPooledObjectPolicy _objectPolicy + ,RabbitMQBusOptions rabbitMQOptions + ,IEasyCachingSerializer serializer) { - this._rabbitMQBusOptions = rabbitMQOptions; - this._connectionChannelPool = connectionChannelPool; + this._options = rabbitMQOptions; this._serializer = serializer; - this._localCachingProvider = localCachingProvider; + + var factory = new ConnectionFactory + { + HostName = _options.HostName, + UserName = _options.UserName, + Port = _options.Port, + Password = _options.Password, + VirtualHost = _options.VirtualHost, + RequestedConnectionTimeout = _options.RequestedConnectionTimeout, + SocketReadTimeout = _options.SocketReadTimeout, + SocketWriteTimeout = _options.SocketWriteTimeout + }; + + _subConnection = factory.CreateConnection(); + + _pubConnectionPool = new DefaultObjectPool(_objectPolicy); } - + /// - /// Publish the specified channel and message. + /// Publish the specified topic and message. /// - /// The publish. - /// Channel. + /// Topic. /// Message. - public void Publish(string channel, EasyCachingMessage message) + public void Publish(string topic, EasyCachingMessage message) { - var _publisherChannel = _connectionChannelPool.Rent(); + var conn = _pubConnectionPool.Get(); + try - { + { var body = _serializer.Serialize(message); + var model = conn.CreateModel(); - _publisherChannel.ExchangeDeclare(_rabbitMQBusOptions.TopicExchangeName, ExchangeType.Topic, true, false, null); - _publisherChannel.BasicPublish(_rabbitMQBusOptions.TopicExchangeName, channel, false, null, body); + model.ExchangeDeclare(_options.TopicExchangeName, ExchangeType.Topic, true, false, null); + model.BasicPublish(_options.TopicExchangeName, topic, false, null, body); } catch (Exception ex) { @@ -77,78 +94,86 @@ public void Publish(string channel, EasyCachingMessage message) } finally { - var returned = _connectionChannelPool.Return(_publisherChannel); - if (!returned) - _publisherChannel.Dispose(); + _pubConnectionPool.Return(conn); } } /// - /// Publishs the async. + /// Publish the specified topic and message async. /// /// The async. - /// Channel. + /// Topic. /// Message. - public Task PublishAsync(string channel, EasyCachingMessage message) - { - throw new NotImplementedException(); - } - + /// Cancellation token. public Task PublishAsync(string topic, EasyCachingMessage message, CancellationToken cancellationToken = default(CancellationToken)) { - throw new NotImplementedException(); - } + var conn = _pubConnectionPool.Get(); + try + { + var body = _serializer.Serialize(message); + var model = conn.CreateModel(); + model.ExchangeDeclare(_options.TopicExchangeName, ExchangeType.Topic, true, false, null); + model.BasicPublish(_options.TopicExchangeName, topic, false, null, body); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + _pubConnectionPool.Return(conn); + } + return Task.CompletedTask; + } + /// - /// Subscribe the specified channel. + /// Subscribe the specified topic and action. /// - /// The subscribe. - /// Channel. - public void Subscribe(string channel) + /// Topic. + /// Action. + public void Subscribe(string topic, Action action) { - var _connection = _connectionChannelPool.GetConnection(); - - var _subscriberChannel = _connection.CreateModel(); + _handler = action; - _subscriberChannel.ExchangeDeclare(_rabbitMQBusOptions.TopicExchangeName, ExchangeType.Topic, true, true, null); - - var arguments = new Dictionary { - { "x-message-ttl", _rabbitMQBusOptions.QueueMessageExpires } - }; + Task.Factory.StartNew(() => + { + var model = _subConnection.CreateModel(); + model.ExchangeDeclare(_options.TopicExchangeName, ExchangeType.Topic, true, false, null); - _subscriberChannel.QueueDeclare("easycaching.queue", true, false, false, arguments); + var queue = model.QueueDeclare($"easycaching.subscriber.{Guid.NewGuid().ToString("N")}", false, false, true, null); - var consumer = new EventingBasicConsumer(_subscriberChannel); - consumer.Received += OnConsumerReceived; - //consumer.Shutdown += OnConsumerShutdown; + // bind the queue with the exchange. + model.QueueBind(_options.TopicExchangeName, queue.QueueName, _options.RouteKey); + var consumer = new EventingBasicConsumer(model); + consumer.Received += OnMessage; + consumer.Shutdown += OnConsumerShutdown; - _subscriberChannel.BasicConsume("easycaching.queue", false, string.Empty, false, false, null, consumer); - } + model.BasicConsume(queue.QueueName, true, consumer); - public void Subscribe(string topic, Action action) - { - throw new NotImplementedException(); + }, TaskCreationOptions.LongRunning); } /// - /// Subscribes the async. + /// Ons the consumer shutdown. /// - /// The async. - /// Channel. - public Task SubscribeAsync(string channel) + /// Sender. + /// E. + private void OnConsumerShutdown(object sender, ShutdownEventArgs e) { - throw new NotImplementedException(); + Console.WriteLine($"{e.ReplyText}"); } /// - /// Consumers the received. + /// Ons the message. /// /// Sender. /// E. - private void OnConsumerReceived(object sender, BasicDeliverEventArgs e) + private void OnMessage(object sender, BasicDeliverEventArgs e) { - var message = _serializer.Deserialize(e.Body); + var message = _serializer.Deserialize(e.Body); + _handler?.Invoke(message); } } } diff --git a/src/EasyCaching.Bus.RabbitMQ/EasyCaching.Bus.RabbitMQ.csproj b/src/EasyCaching.Bus.RabbitMQ/EasyCaching.Bus.RabbitMQ.csproj index 689feaa3..9997a183 100644 --- a/src/EasyCaching.Bus.RabbitMQ/EasyCaching.Bus.RabbitMQ.csproj +++ b/src/EasyCaching.Bus.RabbitMQ/EasyCaching.Bus.RabbitMQ.csproj @@ -23,5 +23,14 @@ + + + + + + + + + diff --git a/src/EasyCaching.Bus.RabbitMQ/IConnectionChannelPool.cs b/src/EasyCaching.Bus.RabbitMQ/IConnectionChannelPool.cs deleted file mode 100644 index 60f7aeed..00000000 --- a/src/EasyCaching.Bus.RabbitMQ/IConnectionChannelPool.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace EasyCaching.Bus.RabbitMQ -{ - using global::RabbitMQ.Client; - - /// - /// Connection channel pool. - /// - public interface IConnectionChannelPool - { - /// - /// Gets the connection. - /// - /// The connection. - IConnection GetConnection(); - - /// - /// Rent this instance. - /// - /// The rent. - IModel Rent(); - - /// - /// Return the specified context. - /// - /// The return. - /// Context. - bool Return(IModel context); - } -} diff --git a/src/EasyCaching.Bus.RabbitMQ/RabbitMQBusServiceCollectionExtensions.cs b/src/EasyCaching.Bus.RabbitMQ/RabbitMQBusServiceCollectionExtensions.cs deleted file mode 100644 index 0097aa99..00000000 --- a/src/EasyCaching.Bus.RabbitMQ/RabbitMQBusServiceCollectionExtensions.cs +++ /dev/null @@ -1,38 +0,0 @@ -namespace EasyCaching.Bus.RabbitMQ -{ - using System; - using EasyCaching.Core; - using EasyCaching.Core.Bus; - using EasyCaching.Core.Serialization; - using Microsoft.Extensions.DependencyInjection; - using Microsoft.Extensions.DependencyInjection.Extensions; - - /// - /// RabbitMQ Bus service collection extensions. - /// - public static class RabbitMQBusServiceCollectionExtensions - { - /// - /// Adds the default rabbitMQ Bus. - /// - /// The default rabbit MQB us. - /// Services. - /// Options action. - public static IServiceCollection AddDefaultRabbitMQBus(this IServiceCollection services, Action optionsAction) - { - ArgumentCheck.NotNull(services, nameof(services)); - ArgumentCheck.NotNull(optionsAction, nameof(optionsAction)); - - var options = new RabbitMQBusOptions(); - optionsAction?.Invoke(options); - services.AddSingleton(options); - - services.TryAddSingleton(); - services.TryAddSingleton(); - services.TryAddSingleton(); - services.TryAddSingleton(); - - return services; - } - } -} From 15d211ae3f28a5727bfa54782bda4c5bafb3615f Mon Sep 17 00:00:00 2001 From: catcherwong Date: Tue, 5 Feb 2019 10:20:58 +0800 Subject: [PATCH 11/20] :ok_hand: Make RedisSubscriberProvider internal. --- .../Configurations/RedisSubscriberProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EasyCaching.Bus.Redis/Configurations/RedisSubscriberProvider.cs b/src/EasyCaching.Bus.Redis/Configurations/RedisSubscriberProvider.cs index 77a978d1..6e1dbd01 100644 --- a/src/EasyCaching.Bus.Redis/Configurations/RedisSubscriberProvider.cs +++ b/src/EasyCaching.Bus.Redis/Configurations/RedisSubscriberProvider.cs @@ -7,7 +7,7 @@ /// /// Redis database provider. /// - public class RedisSubscriberProvider : IRedisSubscriberProvider + internal class RedisSubscriberProvider : IRedisSubscriberProvider { /// /// The options. From a063aa08cd4938410b30ee6c0c0ae9b02bb4f02f Mon Sep 17 00:00:00 2001 From: catcherwong Date: Tue, 5 Feb 2019 20:49:58 +0800 Subject: [PATCH 12/20] :bulb: Documenting source code. --- src/EasyCaching.Bus.Redis/DefaultRedisBus.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/EasyCaching.Bus.Redis/DefaultRedisBus.cs b/src/EasyCaching.Bus.Redis/DefaultRedisBus.cs index 22c69ad8..15bfc92a 100644 --- a/src/EasyCaching.Bus.Redis/DefaultRedisBus.cs +++ b/src/EasyCaching.Bus.Redis/DefaultRedisBus.cs @@ -34,9 +34,10 @@ public class DefaultRedisBus : IEasyCachingBus private readonly IEasyCachingSerializer _serializer; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Subscriber provider. + /// Serializer. public DefaultRedisBus( IRedisSubscriberProvider subscriberProvider, IEasyCachingSerializer serializer) From 61703b6d386d57f228404034c89c672a333de192 Mon Sep 17 00:00:00 2001 From: catcherwong Date: Wed, 6 Feb 2019 10:55:14 +0800 Subject: [PATCH 13/20] :sparkles: Add new APIs for HybridCaching Provider. --- .../IHybridCachingProvider.cs | 52 ++++++++ .../HybridCachingProvider.cs | 124 +++++++++++++++++- 2 files changed, 173 insertions(+), 3 deletions(-) diff --git a/src/EasyCaching.Core/IHybridCachingProvider.cs b/src/EasyCaching.Core/IHybridCachingProvider.cs index 749fafce..71ffc239 100644 --- a/src/EasyCaching.Core/IHybridCachingProvider.cs +++ b/src/EasyCaching.Core/IHybridCachingProvider.cs @@ -1,6 +1,7 @@ namespace EasyCaching.Core { using System; + using System.Collections.Generic; using System.Threading.Tasks; /// @@ -89,5 +90,56 @@ public interface IHybridCachingProvider /// Expiration. /// The 1st type parameter. Task TrySetAsync(string cacheKey, T cacheValue, TimeSpan expiration); + + /// + /// Sets all. + /// + /// Value. + /// Expiration. + /// The 1st type parameter. + void SetAll(IDictionary value, TimeSpan expiration); + + /// + /// Sets all async. + /// + /// The all async. + /// Value. + /// Expiration. + /// The 1st type parameter. + Task SetAllAsync(IDictionary value, TimeSpan expiration); + + /// + /// Removes all. + /// + /// Cache keys. + void RemoveAll(IEnumerable cacheKeys); + + /// + /// Removes all async. + /// + /// The all async. + /// Cache keys. + Task RemoveAllAsync(IEnumerable cacheKeys); + + /// + /// Get the specified cacheKey, dataRetriever and expiration. + /// + /// The get. + /// Cache key. + /// Data retriever. + /// Expiration. + /// The 1st type parameter. + CacheValue Get(string cacheKey, Func dataRetriever, TimeSpan expiration); + + /// + /// Gets the specified cacheKey, dataRetriever and expiration async. + /// + /// The async. + /// Cache key. + /// Data retriever. + /// Expiration. + /// The 1st type parameter. + Task> GetAsync(string cacheKey, Func> dataRetriever, TimeSpan expiration); + } } diff --git a/src/EasyCaching.HybridCache/HybridCachingProvider.cs b/src/EasyCaching.HybridCache/HybridCachingProvider.cs index 6475e07e..5fdfd718 100644 --- a/src/EasyCaching.HybridCache/HybridCachingProvider.cs +++ b/src/EasyCaching.HybridCache/HybridCachingProvider.cs @@ -37,7 +37,7 @@ public class HybridCachingProvider : IHybridCachingProvider /// /// The cache identifier. /// - private readonly string _cacheId = Guid.NewGuid().ToString("N"); + private readonly string _cacheId; /// /// Initializes a new instance of the class. @@ -75,6 +75,8 @@ IOptions optionsAccs this._bus = bus ?? NullEasyCachingBus.Instance; this._bus.Subscribe(_options.TopicName, OnMessage); + + this._cacheId = Guid.NewGuid().ToString("N"); } /// @@ -148,6 +150,7 @@ public CacheValue Get(string cacheKey) if (cacheValue.HasValue) { + //TODO: What about the value of expiration? Form configuration or others? _localCache.Set(cacheKey, cacheValue.Value, TimeSpan.FromSeconds(60)); return cacheValue; @@ -187,6 +190,7 @@ public async Task> GetAsync(string cacheKey) if (cacheValue.HasValue) { + //TODO: What about the value of expiration? Form configuration or others? await _localCache.SetAsync(cacheKey, cacheValue.Value, TimeSpan.FromSeconds(60)); return cacheValue; @@ -208,6 +212,7 @@ public void Remove(string cacheKey) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); + //distributed cache at first _distributedCache.Remove(cacheKey); _localCache.Remove(cacheKey); @@ -224,6 +229,7 @@ public async Task RemoveAsync(string cacheKey) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); + //distributed cache at first await _distributedCache.RemoveAsync(cacheKey); await _localCache.RemoveAsync(cacheKey); @@ -245,7 +251,7 @@ public void Set(string cacheKey, T cacheValue, TimeSpan expiration) _localCache.Set(cacheKey, cacheValue, expiration); _distributedCache.Set(cacheKey, cacheValue, expiration); - //send message to bus + //When create/update cache, send message to bus so that other clients can remove it. _bus.Publish(_options.TopicName, new EasyCachingMessage { Id = _cacheId, CacheKeys = new string[] { cacheKey } }); } @@ -264,7 +270,7 @@ public async Task SetAsync(string cacheKey, T cacheValue, TimeSpan expiration await _localCache.SetAsync(cacheKey, cacheValue, expiration); await _distributedCache.SetAsync(cacheKey, cacheValue, expiration); - //send message to bus + //When create/update cache, send message to bus so that other clients can remove it. await _bus.PublishAsync(_options.TopicName, new EasyCachingMessage { Id = _cacheId, CacheKeys = new string[] { cacheKey } }); } @@ -284,6 +290,7 @@ public bool TrySet(string cacheKey, T cacheValue, TimeSpan expiration) if (flag) { + //When TrySet succeed in distributed cache, Set(not TrySet) this cache to local cache. _localCache.Set(cacheKey, cacheValue, expiration); } @@ -306,10 +313,121 @@ public async Task TrySetAsync(string cacheKey, T cacheValue, TimeSpan e if (flag) { + //When we TrySet succeed in distributed cache, we should Set this cache to local cache. await _localCache.SetAsync(cacheKey, cacheValue, expiration); } return flag; } + + /// + /// Sets all. + /// + /// Value. + /// Expiration. + /// The 1st type parameter. + public void SetAll(IDictionary value, TimeSpan expiration) + { + _distributedCache.SetAll(value, expiration); + } + + /// + /// Sets all async. + /// + /// The all async. + /// Value. + /// Expiration. + /// The 1st type parameter. + public async Task SetAllAsync(IDictionary value, TimeSpan expiration) + { + await _distributedCache.SetAllAsync(value, expiration); + } + + /// + /// Removes all. + /// + /// Cache keys. + public void RemoveAll(IEnumerable cacheKeys) + { + ArgumentCheck.NotNullAndCountGTZero(cacheKeys, nameof(cacheKeys)); + + _localCache.RemoveAll(cacheKeys); + + _distributedCache.RemoveAllAsync(cacheKeys); + + //send message to bus in order to notify other clients. + _bus.Publish(_options.TopicName, new EasyCachingMessage { Id = _cacheId, CacheKeys = cacheKeys.ToArray() }); + } + + /// + /// Removes all async. + /// + /// The all async. + /// Cache keys. + public async Task RemoveAllAsync(IEnumerable cacheKeys) + { + ArgumentCheck.NotNullAndCountGTZero(cacheKeys, nameof(cacheKeys)); + + await _localCache.RemoveAllAsync(cacheKeys); + + await _distributedCache.RemoveAllAsync(cacheKeys); + + //send message to bus in order to notify other clients. + await _bus.PublishAsync(_options.TopicName, new EasyCachingMessage { Id = _cacheId, CacheKeys = cacheKeys.ToArray() }); + } + + /// + /// Get the specified cacheKey, dataRetriever and expiration. + /// + /// The get. + /// Cache key. + /// Data retriever. + /// Expiration. + /// The 1st type parameter. + public CacheValue Get(string cacheKey, Func dataRetriever, TimeSpan expiration) + { + ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); + ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); + + var result = _localCache.Get(cacheKey); + + if(result.HasValue) + { + return result; + } + + result = _distributedCache.Get(cacheKey, dataRetriever , expiration); + + return result.HasValue + ? result + : CacheValue.NoValue; + } + + /// + /// Gets the specified cacheKey, dataRetriever and expiration async. + /// + /// The async. + /// Cache key. + /// Data retriever. + /// Expiration. + /// The 1st type parameter. + public async Task> GetAsync(string cacheKey, Func> dataRetriever, TimeSpan expiration) + { + ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); + ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); + + var result = await _localCache.GetAsync(cacheKey); + + if (result.HasValue) + { + return result; + } + + result = await _distributedCache.GetAsync(cacheKey, dataRetriever , expiration); + + return result.HasValue + ? result + : CacheValue.NoValue; + } } } From dabbf7f4ea6eb6a4efbefbf9b4825f9a7788b746 Mon Sep 17 00:00:00 2001 From: catcherwong Date: Thu, 7 Feb 2019 10:56:48 +0800 Subject: [PATCH 14/20] :white_check_mark: Add tests for Hybrid. --- .../CachingTests/HybridCachingTest.cs | 236 +++++++++++------- .../EasyCaching.UnitTests.csproj | 2 + 2 files changed, 146 insertions(+), 92 deletions(-) diff --git a/test/EasyCaching.UnitTests/CachingTests/HybridCachingTest.cs b/test/EasyCaching.UnitTests/CachingTests/HybridCachingTest.cs index 044623a0..1466da13 100644 --- a/test/EasyCaching.UnitTests/CachingTests/HybridCachingTest.cs +++ b/test/EasyCaching.UnitTests/CachingTests/HybridCachingTest.cs @@ -1,92 +1,144 @@ -//namespace EasyCaching.UnitTests -//{ -// using EasyCaching.Core; -// using EasyCaching.Core.Internal; -// using EasyCaching.HybridCache; -// using EasyCaching.InMemory; -// using EasyCaching.Redis; -// using FakeItEasy; -// using Microsoft.Extensions.Caching.Memory; -// using Microsoft.Extensions.Options; -// using System; -// using System.Collections.Generic; -// using System.Threading.Tasks; -// using Xunit; - -// public class HybridCachingTest : BaseCachingProviderTest -// { -// public HybridCachingTest() -// { -// RedisOptions options = new RedisOptions(); -// options.DBConfig.AllowAdmin = true; -// options.DBConfig.Endpoints.Add(new ServerEndPoint("127.0.0.1", 6379)); -// options.DBConfig.Database = 6; - -// var fakeOption = A.Fake>(); - -// A.CallTo(() => fakeOption.CurrentValue).Returns(options); - -// var fakeDbProvider = A.Fake(option => option.WithArgumentsForConstructor(new object[] { fakeOption })); - -// var serializer = new DefaultBinaryFormatterSerializer(); - -// var providers = new List -// { -// new DefaultInMemoryCachingProvider(new InMemory.InMemoryCaching(new InMemoryCachingOptions()), new TestOptionMonitorWrapper(new InMemoryOptions())), -// new DefaultRedisCachingProvider(fakeDbProvider, serializer, new TestOptionMonitorWrapper(new RedisOptions())) -// }; - -// _provider = new HybridCachingProvider(providers); -// _defaultTs = TimeSpan.FromSeconds(30); -// _nameSpace = "HybridBasic"; -// } - -// [Fact] -// protected override void Get_Count_Without_Prefix_Should_Succeed() -// { - -// } - -// [Fact] -// protected override void Get_Count_With_Prefix_Should_Succeed() -// { - -// } - -// [Fact] -// protected override void OnHit_Should_Return_One_And_OnMiss_Should_Return_Zero() -// { - -// } - -// [Fact] -// protected override void OnHit_Should_Return_Zero_And_OnMiss_Should_Return_One() -// { - -// } - -// [Fact] -// protected override void TrySet_Value_And_Get_Cached_Value_Should_Succeed() -// { - -// } - -// [Fact] -// protected override async Task TrySet_Value_And_Get_Cached_Value_Async_Should_Succeed() -// { -// await Task.FromResult(1); -// } - -// [Fact] -// protected override void Get_Parallel_Should_Succeed() -// { - -// } - -// [Fact] -// protected override Task GetAsync_Parallel_Should_Succeed() -// { -// return Task.FromResult(1); -// } -// } -//} +namespace EasyCaching.UnitTests +{ + using System; + using System.Collections.Generic; + using System.Threading.Tasks; + using EasyCaching.Bus.Redis; + using EasyCaching.Core; + using EasyCaching.Core.Bus; + using EasyCaching.HybridCache; + using EasyCaching.InMemory; + using EasyCaching.Redis; + using Microsoft.Extensions.DependencyInjection; + using Microsoft.Extensions.Options; + using Xunit; + + public class HybridCachingTest //: BaseCachingProviderTest + { + + private HybridCachingProvider hybridCaching_1; + private HybridCachingProvider hybridCaching_2; + private IEasyCachingProviderFactory factory; + private string _namespace; + public HybridCachingTest() + { + _namespace = "hybrid"; + IServiceCollection services = new ServiceCollection(); + services.AddEasyCaching(option => + { + option.UseInMemory("m1"); + option.UseInMemory("m2"); + + option.UseRedis(config => + { + config.DBConfig.Endpoints.Add(new Core.Configurations.ServerEndPoint("127.0.0.1", 6379)); + config.DBConfig.Database = 5; + }, "myredis"); + + option.WithRedisBus(config => + { + config.Endpoints.Add(new Core.Configurations.ServerEndPoint("127.0.0.1", 6379)); + config.Database = 6; + }); + }); + + IServiceProvider serviceProvider = services.BuildServiceProvider(); + factory = serviceProvider.GetService(); + + var providers_1 = new List + { + factory.GetCachingProvider("m1"), + factory.GetCachingProvider("myredis") + }; + + var providers_2 = new List + { + factory.GetCachingProvider("m2"), + factory.GetCachingProvider("myredis") + }; + + var bus = serviceProvider.GetService(); + + hybridCaching_1 = new HybridCachingProvider(new OptionsWrapper(new HybridCachingOptions + { + EnableLogging = false, + TopicName = "test_topic" + }), providers_1, bus); + + hybridCaching_2 = new HybridCachingProvider(new OptionsWrapper(new HybridCachingOptions + { + EnableLogging = false, + TopicName = "test_topic" + }), providers_2, bus); + } + + [Fact] + public void Set_And_Get_Should_Succeed() + { + var cacheKey = $"{_namespace}_{Guid.NewGuid().ToString()}"; + + hybridCaching_1.Set(cacheKey, "val", TimeSpan.FromSeconds(30)); + + var res = hybridCaching_1.Get(cacheKey); + + Assert.Equal("val", res.Value); + } + + + [Fact] + public async Task SetAsync_And_ExistsAsync_Should_Succeed() + { + var cacheKey = $"{_namespace}_{Guid.NewGuid().ToString()}"; + + await hybridCaching_1.SetAsync(cacheKey, "val", TimeSpan.FromSeconds(30)); + + var res = await hybridCaching_1.ExistsAsync(cacheKey); + + Assert.True(res); + } + + [Fact] + public void Set_And_Remove_Should_Succeed() + { + var cacheKey = $"{_namespace}_{Guid.NewGuid().ToString()}"; + + hybridCaching_1.Set(cacheKey, "val", TimeSpan.FromSeconds(30)); + + hybridCaching_1.Remove(cacheKey); + + var res = hybridCaching_1.Exists(cacheKey); + + Assert.True(res); + } + + [Fact] + public async Task SetAsync_And_RemoveAsync_Should_Succeed() + { + var cacheKey = $"{_namespace}_{Guid.NewGuid().ToString()}"; + + await hybridCaching_1.SetAsync(cacheKey, "val", TimeSpan.FromSeconds(30)); + + await hybridCaching_1.RemoveAsync(cacheKey); + + var res = await hybridCaching_1.ExistsAsync(cacheKey); + + Assert.True(res); + } + + [Fact(Skip = "Delay")] + public void Second_Client_Set_Same_Key_Should_Get_New_Value() + { + var cacheKey = $"{_namespace}_{Guid.NewGuid().ToString()}"; + + hybridCaching_1.Set(cacheKey, "val", TimeSpan.FromSeconds(30)); + + hybridCaching_2.Set(cacheKey, "value", TimeSpan.FromSeconds(30)); + + //System.Threading.Thread.Sleep(5000); + + var res = hybridCaching_1.Get(cacheKey); + + Assert.Equal("value", res.Value); + } + } +} diff --git a/test/EasyCaching.UnitTests/EasyCaching.UnitTests.csproj b/test/EasyCaching.UnitTests/EasyCaching.UnitTests.csproj index d9df9e39..0858e4d6 100644 --- a/test/EasyCaching.UnitTests/EasyCaching.UnitTests.csproj +++ b/test/EasyCaching.UnitTests/EasyCaching.UnitTests.csproj @@ -30,6 +30,8 @@ + + From aa08db3b09cdfad7edef1f63ae1a92e08d5886a3 Mon Sep 17 00:00:00 2001 From: catcherwong Date: Thu, 7 Feb 2019 12:56:58 +0800 Subject: [PATCH 15/20] :bug: Fixed condition of handling message --- src/EasyCaching.HybridCache/HybridCachingProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EasyCaching.HybridCache/HybridCachingProvider.cs b/src/EasyCaching.HybridCache/HybridCachingProvider.cs index 5fdfd718..62ea2b7e 100644 --- a/src/EasyCaching.HybridCache/HybridCachingProvider.cs +++ b/src/EasyCaching.HybridCache/HybridCachingProvider.cs @@ -86,7 +86,7 @@ IOptions optionsAccs private void OnMessage(EasyCachingMessage message) { // each clients will recive the message, current client should ignore. - if (string.IsNullOrWhiteSpace(message.Id) && message.Id.Equals(_cacheId, StringComparison.OrdinalIgnoreCase)) + if (!string.IsNullOrWhiteSpace(message.Id) && message.Id.Equals(_cacheId, StringComparison.OrdinalIgnoreCase)) return; foreach (var item in message.CacheKeys) From 06e10c97667e47e595224ebf1ffa0156a918a1c8 Mon Sep 17 00:00:00 2001 From: catcherwong Date: Thu, 7 Feb 2019 13:05:49 +0800 Subject: [PATCH 16/20] :bug: Fixed Hybrid Tests. --- test/EasyCaching.UnitTests/CachingTests/HybridCachingTest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/EasyCaching.UnitTests/CachingTests/HybridCachingTest.cs b/test/EasyCaching.UnitTests/CachingTests/HybridCachingTest.cs index 1466da13..e948f58c 100644 --- a/test/EasyCaching.UnitTests/CachingTests/HybridCachingTest.cs +++ b/test/EasyCaching.UnitTests/CachingTests/HybridCachingTest.cs @@ -108,7 +108,7 @@ public void Set_And_Remove_Should_Succeed() var res = hybridCaching_1.Exists(cacheKey); - Assert.True(res); + Assert.False(res); } [Fact] @@ -122,7 +122,7 @@ public async Task SetAsync_And_RemoveAsync_Should_Succeed() var res = await hybridCaching_1.ExistsAsync(cacheKey); - Assert.True(res); + Assert.False(res); } [Fact(Skip = "Delay")] From 043a779070b3b86af8ce51cd2830f46d4c0f38a1 Mon Sep 17 00:00:00 2001 From: catcherwong Date: Fri, 8 Feb 2019 13:54:23 +0800 Subject: [PATCH 17/20] :boom: Update Version, Description, PackageTags --- build/releasenotes.props | 31 ++++++++++--------- build/version.props | 29 ++++++++--------- .../DefaultRabbitMQBus.cs | 5 ++- .../EasyCaching.Bus.RabbitMQ.csproj | 27 +++++++--------- .../EasyCaching.Bus.Redis.csproj | 8 ++--- .../EasyCaching.CSRedis.csproj | 4 +-- src/EasyCaching.Core/EasyCaching.Core.csproj | 2 +- .../EasyCaching.HybridCache.csproj | 4 +-- .../EasyCaching.InMemory.csproj | 6 ++-- .../EasyCaching.Interceptor.AspectCore.csproj | 6 ++-- .../EasyCaching.Interceptor.Castle.csproj | 4 +-- .../EasyCaching.Memcached.csproj | 6 ++-- .../EasyCaching.Redis.csproj | 6 ++-- .../EasyCaching.ResponseCaching.csproj | 2 +- .../EasyCaching.SQLite.csproj | 6 ++-- .../EasyCaching.Serialization.Json.csproj | 4 +-- ...syCaching.Serialization.MessagePack.csproj | 4 +-- .../EasyCaching.Serialization.Protobuf.csproj | 4 +-- 18 files changed, 79 insertions(+), 79 deletions(-) diff --git a/build/releasenotes.props b/build/releasenotes.props index c892258f..c795beb3 100644 --- a/build/releasenotes.props +++ b/build/releasenotes.props @@ -1,47 +1,50 @@ - 1. Add IRedisCachingProvider. + 1. EasyCaching Bus + 2. HybridCaching - 1. Improve Get cached value. + 1. Adjust reference namespace. - 1. Add Impl of IRedisCachingProvider. + 1. Adjust reference namespace. - 1. Improve Configuration. + 1. Adjust reference namespace. - 1. Update Options. - 2. Improve Get cached value. + 1. Adjust reference namespace. - 1. Improve Configuration. + 1. Refactor. - 1. Fixed bug of IConvertible. + 1. Adjust reference namespace. - 1. Remove Dependency of IEasyCaching. + 1. Adjust reference namespace. - 1. Support .NET Core 2.1 + 1. Adjust reference namespace. - 1. Improve Configuration. + 1. Adjust reference namespace. - 1. Improve Configuration. + 1. Adjust reference namespace. - 1. Improve Configuration. + 1. Adjust reference namespace. - 1. Init. + 1. Adjust reference namespace. 1. Init. + + 1. Init. + diff --git a/build/version.props b/build/version.props index 2849f92f..83d48727 100644 --- a/build/version.props +++ b/build/version.props @@ -1,18 +1,19 @@ - 0.4.6 - 0.4.5.1 - 0.4.6 - 0.4.5 - 0.4.6 - 0.4.5 - 0.3.3 - 0.3.2 - 0.3.0 - 0.3.5 - 0.3.5 - 0.3.5 - 0.1.0 - 0.1.0 + 0.5.0 + 0.5.0 + 0.5.0 + 0.5.0 + 0.5.0 + 0.5.0 + 0.5.0 + 0.5.0 + 0.5.0 + 0.5.0 + 0.5.0 + 0.5.0 + 0.5.0 + 0.5.0 + 0.5.0-alpha diff --git a/src/EasyCaching.Bus.RabbitMQ/DefaultRabbitMQBus.cs b/src/EasyCaching.Bus.RabbitMQ/DefaultRabbitMQBus.cs index 1b44be6c..d14d2d34 100644 --- a/src/EasyCaching.Bus.RabbitMQ/DefaultRabbitMQBus.cs +++ b/src/EasyCaching.Bus.RabbitMQ/DefaultRabbitMQBus.cs @@ -42,10 +42,9 @@ public class DefaultRabbitMQBus : IEasyCachingBus /// /// Initializes a new instance of the class. /// - /// Connection channel pool. - /// Rabbit MQO ptions. + /// Object policy. + /// RabbitMQ Options. /// Serializer. - /// Local caching provider. public DefaultRabbitMQBus( IPooledObjectPolicy _objectPolicy ,RabbitMQBusOptions rabbitMQOptions diff --git a/src/EasyCaching.Bus.RabbitMQ/EasyCaching.Bus.RabbitMQ.csproj b/src/EasyCaching.Bus.RabbitMQ/EasyCaching.Bus.RabbitMQ.csproj index 9997a183..0871cb3b 100644 --- a/src/EasyCaching.Bus.RabbitMQ/EasyCaching.Bus.RabbitMQ.csproj +++ b/src/EasyCaching.Bus.RabbitMQ/EasyCaching.Bus.RabbitMQ.csproj @@ -4,17 +4,19 @@ netstandard2.0 Catcher Wong Catcher Wong - 0.1.0 - - EasyCaching is a open source caching library that contains basic opreations of caching. + $(EasyCachingRabbitBusPackageVersion) + + A simple caching bus(message bus) based on RabbitMQ. - Caching,Cache,Distributed Cache,Memory Cache,Interceptor,Synchronization - https://github.com/catcherwong/EasyCaching - https://github.com/catcherwong/EasyCaching/blob/master/LICENSE - https://github.com/catcherwong/EasyCaching - https://github.com/catcherwong/EasyCaching - https://raw.githubusercontent.com/catcherwong/EasyCaching/master/media/easycaching-icon.png - + Bus,Hybrid,RabbitMQ,Caching,Cache + https://github.com/dotnetcore/EasyCaching + https://github.com/dotnetcore/EasyCaching/blob/master/LICENSE + https://github.com/dotnetcore/EasyCaching + https://github.com/dotnetcore/EasyCaching + https://raw.githubusercontent.com/dotnetcore/EasyCaching/master/media/easycaching-icon.png + + $(EasyCachingRabbitBusPackageNotes) + @@ -25,11 +27,6 @@ - - - - - diff --git a/src/EasyCaching.Bus.Redis/EasyCaching.Bus.Redis.csproj b/src/EasyCaching.Bus.Redis/EasyCaching.Bus.Redis.csproj index 861a4399..5ef428bf 100644 --- a/src/EasyCaching.Bus.Redis/EasyCaching.Bus.Redis.csproj +++ b/src/EasyCaching.Bus.Redis/EasyCaching.Bus.Redis.csproj @@ -5,17 +5,17 @@ Catcher Wong Catcher Wong $(EasyCachingRedisBusPackageVersion) - - EasyCaching is a open source caching library that contains basic opreations of caching. + + A simple caching bus(message bus) based on StackExchange.Redis. - Bus,Hybrid Caching,Redis,Synchronization + Bus,Hybrid,Redis,Caching,Cache https://github.com/dotnetcore/EasyCaching https://github.com/dotnetcore/EasyCaching/blob/master/LICENSE https://github.com/dotnetcore/EasyCaching https://github.com/dotnetcore/EasyCaching https://raw.githubusercontent.com/dotnetcore/EasyCaching/master/media/easycaching-icon.png - $(EasyCachingRedisBusPackageVersion) + $(EasyCachingRedisBusPackageNotes) diff --git a/src/EasyCaching.CSRedis/EasyCaching.CSRedis.csproj b/src/EasyCaching.CSRedis/EasyCaching.CSRedis.csproj index 750db734..ab111bce 100644 --- a/src/EasyCaching.CSRedis/EasyCaching.CSRedis.csproj +++ b/src/EasyCaching.CSRedis/EasyCaching.CSRedis.csproj @@ -7,9 +7,9 @@ Catcher Wong $(EasyCachingCSRedisPackageVersion) - EasyCaching.CSRedis based on EasyCaching.Core and CSRedisCore + A simple distributed caching provider based on csredis. - Caching,Cache,Distributed,Redis + Redis,DistributedCache,Caching,Cache https://github.com/dotnetcore/EasyCaching https://github.com/dotnetcore/EasyCaching/blob/master/LICENSE https://github.com/dotnetcore/EasyCaching diff --git a/src/EasyCaching.Core/EasyCaching.Core.csproj b/src/EasyCaching.Core/EasyCaching.Core.csproj index 72b1a803..b10c256d 100644 --- a/src/EasyCaching.Core/EasyCaching.Core.csproj +++ b/src/EasyCaching.Core/EasyCaching.Core.csproj @@ -9,7 +9,7 @@ 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,Synchronization,Hybrid + Caching,Cache,Distributed,Memory,Interceptor,Hybrid,ResponseCaching https://github.com/dotnetcore/EasyCaching https://github.com/dotnetcore/EasyCaching/blob/master/LICENSE https://github.com/dotnetcore/EasyCaching diff --git a/src/EasyCaching.HybridCache/EasyCaching.HybridCache.csproj b/src/EasyCaching.HybridCache/EasyCaching.HybridCache.csproj index 9331ebc7..547d5ec5 100644 --- a/src/EasyCaching.HybridCache/EasyCaching.HybridCache.csproj +++ b/src/EasyCaching.HybridCache/EasyCaching.HybridCache.csproj @@ -7,9 +7,9 @@ Catcher Wong $(EasyCachingHybridPackageVersion) - EasyCaching.HybridCache combines local caching and distributed caching. + A simple hybrid caching provider combines local caching and distributed caching. - Caching,Cache,Synchronization,Hybrid + Hybrid,Synchronization,LocalCache,DistributedCache,Caching https://github.com/dotnetcore/EasyCaching https://github.com/dotnetcore/EasyCaching/blob/master/LICENSE https://github.com/dotnetcore/EasyCaching diff --git a/src/EasyCaching.InMemory/EasyCaching.InMemory.csproj b/src/EasyCaching.InMemory/EasyCaching.InMemory.csproj index 97157293..68b81006 100644 --- a/src/EasyCaching.InMemory/EasyCaching.InMemory.csproj +++ b/src/EasyCaching.InMemory/EasyCaching.InMemory.csproj @@ -6,10 +6,10 @@ Catcher Wong Catcher Wong $(EasyCachingInMemoryPackageVersion) - - In-memory cache based on EasyCaching.Core and Microsoft.Extensions.Caching.Memory + + A simple in-memory caching provider. - Caching,Cache,In-Memory + In-Memory,LocalCache,Caching,Cache https://github.com/dotnetcore/EasyCaching https://github.com/dotnetcore/EasyCaching/blob/master/LICENSE https://github.com/dotnetcore/EasyCaching diff --git a/src/EasyCaching.Interceptor.AspectCore/EasyCaching.Interceptor.AspectCore.csproj b/src/EasyCaching.Interceptor.AspectCore/EasyCaching.Interceptor.AspectCore.csproj index e27e6853..67c67eba 100644 --- a/src/EasyCaching.Interceptor.AspectCore/EasyCaching.Interceptor.AspectCore.csproj +++ b/src/EasyCaching.Interceptor.AspectCore/EasyCaching.Interceptor.AspectCore.csproj @@ -6,10 +6,10 @@ Catcher Wong Catcher Wong $(EasyCachingAspectCorePackageVersion) - - Caching Interceptor based on EasyCaching.Core and AspectCore + + A simple caching AOP extension library based on AspectCore - Caching,Cache,Distributed,Memory,Interceptor,Synchronization + Interceptor,AspectCore,AOP,Caching,Cache https://github.com/dotnetcore/EasyCaching https://github.com/dotnetcore/EasyCaching/blob/master/LICENSE https://github.com/dotnetcore/EasyCaching diff --git a/src/EasyCaching.Interceptor.Castle/EasyCaching.Interceptor.Castle.csproj b/src/EasyCaching.Interceptor.Castle/EasyCaching.Interceptor.Castle.csproj index e1f068e2..3b1b0d85 100644 --- a/src/EasyCaching.Interceptor.Castle/EasyCaching.Interceptor.Castle.csproj +++ b/src/EasyCaching.Interceptor.Castle/EasyCaching.Interceptor.Castle.csproj @@ -7,9 +7,9 @@ Catcher Wong $(EasyCachingCastlePackageVersion) - Caching Interceptor based on EasyCaching.Core and Castle + A simple caching AOP extension library based on Castle - Caching,Cache,Distributed,Memory,Interceptor,Synchronization + Interceptor,Castle,AOP,Caching,Cache https://github.com/dotnetcore/EasyCaching https://github.com/dotnetcore/EasyCaching/blob/master/LICENSE https://github.com/dotnetcore/EasyCaching diff --git a/src/EasyCaching.Memcached/EasyCaching.Memcached.csproj b/src/EasyCaching.Memcached/EasyCaching.Memcached.csproj index c791faa0..7eda0433 100644 --- a/src/EasyCaching.Memcached/EasyCaching.Memcached.csproj +++ b/src/EasyCaching.Memcached/EasyCaching.Memcached.csproj @@ -6,10 +6,10 @@ Catcher Wong Catcher Wong $(EasyCachingMemcachedPackageVersion) - - EasyCaching.Memcached based on EasyCaching.Core and EnyimMemcachedCore + + A simple distributed caching provider based on EnyimMemcachedCore. - Caching,Cache,Distributed,Memcached + Memcached,DistributedCache,Caching,Cache https://github.com/dotnetcore/EasyCaching https://github.com/dotnetcore/EasyCaching/blob/master/LICENSE https://github.com/dotnetcore/EasyCaching diff --git a/src/EasyCaching.Redis/EasyCaching.Redis.csproj b/src/EasyCaching.Redis/EasyCaching.Redis.csproj index bdebd0e5..ac4d52b6 100644 --- a/src/EasyCaching.Redis/EasyCaching.Redis.csproj +++ b/src/EasyCaching.Redis/EasyCaching.Redis.csproj @@ -6,10 +6,10 @@ Catcher Wong Catcher Wong $(EasyCachingRedisPackageVersion) - - EasyCaching.Redis based on EasyCaching.Core and StackExchange.Redis + + A simple distributed caching provider based on StackExchange.Redis. - Caching,Cache,Distributed,Redis + Redis,DistributedCache,Caching,Cache https://github.com/dotnetcore/EasyCaching https://github.com/dotnetcore/EasyCaching/blob/master/LICENSE https://github.com/dotnetcore/EasyCaching diff --git a/src/EasyCaching.ResponseCaching/EasyCaching.ResponseCaching.csproj b/src/EasyCaching.ResponseCaching/EasyCaching.ResponseCaching.csproj index e711c24b..2e51070f 100644 --- a/src/EasyCaching.ResponseCaching/EasyCaching.ResponseCaching.csproj +++ b/src/EasyCaching.ResponseCaching/EasyCaching.ResponseCaching.csproj @@ -7,7 +7,7 @@ Catcher Wong $(EasyCachingResponseCachingPackageVersion) - EasyCaching.ResponseCaching based on EasyCaching.Core and Microsoft.AspNetCore.ResponseCaching + EasyCaching.ResponseCaching is the extension of ResponseCaching Caching,Cache,ResponseCaching https://github.com/dotnetcore/EasyCaching diff --git a/src/EasyCaching.SQLite/EasyCaching.SQLite.csproj b/src/EasyCaching.SQLite/EasyCaching.SQLite.csproj index 55eba3ee..18a87dbf 100644 --- a/src/EasyCaching.SQLite/EasyCaching.SQLite.csproj +++ b/src/EasyCaching.SQLite/EasyCaching.SQLite.csproj @@ -6,10 +6,10 @@ Catcher Wong Catcher Wong $(EasyCachingSQLitePackageVersion) - - EasyCaching.SQLite based on EasyCaching.Core and Microsoft.Data.SQLite + + A simple local caching provider based on Microsoft.Data.SQLite - Caching,Cache,SQLite + SQLite,LocalCache,Caching,Cache,InMemory,Persisted https://github.com/dotnetcore/EasyCaching https://github.com/dotnetcore/EasyCaching/blob/master/LICENSE https://github.com/dotnetcore/EasyCaching diff --git a/src/EasyCaching.Serialization.Json/EasyCaching.Serialization.Json.csproj b/src/EasyCaching.Serialization.Json/EasyCaching.Serialization.Json.csproj index d8716d53..dc35e654 100644 --- a/src/EasyCaching.Serialization.Json/EasyCaching.Serialization.Json.csproj +++ b/src/EasyCaching.Serialization.Json/EasyCaching.Serialization.Json.csproj @@ -6,8 +6,8 @@ Catcher Wong Catcher Wong $(EasyCachingJsonPackageVersion) - - EasyCaching.Serialization.Json based on EasyCaching.Core and Newtonsoft.Json. + + A serialize library based on Newtonsoft.Json Caching,Serialization,Json https://github.com/dotnetcore/EasyCaching diff --git a/src/EasyCaching.Serialization.MessagePack/EasyCaching.Serialization.MessagePack.csproj b/src/EasyCaching.Serialization.MessagePack/EasyCaching.Serialization.MessagePack.csproj index 80c33699..145c1237 100644 --- a/src/EasyCaching.Serialization.MessagePack/EasyCaching.Serialization.MessagePack.csproj +++ b/src/EasyCaching.Serialization.MessagePack/EasyCaching.Serialization.MessagePack.csproj @@ -6,8 +6,8 @@ Catcher Wong Catcher Wong $(EasyCachingMessagePackPackageVersion) - - EasyCaching.Serialization.MessagePack based on EasyCaching.Core and MessagePack. + + A serialize library based on MessagePack Caching,Serialization,MessagePack https://github.com/dotnetcore/EasyCaching diff --git a/src/EasyCaching.Serialization.Protobuf/EasyCaching.Serialization.Protobuf.csproj b/src/EasyCaching.Serialization.Protobuf/EasyCaching.Serialization.Protobuf.csproj index 5d15b0b2..7e66d6b8 100644 --- a/src/EasyCaching.Serialization.Protobuf/EasyCaching.Serialization.Protobuf.csproj +++ b/src/EasyCaching.Serialization.Protobuf/EasyCaching.Serialization.Protobuf.csproj @@ -6,8 +6,8 @@ Catcher Wong Catcher Wong $(EasyCachingProtobufPackageVersion) - - EasyCaching.Serialization.Protobuf based on EasyCaching.Core and protobuf-net. + + A serialize library based on protobuf-net Caching,Serialization,Protobuf https://github.com/dotnetcore/EasyCaching From ffaa8022930281d3aa29c6a84ce34b22607c2160 Mon Sep 17 00:00:00 2001 From: catcherwong Date: Sat, 9 Feb 2019 12:31:06 +0800 Subject: [PATCH 18/20] :ok_hand: RabbitMQ Bus --- .../EasyCachingOptionsExtensions.cs | 1 + .../Configurations/RabbitMQBusOptions.cs | 6 +++++ .../DefaultRabbitMQBus.cs | 24 +++++++++++++++---- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/EasyCaching.Bus.RabbitMQ/Configurations/EasyCachingOptionsExtensions.cs b/src/EasyCaching.Bus.RabbitMQ/Configurations/EasyCachingOptionsExtensions.cs index 5ff72af2..a58a6829 100644 --- a/src/EasyCaching.Bus.RabbitMQ/Configurations/EasyCachingOptionsExtensions.cs +++ b/src/EasyCaching.Bus.RabbitMQ/Configurations/EasyCachingOptionsExtensions.cs @@ -52,6 +52,7 @@ void configure(RabbitMQBusOptions x) x.TopicExchangeName = busOptions.TopicExchangeName; x.UserName = busOptions.UserName; x.VirtualHost = busOptions.VirtualHost; + x.QueueName = busOptions.QueueName; } options.RegisterExtension(new RabbitMQBusOptionsExtension(configure)); diff --git a/src/EasyCaching.Bus.RabbitMQ/Configurations/RabbitMQBusOptions.cs b/src/EasyCaching.Bus.RabbitMQ/Configurations/RabbitMQBusOptions.cs index 4a18f89a..9857d861 100644 --- a/src/EasyCaching.Bus.RabbitMQ/Configurations/RabbitMQBusOptions.cs +++ b/src/EasyCaching.Bus.RabbitMQ/Configurations/RabbitMQBusOptions.cs @@ -12,5 +12,11 @@ public class RabbitMQBusOptions : BaseRabbitMQOptions /// /// The route key. public string RouteKey { get; set; } = "easycaching.subscriber.*"; + + /// + /// Gets or sets the name of the queue. + /// + /// The name of the queue. + public string QueueName { get; set; } = ""; } } diff --git a/src/EasyCaching.Bus.RabbitMQ/DefaultRabbitMQBus.cs b/src/EasyCaching.Bus.RabbitMQ/DefaultRabbitMQBus.cs index d14d2d34..5a35a404 100644 --- a/src/EasyCaching.Bus.RabbitMQ/DefaultRabbitMQBus.cs +++ b/src/EasyCaching.Bus.RabbitMQ/DefaultRabbitMQBus.cs @@ -39,6 +39,11 @@ public class DefaultRabbitMQBus : IEasyCachingBus /// private readonly IEasyCachingSerializer _serializer; + /// + /// The identifier. + /// + private readonly string _Id; + /// /// Initializes a new instance of the class. /// @@ -68,6 +73,8 @@ IPooledObjectPolicy _objectPolicy _subConnection = factory.CreateConnection(); _pubConnectionPool = new DefaultObjectPool(_objectPolicy); + + _Id = Guid.NewGuid().ToString("N"); } /// @@ -134,21 +141,28 @@ public void Publish(string topic, EasyCachingMessage message) public void Subscribe(string topic, Action action) { _handler = action; + var queueName = string.Empty; + if(string.IsNullOrWhiteSpace(_options.QueueName)) + { + queueName = $"easycaching.subscriber.{_Id}"; + } + else + { + queueName = _options.QueueName; + } Task.Factory.StartNew(() => { var model = _subConnection.CreateModel(); model.ExchangeDeclare(_options.TopicExchangeName, ExchangeType.Topic, true, false, null); - - var queue = model.QueueDeclare($"easycaching.subscriber.{Guid.NewGuid().ToString("N")}", false, false, true, null); - + model.QueueDeclare(queueName, false, false, true, null); // bind the queue with the exchange. - model.QueueBind(_options.TopicExchangeName, queue.QueueName, _options.RouteKey); + model.QueueBind(_options.TopicExchangeName, queueName, _options.RouteKey); var consumer = new EventingBasicConsumer(model); consumer.Received += OnMessage; consumer.Shutdown += OnConsumerShutdown; - model.BasicConsume(queue.QueueName, true, consumer); + model.BasicConsume(queueName, true, consumer); }, TaskCreationOptions.LongRunning); } From a9c24f2fd77ab0d787d3d92485305fedf187f8e7 Mon Sep 17 00:00:00 2001 From: catcherwong Date: Sat, 9 Feb 2019 12:34:59 +0800 Subject: [PATCH 19/20] :bento: Add hybrid_details.png --- media/hybrid_details.png | Bin 0 -> 51197 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 media/hybrid_details.png diff --git a/media/hybrid_details.png b/media/hybrid_details.png new file mode 100644 index 0000000000000000000000000000000000000000..78a6505b27e4a4d2a1c4bf47aaadc19f4d9d04c9 GIT binary patch literal 51197 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 X%ap Date: Sun, 10 Feb 2019 19:53:25 +0800 Subject: [PATCH 20/20] :ok_hand: Default RabbitMQ Options. --- .../Configurations/RabbitMQBusOptions.cs | 2 +- src/EasyCaching.Bus.RabbitMQ/DefaultRabbitMQBus.cs | 6 +++--- src/EasyCaching.Core/Configurations/BaseRabbitMQOptions.cs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/EasyCaching.Bus.RabbitMQ/Configurations/RabbitMQBusOptions.cs b/src/EasyCaching.Bus.RabbitMQ/Configurations/RabbitMQBusOptions.cs index 9857d861..bf0da3d2 100644 --- a/src/EasyCaching.Bus.RabbitMQ/Configurations/RabbitMQBusOptions.cs +++ b/src/EasyCaching.Bus.RabbitMQ/Configurations/RabbitMQBusOptions.cs @@ -11,7 +11,7 @@ public class RabbitMQBusOptions : BaseRabbitMQOptions /// Gets or sets the route key. /// /// The route key. - public string RouteKey { get; set; } = "easycaching.subscriber.*"; + public string RouteKey { get; set; } = "rmq.queue.undurable.easycaching.subscriber.*"; /// /// Gets or sets the name of the queue. diff --git a/src/EasyCaching.Bus.RabbitMQ/DefaultRabbitMQBus.cs b/src/EasyCaching.Bus.RabbitMQ/DefaultRabbitMQBus.cs index 5a35a404..a8c178ae 100644 --- a/src/EasyCaching.Bus.RabbitMQ/DefaultRabbitMQBus.cs +++ b/src/EasyCaching.Bus.RabbitMQ/DefaultRabbitMQBus.cs @@ -42,7 +42,7 @@ public class DefaultRabbitMQBus : IEasyCachingBus /// /// The identifier. /// - private readonly string _Id; + private readonly string _busId; /// /// Initializes a new instance of the class. @@ -74,7 +74,7 @@ IPooledObjectPolicy _objectPolicy _pubConnectionPool = new DefaultObjectPool(_objectPolicy); - _Id = Guid.NewGuid().ToString("N"); + _busId = Guid.NewGuid().ToString("N"); } /// @@ -144,7 +144,7 @@ public void Subscribe(string topic, Action action) var queueName = string.Empty; if(string.IsNullOrWhiteSpace(_options.QueueName)) { - queueName = $"easycaching.subscriber.{_Id}"; + queueName = $"rmq.queue.undurable.easycaching.subscriber.{_busId}"; } else { diff --git a/src/EasyCaching.Core/Configurations/BaseRabbitMQOptions.cs b/src/EasyCaching.Core/Configurations/BaseRabbitMQOptions.cs index e3dee99f..aae147f1 100644 --- a/src/EasyCaching.Core/Configurations/BaseRabbitMQOptions.cs +++ b/src/EasyCaching.Core/Configurations/BaseRabbitMQOptions.cs @@ -25,7 +25,7 @@ public class BaseRabbitMQOptions /// /// Topic exchange name when declare a topic exchange. /// - public string TopicExchangeName { get; set; } = "easycaching.exchange"; + public string TopicExchangeName { get; set; } = "rmq.exchange.topic.easycaching"; /// /// Timeout setting for connection attempts (in milliseconds).