public async Task <IAsyncPolicy> Get(ICircuitRequest request) { IAsyncPolicy result; var key = $"{request.CircuitKey}:{request.Retry}:{request.Timeout}"; if (_source.TryGetValue(key, out result)) { return(result); } await _semaphore.WaitAsync(); try { if (_source.TryGetValue(key, out result)) { return(result); } CircuitBreakerLog.LogTrace("Loading policy from provider..."); PolicySettings settings = null; if (_settingsProvider != null) { foreach (var provider in _settingsProvider) { settings = await provider.Get(request); if (settings != null) { break; } } } var shouldReloadSettings = settings?.ShouldReload ?? false; var policy = BuildPolicy(request, settings); if (!shouldReloadSettings) { _source.TryAdd(key, policy); } else { CircuitBreakerLog.LogWarning("Policy need to reload from provider next time as requested by provider. So escape storing the policy to reuse"); } return(policy); } finally { _semaphore.Release(); } }
private IAsyncPolicy BuildPolicy(ICircuitRequest request, PolicySettings settings) { settings = settings ?? new PolicySettings(); var maxParallelization = settings.MaxParallelization ?? 100; var maxQueingActions = settings.MaxQueingActions ?? 10; var timeout = AppliedTimespan(request.Timeout, settings.Timeout, TimeSpan.FromMinutes(10)); var retry = request.Retry ?? settings.Retry ?? 0; var failurePercentThresholdPercent = EmptyAlternative(settings.FailurePercentThreshold, 50); var failureThreshold = failurePercentThresholdPercent / 100d; var samplingDuration = AppliedTimespan(settings.SamplingDuration, TimeSpan.FromMilliseconds(1000)); var minThroughput = settings.MinimumThroughput ?? 5; var durationOfBreak = AppliedTimespan(settings.DurationOfBreak, TimeSpan.FromMilliseconds(500)); if (CircuitBreakerLog.IsTraceEnabled) { CircuitBreakerLog.LogTrace($@"RequestId:{request.RequestId} |AppName:{request.Context.GetAppName()} |ServiceName:{request.Context.GetServiceName()} |CircuitKey:{request.CircuitKey} |Request.Retry:{request.Retry} |Request.Timeout:{request.Timeout} |Settings.Retry:{settings.Retry} |Settings.Timeout:{settings.Timeout} |Settings.FailureThreshold:{failureThreshold} |Settings.SamplingDuration:{samplingDuration} |Settings.MinThroughput:{minThroughput} |Settings.DurationOfBreak:{durationOfBreak} |Settings.MaxParallelization:{maxParallelization} |Settings.MaxQueingActions:{maxQueingActions}"); } var bulkHead = Policy.BulkheadAsync(maxParallelization, maxQueingActions); var timeoutPolicy = Policy.TimeoutAsync(timeout, Polly.Timeout.TimeoutStrategy.Pessimistic); var retryPolicy = Policy.Handle <Exception>().RetryAsync(retry); var circuit = Policy.Handle <Exception>() .AdvancedCircuitBreakerAsync(failureThreshold, samplingDuration, minThroughput, durationOfBreak); return(circuit.WrapAsync(bulkHead.WrapAsync(retryPolicy.WrapAsync(timeoutPolicy)))); }
private void Trace(CircuitStatus status, ICircuitRequest request, Exception exception, TimeSpan executiontime) { CircuitBreakerLog.LogTrace($"RequestId:{request.RequestId}|CircuitKey:{request.CircuitKey}|Status:{status}|ExecutionTime:{executiontime.TotalMilliseconds}ms|Msg:{exception?.Message}"); }