public async Task Distributed_Set_Async_Throw_Exception_Should_Not_Break() { A.CallTo(() => fakeDisProvider.SetAsync(A <string> .Ignored, A <string> .Ignored, A <TimeSpan> .Ignored)).ThrowsAsync(new Exception()); var key = $"d-set-{Guid.NewGuid().ToString()}"; await fakeHybrid.SetAsync(key, "123", TimeSpan.FromSeconds(30)); var res = await fakeHybrid.GetAsync <string>(key); Assert.True(res.HasValue); Assert.Equal(default(string), res.Value); }
public async void GetAsyncWithDataRetriever_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 = CreateFakeAsyncDataRetriever(result: "cachedValue"); A.CallTo(() => fakeDistributedProvider.GetExpirationAsync(cacheKey)).Returns(distributeExpiration); A.CallTo(() => fakeDistributedProvider.GetAsync(cacheKey, A <Func <Task <string> > > ._, A <TimeSpan> ._)) .Returns(new CacheValue <string>("cachedValue", true)); var res = await hybridProvider.GetAsync(cacheKey, dataRetriever, newExpiration); Assert.NotNull(res); Assert.True(res.HasValue); Assert.Equal("cachedValue", res.Value); A.CallTo(() => fakeDistributedProvider.GetExpirationAsync(cacheKey)).MustHaveHappenedOnceExactly(); A.CallTo(() => fakeLocalCache.Set(cacheKey, A <string> ._, TimeSpan.FromMinutes(setLocalExpirationMinutes))) .MustHaveHappenedOnceExactly(); }
public async void GetAsyncWithDataRetriever_LocalCacheHasValue_DistributedCacheAndDataRetrieverShouldNotBeCalled() { var(hybridProvider, localProvider, fakeDistributedProvider, _) = CreateCachingProviderWithFakes(); var dataRetriever = CreateFakeAsyncDataRetriever(result: "value"); localProvider.Set("key", "cachedValue", Expiration); var res = await hybridProvider.GetAsync("key", dataRetriever, Expiration); Assert.True(res.HasValue); Assert.Equal("cachedValue", res.Value); var cachedValue = localProvider.Get <string>("key"); Assert.True(cachedValue.HasValue); Assert.Equal("cachedValue", cachedValue.Value); A.CallTo(() => dataRetriever.Invoke()).MustNotHaveHappened(); fakeDistributedProvider.CallToGetAsyncWithDataRetriever <string>().MustNotHaveHappened(); A.CallTo(() => fakeDistributedProvider.GetExpirationAsync("key")).MustNotHaveHappened(); }
/// <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(); } }