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 <IOptionsMonitor <RedisOptions> >(); A.CallTo(() => fakeOption.CurrentValue).Returns(options); var fakeDbProvider = A.Fake <RedisDatabaseProvider>(option => option.WithArgumentsForConstructor(new object[] { fakeOption })); var serializer = new DefaultBinaryFormatterSerializer(); var providers = new List <IEasyCachingProvider> { new DefaultInMemoryCachingProvider(new MemoryCache(new MemoryCacheOptions()), new TestOptionMonitorWrapper <InMemoryOptions>(new InMemoryOptions())), new DefaultRedisCachingProvider(fakeDbProvider, serializer, new TestOptionMonitorWrapper <RedisOptions>(new RedisOptions())) }; _provider = new HybridCachingProvider(providers); _defaultTs = TimeSpan.FromSeconds(30); }
public HybridCachingTest() { RedisCacheOptions options = new RedisCacheOptions() { AllowAdmin = true, //Password = "" }; options.Endpoints.Add(new ServerEndPoint("127.0.0.1", 6379)); var fakeOption = A.Fake <IOptions <RedisCacheOptions> >(); A.CallTo(() => fakeOption.Value).Returns(options); var fakeDbProvider = A.Fake <RedisDatabaseProvider>(option => option.WithArgumentsForConstructor(new object[] { fakeOption })); var serializer = new DefaultBinaryFormatterSerializer(); var serviceAccessor = A.Fake <Func <string, IEasyCachingProvider> >(); A.CallTo(() => serviceAccessor(HybridCachingKeyType.LocalKey)).Returns(new DefaultInMemoryCachingProvider(new MemoryCache(new MemoryCacheOptions()))); A.CallTo(() => serviceAccessor(HybridCachingKeyType.DistributedKey)).Returns(new DefaultRedisCachingProvider(fakeDbProvider, serializer)); _provider = new HybridCachingProvider(serviceAccessor); _defaultTs = TimeSpan.FromSeconds(30); }
public HybridCachingTest() { _namespace = "hybrid"; var options = new HybridCachingOptions { EnableLogging = false, TopicName = "test_topic", LocalCacheProviderName = "m1", DistributedCacheProviderName = "myredis", BusRetryCount = 1, DefaultExpirationForTtlFailed = 60 }; 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.UseHybrid(config => { config.EnableLogging = false; config.TopicName = "test_topic"; config.LocalCacheProviderName = "m1"; config.DistributedCacheProviderName = "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 <IEasyCachingProviderFactory>(); var bus = serviceProvider.GetService <IEasyCachingBus>(); hybridCaching_1 = serviceProvider.GetService <IHybridCachingProvider>(); fakeBus = A.Fake <IEasyCachingBus>(); fakeFactory = A.Fake <IEasyCachingProviderFactory>(); fakeDisProvider = A.Fake <FakeDistributedCachingProvider>(); var myOptions = Options.Create(options); FakeCreatProvider(); fakeHybrid = new HybridCachingProvider("h1", myOptions.Value, fakeFactory, fakeBus); }
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 <IEasyCachingProviderFactory>(); var providers_1 = new List <IEasyCachingProvider> { factory.GetCachingProvider("m1"), factory.GetCachingProvider("myredis") }; var providers_2 = new List <IEasyCachingProvider> { factory.GetCachingProvider("m2"), factory.GetCachingProvider("myredis") }; var bus = serviceProvider.GetService <IEasyCachingBus>(); hybridCaching_1 = new HybridCachingProvider(new OptionsWrapper <HybridCachingOptions>(new HybridCachingOptions { EnableLogging = false, TopicName = "test_topic" }), providers_1, bus); hybridCaching_2 = new HybridCachingProvider(new OptionsWrapper <HybridCachingOptions>(new HybridCachingOptions { EnableLogging = false, TopicName = "test_topic" }), providers_2, bus); }
public void GetSyncWithDataRetriever_DistributedCacheHasValue_SetLocalWithDefaultOrDistributedExpiration(int distributedExpirationMinutes, int setLocalExpirationMinutes) { var cacheKey = GetUniqueCacheKey(); var fakeLocalCache = A.Fake <IInMemoryCaching>(); A.CallTo(() => fakeLocalCache.ProviderName) .Returns("testCache"); A.CallTo(() => fakeLocalCache.Get <string>(cacheKey)) .Returns(CacheValue <string> .NoValue); A.CallTo(() => fakeLocalCache.Add($"{cacheKey}_Lock", A <int> ._, A <TimeSpan> ._)) .Returns(true); var localProvider = new DefaultInMemoryCachingProvider("testCache", new[] { fakeLocalCache }, new InMemoryOptions() { MaxRdSecond = 0 }); var fakeDistributedProvider = A.Fake <IEasyCachingProvider>(); var fakeProvidersFactory = A.Fake <IEasyCachingProviderFactory>(); A.CallTo(() => fakeProvidersFactory.GetCachingProvider(LocalCacheProviderName)).Returns(localProvider); A.CallTo(() => fakeProvidersFactory.GetCachingProvider(DistributedCacheProviderName)).Returns(fakeDistributedProvider); var hybridProvider = new HybridCachingProvider("TestProvider", new HybridCachingOptions() { TopicName = "TestTopicName", LocalCacheProviderName = LocalCacheProviderName, DistributedCacheProviderName = DistributedCacheProviderName }, fakeProvidersFactory); var newExpiration = TimeSpan.FromMinutes(5); var distributeExpiration = TimeSpan.FromMinutes(distributedExpirationMinutes); var dataRetriever = A.Fake <Func <string> >(); A.CallTo(() => dataRetriever.Invoke()).Returns("cachedValue"); A.CallTo(() => fakeDistributedProvider.GetExpiration(cacheKey)).Returns(distributeExpiration); A.CallTo(() => fakeDistributedProvider.Get(cacheKey, A <Func <string> > ._, A <TimeSpan> ._)) .Returns(new CacheValue <string>("cachedValue", true)); var res = hybridProvider.Get(cacheKey, dataRetriever, newExpiration); Assert.NotNull(res); Assert.True(res.HasValue); Assert.Equal("cachedValue", res.Value); A.CallTo(() => fakeDistributedProvider.GetExpiration(cacheKey)).MustHaveHappenedOnceExactly(); A.CallTo(() => fakeLocalCache.Set(cacheKey, A <string> ._, TimeSpan.FromMinutes(setLocalExpirationMinutes))) .MustHaveHappenedOnceExactly(); }
/// <summary> /// Processes the evict async. /// </summary> /// <returns>The evict async.</returns> /// <param name="context">Context.</param> /// <param name="isBefore">If set to <c>true</c> is before.</param> private async Task ProcessEvictAsync(AspectContext context, bool isBefore) { if (GetMethodAttributes(context.ServiceMethod).FirstOrDefault(x => typeof(EasyCachingEvictAttribute).IsAssignableFrom(x.GetType())) is EasyCachingEvictAttribute attribute && attribute.IsBefore == isBefore) { try { if (attribute.IsAll) { // If is all , clear all cached items which cachekey start with the prefix. var cachePrefix = KeyGenerator.GetCacheKeyPrefix(context.ServiceMethod, attribute.CacheKeyPrefix); if (attribute.IsHybridProvider) { await HybridCachingProvider.RemoveByPrefixAsync(cachePrefix); } else { var _cacheProvider = CacheProviderFactory.GetCachingProvider(attribute.CacheProviderName ?? Options.Value.CacheProviderName); await _cacheProvider.RemoveByPrefixAsync(cachePrefix); } } else { // If not all , just remove the cached item by its cachekey. var cacheKey = KeyGenerator.GetCacheKey(context.ServiceMethod, context.Parameters, attribute.CacheKeyPrefix); if (attribute.IsHybridProvider) { await HybridCachingProvider.RemoveAsync(cacheKey); } else { var _cacheProvider = CacheProviderFactory.GetCachingProvider(attribute.CacheProviderName ?? Options.Value.CacheProviderName); await _cacheProvider.RemoveAsync(cacheKey); } } } catch (Exception ex) { if (!attribute.IsHighAvailability) { throw; } else { Logger?.LogError(new EventId(), ex, $"Cache provider remove error."); } } } }
private (HybridCachingProvider hybridProvider, IEasyCachingProvider fakeLocalCachingProvider, IEasyCachingProvider fakeDistributedProvider) CreateFakeHybridProvider() { var fakeLocalProvider = A.Fake <IEasyCachingProvider>(); var fakeDistributedProvider = A.Fake <IEasyCachingProvider>(); var fakeProvidersFactory = A.Fake <IEasyCachingProviderFactory>(); A.CallTo(() => fakeProvidersFactory.GetCachingProvider(LocalCacheProviderName)).Returns(fakeLocalProvider); A.CallTo(() => fakeProvidersFactory.GetCachingProvider(DistributedCacheProviderName)).Returns(fakeDistributedProvider); var hybridProvider = new HybridCachingProvider("TestProvider", new HybridCachingOptions() { TopicName = "TestTopicName", LocalCacheProviderName = LocalCacheProviderName, DistributedCacheProviderName = DistributedCacheProviderName }, fakeProvidersFactory); return(hybridProvider, fakeLocalProvider, fakeDistributedProvider); }
/// <summary> /// Processes the put async. /// </summary> /// <returns>The put async.</returns> /// <param name="context">Context.</param> private async Task ProcessPutAsync(AspectContext context) { if (GetMethodAttributes(context.ServiceMethod).FirstOrDefault(x => typeof(EasyCachingPutAttribute).IsAssignableFrom(x.GetType())) is EasyCachingPutAttribute attribute && context.ReturnValue != null) { var cacheKey = KeyGenerator.GetCacheKey(context.ServiceMethod, context.Parameters, attribute.CacheKeyPrefix); try { // get the result var returnValue = context.IsAsync() ? await context.UnwrapAsyncReturnValue() : context.ReturnValue; if (attribute.IsHybridProvider) { await HybridCachingProvider.SetAsync(cacheKey, returnValue, TimeSpan.FromSeconds(attribute.Expiration)); } else { var _cacheProvider = CacheProviderFactory.GetCachingProvider(attribute.CacheProviderName ?? Options.Value.CacheProviderName); await _cacheProvider.SetAsync(cacheKey, returnValue, TimeSpan.FromSeconds(attribute.Expiration)); } } catch (Exception ex) { if (!attribute.IsHighAvailability) { throw; } else { Logger?.LogError(new EventId(), ex, $"Cache provider set error."); } } } }
/// <summary> /// Proceeds the able async. /// </summary> /// <returns>The able async.</returns> /// <param name="context">Context.</param> /// <param name="next">Next.</param> private async Task ProceedAbleAsync(AspectContext context, AspectDelegate next) { if (GetMethodAttributes(context.ServiceMethod).FirstOrDefault(x => typeof(EasyCachingAbleAttribute).IsAssignableFrom(x.GetType())) is EasyCachingAbleAttribute attribute) { var returnType = context.IsAsync() ? context.ServiceMethod.ReturnType.GetGenericArguments().First() : context.ServiceMethod.ReturnType; var cacheKey = KeyGenerator.GetCacheKey(context.ServiceMethod, context.Parameters, attribute.CacheKeyPrefix); object cacheValue = null; var isAvailable = true; try { if (attribute.IsHybridProvider) { cacheValue = await HybridCachingProvider.GetAsync(cacheKey, returnType); } else { var _cacheProvider = CacheProviderFactory.GetCachingProvider(attribute.CacheProviderName ?? Options.Value.CacheProviderName); cacheValue = await _cacheProvider.GetAsync(cacheKey, returnType); } } catch (Exception ex) { if (!attribute.IsHighAvailability) { throw; } else { isAvailable = false; Logger?.LogError(new EventId(), ex, $"Cache provider get error."); } } if (cacheValue != null) { if (context.IsAsync()) { //#1 //dynamic member = context.ServiceMethod.ReturnType.GetMember("Result")[0]; //dynamic temp = System.Convert.ChangeType(cacheValue.Value, member.PropertyType); //context.ReturnValue = System.Convert.ChangeType(Task.FromResult(temp), context.ServiceMethod.ReturnType); //#2 context.ReturnValue = TypeofTaskResultMethod.GetOrAdd(returnType, t => typeof(Task).GetMethods().First(p => p.Name == "FromResult" && p.ContainsGenericParameters).MakeGenericMethod(returnType)).Invoke(null, new object[] { cacheValue }); } else { //context.ReturnValue = System.Convert.ChangeType(cacheValue.Value, context.ServiceMethod.ReturnType); context.ReturnValue = cacheValue; } } else { // Invoke the method if we don't have a cache hit await next(context); if (isAvailable) { // get the result var returnValue = context.IsAsync() ? await context.UnwrapAsyncReturnValue() : context.ReturnValue; // should we do something when method return null? // 1. cached a null value for a short time // 2. do nothing if (returnValue != null) { if (attribute.IsHybridProvider) { await HybridCachingProvider.SetAsync(cacheKey, returnValue, TimeSpan.FromSeconds(attribute.Expiration)); } else { var _cacheProvider = CacheProviderFactory.GetCachingProvider(attribute.CacheProviderName ?? Options.Value.CacheProviderName); await _cacheProvider.SetAsync(cacheKey, returnValue, TimeSpan.FromSeconds(attribute.Expiration)); } } } } } else { // Invoke the method if we don't have EasyCachingAbleAttribute await next(context); } }
/// <summary> /// /// </summary> /// <param name="context"></param> /// <param name="next"></param> /// <returns></returns> private async Task ProcessRedisCaching(AspectContext context, AspectDelegate next) { var attribute = GetMethodAttributes(context.ServiceMethod).FirstOrDefault(x => x.GetType() == typeof(RedisCachingAttribute)) as RedisCachingAttribute; if (attribute == null) { await context.Invoke(next); } var returnType = context.IsAsync() ? context.ServiceMethod.ReturnType.GetGenericArguments().First() : context.ServiceMethod.ReturnType; var cacheKey = ""; cacheKey = KeyGenerator.GetCacheKey(context.ServiceMethod, context.Parameters, attribute.CacheKeyPrefix); if (context.Parameters != null && context.Parameters.Length > 0) { var md5key = Encrypt.Md5By32(Json.ToJson(context.Parameters)); cacheKey = cacheKey + ":" + md5key; } else { var md5key = Encrypt.Md5By32(Json.ToJson(context.ServiceMethod.Name)); cacheKey = cacheKey + ":" + md5key; } object cacheValue = null; var isAvailable = true; try { if (attribute.IsHybridProvider) { cacheValue = await HybridCachingProvider.GetAsync(cacheKey, returnType); } else { var _cacheProvider = CacheProviderFactory.GetCachingProvider(attribute.CacheProviderName ?? Options.Value.CacheProviderName); //cacheValue = await _cacheProvider.GetAsync(cacheKey, returnType); var val = await _cacheProvider.GetAsync <string>(cacheKey); if (val.HasValue) { cacheValue = JsonConvert.DeserializeObject(val.Value, returnType); } } } catch (Exception ex) { if (!attribute.IsHighAvailability) { throw ex; } else { isAvailable = false; } } if (cacheValue != null) { if (context.IsAsync()) { //#1 //dynamic member = context.ServiceMethod.ReturnType.GetMember("Result")[0]; //dynamic temp = System.Convert.ChangeType(cacheValue.Value, member.PropertyType); //context.ReturnValue = System.Convert.ChangeType(Task.FromResult(temp), context.ServiceMethod.ReturnType); //#2 context.ReturnValue = TypeofTaskResultMethod.GetOrAdd(returnType, t => typeof(Task).GetMethods().First(p => p.Name == "FromResult" && p.ContainsGenericParameters).MakeGenericMethod(returnType)).Invoke(null, new object[] { cacheValue }); } else { //context.ReturnValue = System.Convert.ChangeType(cacheValue.Value, context.ServiceMethod.ReturnType); context.ReturnValue = cacheValue; } return; } // Invoke the method if we don't have a cache hit await next(context); try { if (isAvailable) { // get the result var returnValue = context.IsAsync() ? await context.UnwrapAsyncReturnValue() : context.ReturnValue; // should we do something when method return null? // 1. cached a null value for a short time // 2. do nothing if (returnValue != null && cacheKey.IsNotWhiteSpaceEmpty()) { if (attribute.IsHybridProvider) { await HybridCachingProvider.SetAsync(cacheKey, returnValue, TimeSpan.FromSeconds(attribute.Expiration)); } else { var _cacheProvider = CacheProviderFactory.GetCachingProvider(attribute.CacheProviderName ?? Options.Value.CacheProviderName); //var f = Newtonsoft.Json.JsonConvert.SerializeObject(returnValue); await _cacheProvider.SetAsync(cacheKey, JsonConvert.SerializeObject(returnValue, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, DateTimeZoneHandling = DateTimeZoneHandling.Local }), TimeSpan.FromSeconds(attribute.Expiration)); } } } } catch (Exception ex) { ex.Submit(); } }