コード例 #1
0
        private Task Notify(ICircuitRequest request, ICircuitResponse response, TimeSpan executionTime)
        {
            if (_listeners == null || !_listeners.Any())
            {
                return(Task.CompletedTask);
            }

            try
            {
                var data = new CircuitStatusData
                {
                    RequestId     = request.RequestId,
                    CircuitKey    = request.CircuitKey,
                    Context       = request.Context,
                    ExecutionTime = executionTime,
                    Status        = response.Status
                };

                var tasks = _listeners.Select(x => x.Notify(data)).ToArray();

                return(Task.WhenAll(tasks));
            }
            catch (Exception e)
            {
                CircuitBreakerLog.LogError(e, e.Message);
            }

            return(Task.CompletedTask);
        }
コード例 #2
0
        public async Task <ICircuitResponse <T> > ExecuteAsync <T>(ICircuitRequest request, Func <ICircuitRequest, Task <T> > funcAsync)
        {
            if (string.IsNullOrWhiteSpace(request.CircuitKey))
            {
                throw new ArgumentNullException(nameof(request.CircuitKey));
            }
            if (funcAsync == null)
            {
                throw new ArgumentNullException(nameof(funcAsync));
            }

            var policy = await _policyProvider.Get(request);

            T        value         = default(T);
            TimeSpan executionTime = TimeSpan.Zero;

            var policyResult = await policy.ExecuteAndCaptureAsync(async() => {
                var sw = Stopwatch.StartNew();
                value  = await funcAsync(request);
                sw.Stop();
                executionTime = sw.Elapsed;
            });

            var result = BuildResponse <CircuitResponse <T> >(request, policyResult.Outcome, policyResult.FinalException, executionTime);

            result.Value = value;

            await Notify(request, result, executionTime);

            return(result);
        }
コード例 #3
0
        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();
            }
        }
コード例 #4
0
ファイル: Program.cs プロジェクト: mruhul/Bolt.CircuitBreaker
        private static async Task Execute(ICircuitBreaker cb, ICircuitRequest request)
        {
            var result = await cb.ExecuteAsync(request, cxt => DoSomething(cxt));

            Console.WriteLine(result.Value);

            WriteStatus(result);
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine("******");
            Console.WriteLine();
        }
コード例 #5
0
        private int?GetInt(ICircuitRequest request, string key)
        {
            var strValue = request.Context.Get <string>(key);

            if (string.IsNullOrWhiteSpace(strValue))
            {
                return(null);
            }

            return(int.TryParse(strValue, out var result) ? result : (int?)null);
        }
コード例 #6
0
        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))));
        }
コード例 #7
0
        private async Task <TResponse> HandleError <TResponse>(ICircuitRequest request, Exception e) where TResponse : ICircuitResponse, new()
        {
            CircuitBreakerLog.LogError(e, e.Message);

            var response = new TResponse {
                Status = CircuitStatus.Failed
            };

            await Notify(request, response, TimeSpan.Zero);

            return(response);
        }
コード例 #8
0
ファイル: Program.cs プロジェクト: mruhul/Bolt.CircuitBreaker
        private static async Task <string> DoSomething(ICircuitRequest request)
        {
            //Console.WriteLine($"Start...");

            //var toss = _rnd.Next(1, 5);

            //if (toss > 2) throw new Exception("Toss failed");

            var delay = _rnd.Next(100, 100);
            await Task.Delay(delay);

            return($"Delay {delay}ms");
        }
コード例 #9
0
        public Task <PolicySettings> Get(ICircuitRequest request)
        {
            var settings = new PolicySettings();

            settings.DurationOfBreak         = GetTimeSpan(request, "Polly.DurationOfBreak");
            settings.FailurePercentThreshold = GetInt(request, "Polly.FailurePercentThreshold");
            settings.MaxParallelization      = GetInt(request, "Polly.MaxParallelization");
            settings.MaxQueingActions        = GetInt(request, "Polly.MaxQueingActions");
            settings.MinimumThroughput       = GetInt(request, "Polly.MinimumThroughput");
            settings.SamplingDuration        = GetTimeSpan(request, "Polly.SamplingDuration");
            settings.Timeout = GetTimeSpan(request, "Polly.Timeout");
            settings.Retry   = GetInt(request, "Polly.Retry");

            return(Task.FromResult(settings));
        }
コード例 #10
0
        public Task <PolicySettings> Get(ICircuitRequest request)
        {
            var result = _config.Policies?.FirstOrDefault(x => string.Equals(x.CircuitKey, request.CircuitKey));

            if (result != null)
            {
                return(Task.FromResult(BuildSettings(result)));
            }

            var serviceName = request.Context.GetServiceName();

            result = _config.Policies?.FirstOrDefault(x => string.Equals(x.CircuitKey, $"{serviceName}"));

            if (result != null)
            {
                return(Task.FromResult(BuildSettings(result)));
            }

            return(Task.FromResult <PolicySettings>(null));
        }
コード例 #11
0
        public async Task <ICircuitResponse <T> > ExecuteAsync <T>(ICircuitRequest request, Func <ICircuitRequest, Task <T> > funcAsync)
        {
            try
            {
                var sw = Stopwatch.StartNew();

                var value = await funcAsync(request);

                sw.Stop();

                var response = new CircuitResponse <T> {
                    Status = CircuitStatus.Succeed, Value = value
                };

                await Notify(request, response, sw.Elapsed);

                return(response);
            }
            catch (Exception e)
            {
                return(await HandleError <CircuitResponse <T> >(request, e));
            }
        }
コード例 #12
0
        private TResponse BuildResponse <TResponse>(ICircuitRequest request, Polly.OutcomeType outcome, Exception finalException, TimeSpan executionTime) where TResponse : ICircuitResponse, new()
        {
            var result = new TResponse();

            if (outcome == Polly.OutcomeType.Failure)
            {
                if (finalException is Polly.Timeout.TimeoutRejectedException || finalException is TimeoutException)
                {
                    Trace(CircuitStatus.Timeout, request, finalException, executionTime);

                    result.Status = CircuitStatus.Timeout;
                }
                else if (finalException is Polly.CircuitBreaker.BrokenCircuitException)
                {
                    Trace(CircuitStatus.Broken, request, finalException, executionTime);

                    result.Status = CircuitStatus.Broken;
                }
                else
                {
                    CircuitBreakerLog.LogError(finalException, finalException.Message);

                    Trace(CircuitStatus.Failed, request, finalException, executionTime);

                    result.Status = CircuitStatus.Failed;
                }
            }
            else
            {
                Trace(CircuitStatus.Succeed, request, finalException, executionTime);

                result.Status = CircuitStatus.Succeed;
            }

            return(result);
        }
コード例 #13
0
 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}");
 }
コード例 #14
0
        private TimeSpan?GetTimeSpan(ICircuitRequest request, string key)
        {
            var value = GetInt(request, key);

            return(value.HasValue ? TimeSpan.FromMilliseconds(value.Value) : (TimeSpan?)null);
        }