/// <summary>
        /// Creates a new <see cref="FusionCacheEntryOptions"/> object by duplicating all the options of the current one.
        /// </summary>
        /// <param name="duration">A custom <see cref="Duration"/> that, if specified, will overwrite the current one.</param>
        /// <param name="includeOptionsModifiers">If false, the <see cref="MemoryOptionsModifier"/> and <see cref="DistributedOptionsModifier"/> will not be duplicated.</param>
        /// <returns>The newly created <see cref="FusionCacheEntryOptions"/> object.</returns>
        public FusionCacheEntryOptions Duplicate(TimeSpan?duration = null, bool includeOptionsModifiers = true)
        {
            var res = new FusionCacheEntryOptions()
            {
                Duration    = duration ?? Duration,
                LockTimeout = LockTimeout,

                Size              = Size,
                Priority          = Priority,
                JitterMaxDuration = JitterMaxDuration,

                IsFailSafeEnabled        = IsFailSafeEnabled,
                FailSafeMaxDuration      = FailSafeMaxDuration,
                FailSafeThrottleDuration = FailSafeThrottleDuration,

                FactorySoftTimeout = FactorySoftTimeout,
                FactoryHardTimeout = FactoryHardTimeout,
                AllowTimedOutFactoryBackgroundCompletion = AllowTimedOutFactoryBackgroundCompletion,

                DistributedCacheSoftTimeout = DistributedCacheSoftTimeout,
                DistributedCacheHardTimeout = DistributedCacheHardTimeout,
                AllowBackgroundDistributedCacheOperations = AllowBackgroundDistributedCacheOperations
            };

            if (includeOptionsModifiers)
            {
                res.MemoryOptionsModifier      = MemoryOptionsModifier;
                res.DistributedOptionsModifier = DistributedOptionsModifier;
            }

            return(res);
        }
Esempio n. 2
0
        /// <summary>
        /// Creates a new instance of a <see cref="FusionCacheOptions"/> object.
        /// </summary>
        public FusionCacheOptions()
        {
            DefaultEntryOptions = new FusionCacheEntryOptions();

            // LOG LEVELS
            SerializationErrorsLogLevel = LogLevel.Error;
            DistributedCacheSyntheticTimeoutsLogLevel = LogLevel.Warning;
            DistributedCacheErrorsLogLevel            = LogLevel.Warning;
            FactorySyntheticTimeoutsLogLevel          = LogLevel.Warning;
            FactoryErrorsLogLevel      = LogLevel.Warning;
            FailSafeActivationLogLevel = LogLevel.Warning;
        }
        private void MaybeBackgroundCompleteTimedOutFactory <TValue>(string operationId, string key, Task <TValue>?factoryTask, FusionCacheEntryOptions options, DistributedCacheAccessor?dca, CancellationToken token)
        {
            if (options.AllowTimedOutFactoryBackgroundCompletion == false || factoryTask is null)
            {
                return;
            }

            if (factoryTask.IsFaulted)
            {
                if (_logger?.IsEnabled(_options.FactoryErrorsLogLevel) ?? false)
                {
                    _logger.Log(_options.FactoryErrorsLogLevel, factoryTask.Exception.GetSingleInnerExceptionOrSelf(), "FUSION (K={CacheKey} OP={CacheOperationId}): a timed-out factory thrown an exception", key, operationId);
                }
                return;
            }

            // CONTINUE IN THE BACKGROUND TO TRY TO KEEP THE RESULT AS SOON AS IT WILL COMPLETE SUCCESSFULLY
            if (_logger?.IsEnabled(LogLevel.Debug) ?? false)
            {
                _logger.LogDebug("FUSION (K={CacheKey} OP={CacheOperationId}): trying to complete the timed-out factory in the background", key, operationId);
            }

            _ = factoryTask.ContinueWith(antecedent =>
            {
                if (antecedent.Status == TaskStatus.Faulted)
                {
                    if (_logger?.IsEnabled(_options.FactoryErrorsLogLevel) ?? false)
                    {
                        _logger.Log(_options.FactoryErrorsLogLevel, antecedent.Exception.GetSingleInnerExceptionOrSelf(), "FUSION (K={CacheKey} OP={CacheOperationId}): a timed-out factory thrown an exception", key, operationId);
                    }
                }
                else if (antecedent.Status == TaskStatus.RanToCompletion)
                {
                    if (_logger?.IsEnabled(LogLevel.Debug) ?? false)
                    {
                        _logger.LogDebug("FUSION (K={CacheKey} OP={CacheOperationId}): a timed-out factory successfully completed in the background: keeping the result", key, operationId);
                    }

                    var lateEntry = FusionCacheMemoryEntry.CreateFromOptions(antecedent.Result, options, false);
                    _             = dca?.SetEntryAsync <TValue>(operationId, key, lateEntry, options, token);
                    _mca.SetEntry <TValue>(operationId, key, lateEntry, options);
                }
            });
        }
        private IFusionCacheEntry?MaybeGetFallbackEntry <TValue>(string operationId, string key, FusionCacheDistributedEntry <TValue>?distributedEntry, FusionCacheMemoryEntry?memoryEntry, FusionCacheEntryOptions options, out bool failSafeActivated)
        {
            failSafeActivated = false;

            if (options.IsFailSafeEnabled)
            {
                if (_logger?.IsEnabled(LogLevel.Trace) ?? false)
                {
                    _logger.LogTrace("FUSION (K={CacheKey} OP={CacheOperationId}): trying to activate FAIL-SAFE", key, operationId);
                }
                if (distributedEntry is object)
                {
                    // FAIL SAFE (FROM DISTRIBUTED)
                    if (_logger?.IsEnabled(_options.FailSafeActivationLogLevel) ?? false)
                    {
                        _logger.Log(_options.FailSafeActivationLogLevel, "FUSION (K={CacheKey} OP={CacheOperationId}): FAIL-SAFE activated (from distributed)", key, operationId);
                    }
                    failSafeActivated = true;
                    return(distributedEntry);
                }
                else if (memoryEntry is object)
                {
                    // FAIL SAFE (FROM MEMORY)
                    if (_logger?.IsEnabled(_options.FailSafeActivationLogLevel) ?? false)
                    {
                        _logger.Log(_options.FailSafeActivationLogLevel, "FUSION (K={CacheKey} OP={CacheOperationId}): FAIL-SAFE activated (from memory)", key, operationId);
                    }
                    failSafeActivated = true;
                    return(memoryEntry);
                }
                else
                {
                    if (_logger?.IsEnabled(_options.FailSafeActivationLogLevel) ?? false)
                    {
                        _logger.Log(_options.FailSafeActivationLogLevel, "FUSION (K={CacheKey} OP={CacheOperationId}): unable to activate FAIL-SAFE (no entries in memory or distributed)", key, operationId);
                    }
                    return(null);
                }
            }
            else
            {
                if (_logger?.IsEnabled(LogLevel.Trace) ?? false)
                {
                    _logger.LogTrace("FUSION (K={CacheKey} OP={CacheOperationId}): FAIL-SAFE not enabled", key, operationId);
                }
                return(null);
            }
        }