/// <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); }
/// <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); } }