Exemple #1
0
        /// <summary>
        /// Proceeds the able.
        /// </summary>
        /// <param name="invocation">Invocation.</param>
        private void ProceedAble(IInvocation invocation, CachingAbleAttribute attribute)
        {
            var serviceMethod = invocation.Method ?? invocation.MethodInvocationTarget;

            var returnType = serviceMethod.IsReturnTask()
                    ? serviceMethod.ReturnType.GetGenericArguments().First()
                    : serviceMethod.ReturnType;

            var cacheKey = string.IsNullOrEmpty(attribute.CacheKey)
                                 ? _keyGenerator.GetCacheKey(serviceMethod, invocation.Arguments, attribute.CacheKeyPrefix)
                                 : attribute.CacheKey
            ;

            object cacheValue  = null;
            var    isAvailable = true;

            try
            {
                cacheValue = _cacheProvider.GetAsync(cacheKey, returnType).GetAwaiter().GetResult();
            }
            catch (Exception ex)
            {
                if (!attribute.IsHighAvailability)
                {
                    throw;
                }
                else
                {
                    isAvailable = false;
                    _logger?.LogError(new EventId(), ex, $"Cache provider get error.");
                }
            }

            if (cacheValue != null)
            {
                if (serviceMethod.IsReturnTask())
                {
                    invocation.ReturnValue =
                        TypeofTaskResultMethod.GetOrAdd(returnType, t => typeof(Task).GetMethods().First(p => p.Name == "FromResult" && p.ContainsGenericParameters).MakeGenericMethod(returnType)).Invoke(null, new object[] { cacheValue });
                }
                else
                {
                    invocation.ReturnValue = cacheValue;
                }
            }
            else
            {
                // Invoke the method if we don't have a cache hit
                invocation.Proceed();

                if (!string.IsNullOrWhiteSpace(cacheKey) && invocation.ReturnValue != null && isAvailable)
                {
                    // get the result
                    var returnValue = serviceMethod.IsReturnTask()
                       ? invocation.UnwrapAsyncReturnValue().Result
                       : invocation.ReturnValue;

                    // should we do something when method return null?
                    // 1. cached a null value for a short time
                    // 2. do nothing
                    if (returnValue != null)
                    {
                        _cacheProvider.Set(cacheKey, returnValue, TimeSpan.FromSeconds(attribute.Expiration));
                    }
                }
            }
        }
        private void InternalInterceptSynchronous(IInvocation invocation, CachingInterceptorAttribute attribute)
        {
            var methodInfo = invocation.Method ?? invocation.MethodInvocationTarget;

            if (attribute is CachingAbleAttribute ableAttribute)
            {
                var cacheKey = string.IsNullOrEmpty(attribute.CacheKey)
                 ? _keyGenerator.GetCacheKey(methodInfo, invocation.Arguments, attribute.CacheKeyPrefix)
                 : attribute.CacheKey
                ;

                try
                {
                    var cacheValue = _cacheProvider.GetAsync(cacheKey, methodInfo.ReturnType).GetAwaiter().GetResult();
                    if (cacheKey != null)
                    {
                        invocation.ReturnValue = cacheValue;
                    }
                    else
                    {
                        invocation.Proceed();
                        if (!string.IsNullOrWhiteSpace(cacheKey) && invocation.ReturnValue != null)
                        {
                            _cacheProvider.Set(cacheKey, invocation.ReturnValue, TimeSpan.FromSeconds(ableAttribute.Expiration));
                        }
                    }
                }
                catch (Exception ex)
                {
                    if (!attribute.IsHighAvailability)
                    {
                        throw;
                    }
                    else
                    {
                        _logger?.LogError(new EventId(), ex, $"Cache provider get error.");
                    }
                }
                return;
            }

            if (attribute is CachingEvictAttribute evictAttribute)
            {
                var(cacheKeys, expireDt) = ProcessEvictBefore(invocation, evictAttribute);

                var cancelTokenSource = new CancellationTokenSource();
                var timeoutPolicy     = Policy.Timeout(_cacheProvider.CacheOptions.PollyTimeoutSeconds, Polly.Timeout.TimeoutStrategy.Optimistic);
                try
                {
                    timeoutPolicy.Execute((cancellToken) =>
                    {
                        invocation.Proceed();
                        cancellToken.ThrowIfCancellationRequested();
                    }, cancelTokenSource.Token);

                    _cacheProvider.RemoveAll(cacheKeys);
                }
                catch (Exception ex)
                {
                    LocalVariables.Instance.Queue.Enqueue(new LocalVariables.Model(cacheKeys, expireDt));

                    if (!attribute.IsHighAvailability)
                    {
                        throw;
                    }
                    else
                    {
                        _logger?.LogError(new EventId(), ex, $"Cache provider remove error.");
                    }
                }
            }
        }