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);
        }
Beispiel #3
0
        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();
        }
Beispiel #6
0
        /// <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);
        }
Beispiel #8
0
        /// <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.");
                    }
                }
            }
        }
Beispiel #9
0
        /// <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();
            }
        }