diff --git a/AopCaching/AopCaching.csproj b/AopCaching/AopCaching.csproj index 910872c..022ac34 100644 --- a/AopCaching/AopCaching.csproj +++ b/AopCaching/AopCaching.csproj @@ -21,6 +21,7 @@ + diff --git a/AopCaching/CacheAttribute.cs b/AopCaching/CacheAttribute.cs index 985c298..1360379 100644 --- a/AopCaching/CacheAttribute.cs +++ b/AopCaching/CacheAttribute.cs @@ -3,6 +3,7 @@ using PostSharp.Serialization; using PubComp.Caching.Core; using PubComp.Caching.Core.Attributes; +using PubComp.Caching.RedisCaching; using System; using System.Collections.Generic; using System.Linq; @@ -22,6 +23,7 @@ public class CacheAttribute : MethodInterceptionAspect private int[] indexesNotToCache; private bool isClassGeneric; private bool isMethodGeneric; + private bool _isRedisActive = true; public CacheAttribute() { @@ -66,10 +68,28 @@ public sealed override void OnInvoke(MethodInterceptionArgs args) { if (this.cache == null) { - this.cache = CacheManager.GetCache(this.cacheName); + this.cache = CacheManager.GetCache(cacheName); if (this.cache == null) { - LogManager.GetCurrentClassLogger().Warn($"AOP cache [{this.cacheName}] is not initialized, define NoCache if needed!"); + LogManager.GetCurrentClassLogger().Warn("AOP cache [" + cacheName + "] is not initialized, define NoCache if needed!"); + } + } + else if (_isRedisActive && cacheName.Contains("BackUp")) + { + cacheName = cacheName.Replace("BackUp", ""); + this.cache = CacheManager.GetCache(cacheName); + } + + if (this.cache is RedisCache) + { + _isRedisActive = (this.cache as RedisCache).IsActive; + if (!(this.cache as RedisCache).IsRedisConnectionStateHandlerRegistered) + (this.cache as RedisCache).OnRedisConnectionStateChanged += CacheAttribute_OnRedisConnectionStateChanged; + + if (!_isRedisActive) + { + cacheName = string.Format("{0}{1}", cacheName, "BackUp"); + this.cache = CacheManager.GetCache(cacheName); } } @@ -91,10 +111,28 @@ public sealed override async Task OnInvokeAsync(MethodInterceptionArgs args) { if (this.cache == null) { - this.cache = CacheManager.GetCache(this.cacheName); + this.cache = CacheManager.GetCache(cacheName); if (this.cache == null) { - LogManager.GetCurrentClassLogger().Warn($"AOP cache [{this.cacheName}] is not initialized, define NoCache if needed!"); + LogManager.GetCurrentClassLogger().Warn("AOP cache [" + cacheName + "] is not initialized, define NoCache if needed!"); + } + } + else if (_isRedisActive && cacheName.Contains("BackUp")) + { + cacheName = cacheName.Replace("BackUp", ""); + this.cache = CacheManager.GetCache(cacheName); + } + + if (this.cache is RedisCache) + { + _isRedisActive = (this.cache as RedisCache).IsActive; + if (!(this.cache as RedisCache).IsRedisConnectionStateHandlerRegistered) + (this.cache as RedisCache).OnRedisConnectionStateChanged += CacheAttribute_OnRedisConnectionStateChanged; + + if (!_isRedisActive) + { + cacheName = string.Format("{0}{1}", cacheName, "BackUp"); + this.cache = CacheManager.GetCache(cacheName); } } @@ -117,6 +155,14 @@ public sealed override async Task OnInvokeAsync(MethodInterceptionArgs args) args.ReturnValue = SafeCasting.CastTo(returnType, result); } + private void CacheAttribute_OnRedisConnectionStateChanged(object sender, bool connectionRestored) + { + if (connectionRestored) + { + _isRedisActive = true; + } + } + private string GetCacheKey(MethodInterceptionArgs args) { var classNameNonGeneric = !this.isClassGeneric diff --git a/RedisCaching/CacheContext.cs b/RedisCaching/CacheContext.cs index 3257a36..f15d565 100644 --- a/RedisCaching/CacheContext.cs +++ b/RedisCaching/CacheContext.cs @@ -10,6 +10,7 @@ public class CacheContext : IDisposable { private readonly RedisClient client; private readonly IRedisConverter convert; + public event EventHandler OnRedisConnectionStateChanged; public bool IsActive { get; private set; } @@ -29,7 +30,12 @@ public CacheContext(String connectionName, String converterType) private void RegisterToRedisConnectionStateChangeEvent() { - this.client.OnRedisConnectionStateChanged += (sender, args) => this.IsActive = args.IsAvailable; + this.client.OnRedisConnectionStateChanged += (sender, args) => + { + this.IsActive = args.IsAvailable; + this.OnRedisConnectionStateChanged(sender, IsActive); + }; + this.IsActive = this.client.IsConnected; } diff --git a/RedisCaching/RedisCache.cs b/RedisCaching/RedisCache.cs index b254254..c69fd07 100644 --- a/RedisCaching/RedisCache.cs +++ b/RedisCaching/RedisCache.cs @@ -21,10 +21,19 @@ public class RedisCache : ICacheV2 private readonly NLog.ILogger log; private readonly RedisCachePolicy Policy; + public event EventHandler OnRedisConnectionStateChanged; public string Name { get { return this.name; } } public bool IsActive => InnerCache.IsActive; + public bool IsRedisConnectionStateHandlerRegistered + { + get + { + return OnRedisConnectionStateChanged != null; + } + } + private CacheContext InnerCache { get { return innerCache; } @@ -106,11 +115,19 @@ public RedisCache(String name, RedisCachePolicy policy) this.innerCache = new CacheContext(policy.ConnectionName, this.converterType); } + this.innerCache.OnRedisConnectionStateChanged += InnerCache_OnRedisConnectionStateChanged; + this.notiferName = policy.SyncProvider; this.synchronizer = CacheSynchronizer.CreateCacheSynchronizer(this, this.notiferName); } + private void InnerCache_OnRedisConnectionStateChanged(object sender, bool e) + { + if (IsRedisConnectionStateHandlerRegistered) + OnRedisConnectionStateChanged(sender, e); + } + private TValue GetOrAdd( CacheContext context, string key, TValue newValue, bool doForceOverride = false) {