示例#1
0
        public void Should_call_fallbackAction_with_the_passed_context_when_execute_and_capture()
        {
            IDictionary <string, object> contextData = null;

            Func <Context, CancellationToken, Task <ResultPrimitive> > fallbackActionAsync = (ctx, ct) => { contextData = ctx; return(Task.FromResult(ResultPrimitive.Substitute)); };

            Func <Exception, Context, Task> onFallbackAsync = (ex, ctx) => TaskHelper.EmptyTask;

            FallbackPolicy fallbackPolicy = Policy
                                            .Handle <ArgumentNullException>()
                                            .FallbackAsync(fallbackActionAsync, onFallbackAsync);

            fallbackPolicy.Awaiting(async p => await p.ExecuteAndCaptureAsync(() => { throw new ArgumentNullException(); },
                                                                              new { key1 = "value1", key2 = "value2" }.AsDictionary()))
            .ShouldNotThrow();

            contextData.Should()
            .ContainKeys("key1", "key2").And
            .ContainValues("value1", "value2");
        }
示例#2
0
        public async Task Context_should_be_empty_at_fallbackAction_if_execute_not_called_with_any_context_data()
        {
            Context capturedContext  = null;
            bool    fallbackExecuted = false;

            Func <Context, CancellationToken, Task <ResultPrimitive> > fallbackActionAsync = (ctx, ct) => { fallbackExecuted = true; capturedContext = ctx; return(Task.FromResult(ResultPrimitive.Substitute)); };
            Func <DelegateResult <ResultPrimitive>, Context, Task>     onFallbackAsync     = (ex, ctx) => TaskHelper.EmptyTask;

            FallbackPolicy <ResultPrimitive> fallbackPolicy = Policy
                                                              .HandleResult(ResultPrimitive.Fault)
                                                              .OrResult(ResultPrimitive.FaultAgain)
                                                              .FallbackAsync(fallbackActionAsync, onFallbackAsync);

            (await fallbackPolicy.RaiseResultSequenceAsync(ResultPrimitive.Fault).ConfigureAwait(false))
            .Should().Be(ResultPrimitive.Substitute);


            fallbackExecuted.Should().BeTrue();
            capturedContext.Should().BeEmpty();
        }
示例#3
0
        public void Should_call_fallbackAction_with_the_passed_context_when_execute_and_capture()
        {
            IDictionary <string, object> contextData = null;

            Action <Context, CancellationToken> fallbackAction = (ctx, ct) => { contextData = ctx; };

            Action <Exception, Context> onFallback = (ex, ctx) => { };

            FallbackPolicy fallbackPolicy = Policy
                                            .Handle <ArgumentNullException>()
                                            .Fallback(fallbackAction, onFallback);

            fallbackPolicy.Invoking(p => p.ExecuteAndCapture(() => { throw new ArgumentNullException(); },
                                                             new { key1 = "value1", key2 = "value2" }.AsDictionary()))
            .ShouldNotThrow();

            contextData.Should()
            .ContainKeys("key1", "key2").And
            .ContainValues("value1", "value2");
        }
示例#4
0
        public async Task Should_call_onFallback_with_the_passed_context_when_execute_and_capture()
        {
            Func <Context, CancellationToken, Task <ResultPrimitive> > fallbackAction = (_, __) => Task.FromResult(ResultPrimitive.Substitute);

            IDictionary <string, object> contextData = null;

            Func <DelegateResult <ResultPrimitive>, Context, Task> onFallbackAsync = (ex, ctx) => { contextData = ctx; return(TaskHelper.EmptyTask); };

            FallbackPolicy <ResultPrimitive> fallbackPolicy = Policy
                                                              .HandleResult(ResultPrimitive.Fault)
                                                              .FallbackAsync(fallbackAction, onFallbackAsync);

            (await fallbackPolicy.ExecuteAndCaptureAsync(() => { return(Task.FromResult(ResultPrimitive.Fault)); },
                                                         new { key1 = "value1", key2 = "value2" }.AsDictionary()).ConfigureAwait(false))
            .Result.Should().Be(ResultPrimitive.Substitute);

            contextData.Should()
            .ContainKeys("key1", "key2").And
            .ContainValues("value1", "value2");
        }
示例#5
0
        public void Should_call_onFallback_passing_exception_triggering_fallback()
        {
            bool   fallbackActionExecuted = false;
            Action fallbackAction         = () => { fallbackActionExecuted = true; };

            Exception          exceptionPassedToOnFallback = null;
            Action <Exception> onFallback = ex => { exceptionPassedToOnFallback = ex; };

            FallbackPolicy fallbackPolicy = Policy
                                            .Handle <ArgumentNullException>()
                                            .Fallback(fallbackAction, onFallback);

            Exception instanceToThrow = new ArgumentNullException("myParam");

            fallbackPolicy.Execute(() => { throw instanceToThrow; });

            fallbackActionExecuted.Should().BeTrue();
            exceptionPassedToOnFallback.Should().BeOfType <ArgumentNullException>();
            exceptionPassedToOnFallback.Should().Be(instanceToThrow);
        }
        public void Should_call_fallbackAction_with_the_fault()
        {
            DelegateResult <ResultPrimitive> fallbackOutcome = null;

            Func <DelegateResult <ResultPrimitive>, Context, CancellationToken, ResultPrimitive> fallbackAction =
                (outcome, ctx, ct) => { fallbackOutcome = outcome; return(ResultPrimitive.Substitute); };

            Action <DelegateResult <ResultPrimitive>, Context> onFallback = (ex, ctx) => { };

            FallbackPolicy <ResultPrimitive> fallbackPolicy = Policy <ResultPrimitive>
                                                              .HandleResult(ResultPrimitive.Fault)
                                                              .Fallback(fallbackAction, onFallback);

            fallbackPolicy.Execute(() => { return(ResultPrimitive.Fault); })
            .Should().Be(ResultPrimitive.Substitute);

            fallbackOutcome.Should().NotBeNull();
            fallbackOutcome.Exception.Should().BeNull();
            fallbackOutcome.Result.Should().Be(ResultPrimitive.Fault);
        }
        public void Should_call_fallbackAction_with_the_passed_context_when_execute_and_capture()
        {
            IDictionary <string, object> contextData = null;

            Func <Context, CancellationToken, ResultPrimitive> fallbackAction = (ctx, ct) => { contextData = ctx; return(ResultPrimitive.Substitute); };

            Action <DelegateResult <ResultPrimitive>, Context> onFallback = (ex, ctx) => { };

            FallbackPolicy <ResultPrimitive> fallbackPolicy = Policy
                                                              .HandleResult(ResultPrimitive.Fault)
                                                              .Fallback(fallbackAction, onFallback);

            fallbackPolicy.ExecuteAndCapture(() => { return(ResultPrimitive.Fault); },
                                             new { key1 = "value1", key2 = "value2" }.AsDictionary())
            .Result.Should().Be(ResultPrimitive.Substitute);

            contextData.Should()
            .ContainKeys("key1", "key2").And
            .ContainValues("value1", "value2");
        }
示例#8
0
        public void Should_call_onFallback_passing_exception_triggering_fallback()
        {
            bool fallbackActionExecuted = false;
            Func <CancellationToken, Task> fallbackActionAsync = _ => { fallbackActionExecuted = true; return(TaskHelper.EmptyTask); };

            Exception exceptionPassedToOnFallback  = null;
            Func <Exception, Task> onFallbackAsync = ex => { exceptionPassedToOnFallback = ex; return(TaskHelper.EmptyTask); };

            FallbackPolicy fallbackPolicy = Policy
                                            .Handle <ArgumentNullException>()
                                            .FallbackAsync(fallbackActionAsync, onFallbackAsync);

            Exception instanceToThrow = new ArgumentNullException("myParam");

            fallbackPolicy.ExecuteAsync(() => { throw instanceToThrow; });

            fallbackActionExecuted.Should().BeTrue();
            exceptionPassedToOnFallback.Should().BeOfType <ArgumentNullException>();
            exceptionPassedToOnFallback.Should().Be(instanceToThrow);
        }
示例#9
0
        public void Should_call_onFallback_with_the_passed_context()
        {
            Func <Context, CancellationToken, Task> fallbackActionAsync = (_, __) => TaskHelper.EmptyTask;

            IDictionary <string, object> contextData = null;

            Func <Exception, Context, Task> onFallbackAsync = (ex, ctx) => { contextData = ctx; return(TaskHelper.EmptyTask); };

            FallbackPolicy fallbackPolicy = Policy
                                            .Handle <ArgumentNullException>()
                                            .FallbackAsync(fallbackActionAsync, onFallbackAsync);

            fallbackPolicy.Awaiting(async p => await p.ExecuteAsync(ctx => { throw new ArgumentNullException(); },
                                                                    new { key1 = "value1", key2 = "value2" }.AsDictionary()))
            .ShouldNotThrow();

            contextData.Should()
            .ContainKeys("key1", "key2").And
            .ContainValues("value1", "value2");
        }
示例#10
0
        public void Should_call_onFallback_passing_result_triggering_fallback()
        {
            bool fallbackActionExecuted       = false;
            Func <ResultClass> fallbackAction = () => { fallbackActionExecuted = true; return(new ResultClass(ResultPrimitive.Substitute)); };

            ResultClass resultPassedToOnFallback = null;
            Action <DelegateResult <ResultClass> > onFallback = r => { resultPassedToOnFallback = r.Result; };

            FallbackPolicy <ResultClass> fallbackPolicy = Policy
                                                          .HandleResult <ResultClass>(r => r.ResultCode == ResultPrimitive.Fault)
                                                          .Fallback(fallbackAction, onFallback);

            ResultClass resultFromDelegate = new ResultClass(ResultPrimitive.Fault);

            fallbackPolicy.Execute(() => { return(resultFromDelegate); });

            fallbackActionExecuted.Should().BeTrue();
            resultPassedToOnFallback.Should().NotBeNull();
            resultPassedToOnFallback.Should().Be(resultFromDelegate);
        }
示例#11
0
        public void Should_call_onFallback_with_the_passed_context()
        {
            Func <Context, ResultPrimitive> fallbackAction = _ => ResultPrimitive.Substitute;

            IDictionary <string, object> contextData = null;

            Action <DelegateResult <ResultPrimitive>, Context> onFallback = (dr, ctx) => { contextData = ctx; };

            FallbackPolicy <ResultPrimitive> fallbackPolicy = Policy
                                                              .HandleResult(ResultPrimitive.Fault)
                                                              .Fallback(fallbackAction, onFallback);

            fallbackPolicy.Execute(() => { return(ResultPrimitive.Fault); },
                                   new { key1 = "value1", key2 = "value2" }.AsDictionary())
            .Should().Be(ResultPrimitive.Substitute);

            contextData.Should()
            .ContainKeys("key1", "key2").And
            .ContainValues("value1", "value2");
        }
示例#12
0
        public void Should_not_handle_exception_thrown_by_fallback_delegate_even_if_is_exception_handled_by_policy()
        {
            bool   fallbackActionExecuted = false;
            Action fallbackAction         = () =>
            {
                fallbackActionExecuted = true;
                throw new DivideByZeroException()
                      {
                          HelpLink = "FromFallbackAction"
                      };
            };

            FallbackPolicy fallbackPolicy = Policy
                                            .Handle <DivideByZeroException>()
                                            .Fallback(fallbackAction);

            fallbackPolicy.Invoking(x => x.RaiseException <DivideByZeroException>((e, i) => e.HelpLink = "FromExecuteDelegate"))
            .ShouldThrow <DivideByZeroException>().And.HelpLink.Should().Be("FromFallbackAction");

            fallbackActionExecuted.Should().BeTrue();
        }
示例#13
0
        public async Task <ActionResult <HttpResponseMessage> > Get()
        {
            Func <Task <HttpResponseMessage> > myFun = async() => await CallFailesService();

            retryPolicy = Policy
                          .HandleResult <HttpResponseMessage>
                              (r => r.StatusCode == System.Net.HttpStatusCode.InternalServerError)
                          .WaitAndRetryAsync(MaxRetryAttempts, i => PauseBetweenFailures);

            fallbackPolicy = Policy.HandleResult <HttpResponseMessage>
                                 (f => f.StatusCode == System.Net.HttpStatusCode.InternalServerError)
                             .FallbackAsync(new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new ObjectContent(typeof(string), "the system under maintentance", new JsonMediaTypeFormatter())
            });

            myResilienceStrategy = Policy.WrapAsync(fallbackPolicy, retryPolicy);
            var ret = await myResilienceStrategy.ExecuteAsync(async() => await myFun.Invoke());

            return(ret);
        }
示例#14
0
        public void Should_not_handle_exception_thrown_by_fallback_delegate_even_if_is_exception_handled_by_policy()
        {
            bool fallbackActionExecuted = false;
            Func <CancellationToken, Task> fallbackActionAsync = _ =>
            {
                fallbackActionExecuted = true;
                throw new DivideByZeroException()
                      {
                          HelpLink = "FromFallbackAction"
                      };
            };

            FallbackPolicy fallbackPolicy = Policy
                                            .Handle <DivideByZeroException>()
                                            .FallbackAsync(fallbackActionAsync);

            fallbackPolicy.Awaiting(async x => await x.RaiseExceptionAsync <DivideByZeroException>((e, i) => e.HelpLink = "FromExecuteDelegate"))
            .ShouldThrow <DivideByZeroException>().And.HelpLink.Should().Be("FromFallbackAction");

            fallbackActionExecuted.Should().BeTrue();
        }
示例#15
0
        public void Should_call_fallbackAction_with_the_passed_context()
        {
            IDictionary <string, object> contextData = null;

            Func <Context, CancellationToken, Task <ResultPrimitive> > fallbackActionAsync = (ctx, ct) => { contextData = ctx; return(Task.FromResult(ResultPrimitive.Substitute)); };

            Func <DelegateResult <ResultPrimitive>, Context, Task> onFallbackAsync = (dr, ctx) => TaskHelper.EmptyTask;

            FallbackPolicy <ResultPrimitive> fallbackPolicy = Policy
                                                              .HandleResult(ResultPrimitive.Fault)
                                                              .FallbackAsync(fallbackActionAsync, onFallbackAsync);

            fallbackPolicy.ExecuteAsync(ctx => { return(Task.FromResult(ResultPrimitive.Fault)); },
                                        new { key1 = "value1", key2 = "value2" }.AsDictionary())
            .Result
            .Should().Be(ResultPrimitive.Substitute);

            contextData.Should()
            .ContainKeys("key1", "key2").And
            .ContainValues("value1", "value2");
        }
示例#16
0
        public async Task Should_call_fallbackAction_with_the_fault()
        {
            DelegateResult <ResultPrimitive> fallbackOutcome = null;

            Func <DelegateResult <ResultPrimitive>, Context, CancellationToken, Task <ResultPrimitive> > fallbackAction =
                (outcome, ctx, ct) => { fallbackOutcome = outcome; return(Task.FromResult(ResultPrimitive.Substitute)); };

            Func <DelegateResult <ResultPrimitive>, Context, Task> onFallback = (ex, ctx) => { return(TaskHelper.EmptyTask); };

            FallbackPolicy <ResultPrimitive> fallbackPolicy = Policy <ResultPrimitive>
                                                              .HandleResult(ResultPrimitive.Fault)
                                                              .FallbackAsync(fallbackAction, onFallback);

            var result = await fallbackPolicy.ExecuteAsync(() => { return(Task.FromResult(ResultPrimitive.Fault)); });

            result.Should().Be(ResultPrimitive.Substitute);

            fallbackOutcome.Should().NotBeNull();
            fallbackOutcome.Exception.Should().BeNull();
            fallbackOutcome.Result.Should().Be(ResultPrimitive.Fault);
        }
示例#17
0
        public static void Test2()
        {
            FallbackPolicy <string> policy = Policy <string> .Handle <ArgumentNullException>()
                                             .Fallback("匿名");

            try
            {
                for (int i = 0; i < 3; i++)
                {
                    string result = policy.Execute(() =>
                    {
                        return(GetUserName(i == 0 ? null : (int?)i));
                    });
                    Console.WriteLine($"用户名是:{result}");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"异常信息:{ex.Message}");
            }
        }
示例#18
0
        public void Should_call_fallbackAction_with_the_fault_when_execute_and_capture()
        {
            DelegateResult <ResultPrimitive> fallbackOutcome = null;

            Func <DelegateResult <ResultPrimitive>, Context, CancellationToken, ResultPrimitive> fallbackAction =
                (outcome, _, _) => { fallbackOutcome = outcome; return(ResultPrimitive.Substitute); };

            Action <DelegateResult <ResultPrimitive>, Context> onFallback = (_, _) => { };

            FallbackPolicy <ResultPrimitive> fallbackPolicy = Policy <ResultPrimitive>
                                                              .HandleResult(ResultPrimitive.Fault)
                                                              .Fallback(fallbackAction, onFallback);

            var result = fallbackPolicy.ExecuteAndCapture(() => ResultPrimitive.Fault);

            result.Should().NotBeNull();
            result.Result.Should().Be(ResultPrimitive.Substitute);

            fallbackOutcome.Should().NotBeNull();
            fallbackOutcome.Exception.Should().BeNull();
            fallbackOutcome.Result.Should().Be(ResultPrimitive.Fault);
        }
示例#19
0
        public static T Get <T>(
            this IStorageManager storageManager,
            IKeyBuilder key,
            FallbackPolicy fallbackPolicy,
            Func <T> callback,
            ISerializer <T, string> serializer = null
            )
        {
            serializer = serializer ?? GetDefaultSerializer <T>();

            var item       = default(T);
            var serialized = storageManager.Get(key, fallbackPolicy);

            if (serialized == null || (item = serializer.Deserialize(serialized)) == null)
            {
                item       = callback();
                serialized = serializer.Serialize(item);
                storageManager.Add(key, serialized);
            }

            return(item);
        }
示例#20
0
        public ResilientHttpClient(HttpClient client, CircuitBreakerPolicy <HttpResponseMessage> circuitBreakerPolicy)
        {
            _client = client;
            _client.DefaultRequestHeaders.Accept.Clear();
            _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            //circuit breaker policy injected as defined in the Startup class
            _circuitBreakerPolicy = circuitBreakerPolicy;

            //Defining retry policy
            _retryPolicy = Policy.HandleResult <HttpResponseMessage>(x =>
            {
                var result = !x.IsSuccessStatusCode;
                return(result);
            })
                           .Or <TimeoutException>()
                           //Retry 3 times and for each retry wait for 3 seconds
                           .WaitAndRetry(3, sleepDuration => TimeSpan.FromSeconds(3));


            _fallbackCircuitBreakerPolicy = Policy <HttpResponseMessage>
                                            .Handle <BrokenCircuitException>()
                                            .Fallback(new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new StringContent("Please try again later[Circuit breaker is Open]")
            }
                                                      );


            _fallbackPolicy = Policy.HandleResult <HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.InternalServerError)
                              .Or <TimeoutRejectedException>()
                              .Fallback(new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new StringContent("Some error occured")
            });

            _timeoutPolicy = Policy.Timeout <HttpResponseMessage>(1);
        }
示例#21
0
        private PolicyWrap <string> BuildPolicy()
        {
            // max timeout policy, to stop the entire request because of the API is being TOOO slow
            var timeoutPolicy = Policy.Timeout(TimeSpan.FromSeconds(TimeoutFallback), TimeoutStrategy.Pessimistic, (context, span, task) =>
            {
                if (task.Status == TaskStatus.Running)
                {
                    _progress.Report(ProgressWithMessage($"Timeout policy called: call exceeded {span.TotalSeconds}s", Color.Magenta));
                }
            });

            // fallback policy, what to do when a timeout is occured
            FallbackPolicy <string> fallbackForAnyException = Policy <string>
                                                              .Handle <Exception>()
                                                              .Fallback(
                fallbackAction: () => "Please try again later [Fallback for any exception]",
                onFallback: e =>
            {
                _progress.Report(ProgressWithMessage("Fallback catches eventually failed with: " + e.Exception.Message, Color.Red));
            }
                );

            // wait and retry policy, when a call fails
            RetryPolicy waitAndRetryPolicy = Policy
                                             .Handle <Exception>()
                                             .WaitAndRetry(
                retryCount: 3,
                sleepDurationProvider: attempt => TimeSpan.FromSeconds(4), // Wait 4s between each try.
                onRetry: (exception, calculatedWaitDuration) =>            // Capture some info for logging!
            {
                // This is your new exception handler!
                // Tell the user what they've won!
                _progress.Report(ProgressWithMessage("Retry is starting.... Logging: " + exception.Message, Color.Yellow));
            });

            // Wrap the policies together (timeout check on every request)
            return(fallbackForAnyException.Wrap(waitAndRetryPolicy).Wrap(timeoutPolicy));
        }
        public static void Execute()
        {
            Console.WriteLine(MethodBase.GetCurrentMethod().DeclaringType.Name);
            Console.WriteLine("=======");
            // Let's call a web api service to make repeated requests to a server.
            // The service is programmed to fail after 3 requests in 5 seconds.

            var       client                          = new WebClient();
            int       eventualSuccesses               = 0;
            int       retries                         = 0;
            int       eventualFailuresDueToTimeout    = 0;
            int       eventualFailuresForOtherReasons = 0;
            Stopwatch watch = null;

            // Define our timeout policy: time out after 2 seconds.  We will use the pessimistic timeout strategy, which forces a timeout - even when the underlying delegate doesn't support it.
            var timeoutPolicy = Policy
                                .Timeout(TimeSpan.FromSeconds(2), TimeoutStrategy.Pessimistic);

            // Define our waitAndRetry policy: keep retrying with 4 second gaps.  This is (intentionally) too long: to demonstrate that the timeout policy will time out on this before waiting for the retry.
            RetryPolicy waitAndRetryPolicy = Policy
                                             .Handle <Exception>()
                                             .WaitAndRetryForever(
                attempt => TimeSpan.FromSeconds(4),
                (exception, calculatedWaitDuration) =>
            {
                ConsoleHelper.WriteLineInColor(".Log,then retry: " + exception.Message, ConsoleColor.Yellow);
                retries++;
            });

            // Define a fallback policy: provide a nice substitute message to the user, if we found the call was rejected due to the timeout policy.
            FallbackPolicy <String> fallbackForTimeout = Policy <String>
                                                         .Handle <TimeoutRejectedException>()
                                                         .Fallback(
                fallbackValue: /* Demonstrates fallback value syntax */ "Please try again later [Fallback for timeout]",
                onFallback: b =>
            {
                watch.Stop();
                ConsoleHelper.WriteInColor("Fallback catches failed with: " + b.Exception.Message, ConsoleColor.Red);
                ConsoleHelper.WriteLineInColor(" (after " + watch.ElapsedMilliseconds + "ms)", ConsoleColor.Red);
                eventualFailuresDueToTimeout++;
            }
                );

            // Define a fallback policy: provide a substitute string to the user, for any exception.
            FallbackPolicy <String> fallbackForAnyException = Policy <String>
                                                              .Handle <Exception>()
                                                              .Fallback(
                fallbackAction: /* Demonstrates fallback action/func syntax */ () => { return("Please try again later [Fallback for any exception]"); },
                onFallback: e =>
            {
                watch.Stop();
                ConsoleHelper.WriteInColor("Fallback catches eventually failed with: " + e.Exception.Message, ConsoleColor.Red);
                ConsoleHelper.WriteLineInColor(" (after " + watch.ElapsedMilliseconds + "ms)", ConsoleColor.Red);
                eventualFailuresForOtherReasons++;
            }
                );


            // Compared to previous demo08: here we use *instance* wrap syntax, to wrap all in one go.
            PolicyWrap <String> policyWrap = fallbackForAnyException.Wrap(fallbackForTimeout).Wrap(timeoutPolicy).Wrap(waitAndRetryPolicy).Wrap(waitAndRetryPolicy);

            int i = 0;

            while (!Console.KeyAvailable)
            {
                i++;
                watch = new Stopwatch();
                watch.Start();

                try
                {
                    // Manage the call according to the whole policy wrap.
                    string msg = policyWrap.Execute(() => client.DownloadString(Configuration.WEB_API_ROOT + "/api/values/" + i));

                    watch.Stop();

                    // Display the response message on the console
                    ConsoleHelper.WriteInColor("Response : " + msg, ConsoleColor.Green);
                    ConsoleHelper.WriteLineInColor(" (after " + watch.ElapsedMilliseconds + "ms)", ConsoleColor.Green);

                    eventualSuccesses++;
                }
                catch (Exception e) // try-catch not needed, now that we have a Fallback.Handle<Exception>.  It's only been left in to *demonstrate* it should never get hit.
                {
                    throw new InvalidOperationException("Should never arrive here.  Use of fallbackForAnyException should have provided nice fallback value for any exceptions.", e);
                }

                // Wait half second
                Thread.Sleep(500);
            }

            Console.WriteLine("");
            Console.WriteLine("Total requests made                     : " + i);
            Console.WriteLine("Requests which eventually succeeded     : " + eventualSuccesses);
            Console.WriteLine("Retries made to help achieve success    : " + retries);
            Console.WriteLine("Requests timed out by timeout policy    : " + eventualFailuresDueToTimeout);
            Console.WriteLine("Requests which failed after longer delay: " + eventualFailuresForOtherReasons);
        }
        public PollyServiceClient()
        {
            _client     = new HttpClient();
            _gatewayUri = _primaryUri;

            var circuitBreakerPolicy = Policy
                                       .Handle <Exception>()
                                       .CircuitBreakerAsync(
                exceptionsAllowedBeforeBreaking: 4,
                durationOfBreak: TimeSpan.FromSeconds(3),
                onBreak: (ex, breakDelay) =>
            {
                //Called when circuit first open
                //Setting the backupUri so calls now go to backup gateway
                _gatewayUri = _backupUri;
            },
                onReset: () =>
            {
                //Called when circuit is closed again.
                //Primary gateway is responding again, setting to primaryUri.
                _gatewayUri = _primaryUri;
            },
                onHalfOpen: () =>
            {
                //Called when the policy is going to check the original call to see if there are no exceptions.
                //Send the call to the primary gateway to see if it's operational again.
                _gatewayUri = _primaryUri;;
            }
                );

            var waitAndRetryPolicy = Policy
                                     .Handle <Exception>(e => !(e is BrokenCircuitException)) // Exception filtering!  We don't retry if the inner circuit-breaker judges the underlying system is out of commission!
                                     .WaitAndRetryForeverAsync(
                attempt => TimeSpan.FromMilliseconds(200),
                (exception, calculatedWaitDuration) =>
            {
                //Handle the exception here.
            });

            FallbackPolicy <String> fallbackForCircuitBreaker = Policy <String>
                                                                .Handle <BrokenCircuitException>()
                                                                .FallbackAsync(
                fallbackAction: /* Demonstrates fallback action/func syntax */ async ct =>
            {
                await Task.FromResult(true);

                //This is called after the circuit breaker is tripped
                //and the gatewayUri is changed to point to the backup
                //gateway.  This call runs on the backup gateway.
                return(await ClientWrapper());
            },
                onFallbackAsync: async e =>
            {
                await Task.FromResult(true);
            }
                );

            //Something really bad has happened.
            FallbackPolicy <String> fallbackForAnyException = Policy <String>
                                                              .Handle <Exception>()
                                                              .FallbackAsync(
                fallbackAction: /* Demonstrates fallback action/func syntax */ async ct =>
            {
                await Task.FromResult(true);
                return("Another exception occurred.");
            },
                onFallbackAsync: async e =>
            {
                await Task.FromResult(true);
            }
                );

            PolicyWrap myResilienceStrategy = Policy.Wrap(waitAndRetryPolicy, circuitBreakerPolicy);

            _policyWrap = fallbackForAnyException.WrapAsync(fallbackForCircuitBreaker.WrapAsync(myResilienceStrategy));
        }
示例#24
0
        private void ConfigurationChanged(PriusConfig config)
        {
            Action nullConfig = () =>
            {
                _groups = new Group[0];
            };

            if (config == null || config.Repositories == null)
            {
                nullConfig();
                return;
            }

            var repositoryConfiguration = config.Repositories.FirstOrDefault(r => string.Equals(r.Name, Name, StringComparison.InvariantCultureIgnoreCase));

            if (repositoryConfiguration == null)
            {
                nullConfig();
                return;
            }

            var fallbackPolicies = config.FallbackPolicies == null
                ? new Dictionary <string, FallbackPolicy>()
                : config.FallbackPolicies.ToDictionary(p => p.Name.ToLowerInvariant());

            var databases = config.Databases == null
                ? new Dictionary <string, Database>()
                : config.Databases.ToDictionary(s => s.Name.ToLowerInvariant());

            var storedProcedures = repositoryConfiguration.StoredProcedures == null
                ? new Dictionary <string, StoredProcedure>()
                : repositoryConfiguration.StoredProcedures.ToDictionary(s => s.Name.ToLowerInvariant());

            var groups = repositoryConfiguration.Clusters
                         .Where(cluster => cluster.Enabled)
                         .OrderBy(cluster => cluster.SequenceNumber)
                         .Select(cluster =>
            {
                if (!fallbackPolicies.TryGetValue(cluster.FallbackPolicyName.ToLowerInvariant(), out var fallbackPolicy))
                {
                    fallbackPolicy = new FallbackPolicy();
                }

                var servers = cluster.DatabaseNames
                              .Select(databaseName =>
                {
                    return(databases.TryGetValue(databaseName.ToLowerInvariant(), out var database)
                                ? database
                                : null);
                })
                              .Where(database => database != null && database.Enabled)
                              .OrderBy(database => database.SequenceNumber)
                              .Select(database => new Server(
                                          database.Name,
                                          database.ServerType,
                                          database.ConnectionString,
                                          database.StoredProcedures == null ? null : database.StoredProcedures.ToDictionary(p => p.Name.ToLower(), p => p.TimeoutSeconds),
                                          database.Role));

                return(new Group().Initialize
                       (
                           cluster.Name,
                           this,
                           fallbackPolicy.FailureWindowSeconds,
                           fallbackPolicy.AllowedFailurePercent / 100f,
                           fallbackPolicy.WarningFailurePercent / 100f,
                           fallbackPolicy.BackOffTime,
                           servers,
                           storedProcedures
                       ));
            });

            _groups = groups.ToArray();
        }
        public override async Task ExecuteAsync(CancellationToken cancellationToken, IProgress <DemoProgress> progress)
        {
            if (cancellationToken == null)
            {
                throw new ArgumentNullException(nameof(cancellationToken));
            }
            if (progress == null)
            {
                throw new ArgumentNullException(nameof(progress));
            }

            // Let's call a web api service to make repeated requests to a server.
            // The service is programmed to fail after 3 requests in 5 seconds.

            eventualSuccesses               = 0;
            retries                         = 0;
            eventualFailuresDueToTimeout    = 0;
            eventualFailuresForOtherReasons = 0;

            progress.Report(ProgressWithMessage(typeof(AsyncDemo09_Wrap_Fallback_Timeout_WaitAndRetry).Name));
            progress.Report(ProgressWithMessage("======"));
            progress.Report(ProgressWithMessage(String.Empty));

            Stopwatch watch = null;

            // Define our timeout policy: time out after 2 seconds.  We will use the pessimistic timeout strategy, which forces a timeout - even when the underlying delegate doesn't support it.
            var timeoutPolicy = Policy
                                .TimeoutAsync(TimeSpan.FromSeconds(2), TimeoutStrategy.Pessimistic);

            // Define our waitAndRetry policy: keep retrying with 4 second gaps.  This is (intentionally) too long: to demonstrate that the timeout policy will time out on this before waiting for the retry.
            var waitAndRetryPolicy = Policy
                                     .Handle <Exception>() // Exception filtering!  We don't retry if the inner circuit-breaker judges the underlying system is out of commission!
                                     .WaitAndRetryForeverAsync(
                attempt => TimeSpan.FromSeconds(4),
                (exception, calculatedWaitDuration) =>
            {
                progress.Report(ProgressWithMessage(".Log,then retry: " + exception.Message, Color.Yellow));
                retries++;
            });

            // Define a fallback policy: provide a nice substitute message to the user, if we found the call was rejected due to the timeout policy.
            FallbackPolicy <String> fallbackForTimeout = Policy <String>
                                                         .Handle <TimeoutRejectedException>()
                                                         .FallbackAsync(
                fallbackValue: /* Demonstrates fallback value syntax */ "Please try again later [Fallback for timeout]",
                onFallbackAsync: async b =>
            {
                await Task.FromResult(true);
                watch.Stop();
                progress.Report(ProgressWithMessage("Fallback catches failed with: " + b.Exception.Message + " (after " + watch.ElapsedMilliseconds + "ms)", Color.Red));
                eventualFailuresDueToTimeout++;
            }
                );

            // Define a fallback policy: provide a substitute string to the user, for any exception.
            FallbackPolicy <String> fallbackForAnyException = Policy <String>
                                                              .Handle <Exception>()
                                                              .FallbackAsync(
                fallbackAction: /* Demonstrates fallback action/func syntax */ async ct =>
            {
                await Task.FromResult(true);
                /* do something else async if desired */
                return("Please try again later [Fallback for any exception]");
            },
                onFallbackAsync: async e =>
            {
                await Task.FromResult(true);
                watch.Stop();
                progress.Report(ProgressWithMessage("Fallback catches eventually failed with: " + e.Exception.Message + " (after " + watch.ElapsedMilliseconds + "ms)", Color.Red));
                eventualFailuresForOtherReasons++;
            }
                );

            // Compared to previous demo08: here we use *instance* wrap syntax, to wrap all in one go.
            PolicyWrap <String> policyWrap = fallbackForAnyException.WrapAsync(fallbackForTimeout).WrapAsync(timeoutPolicy).WrapAsync(waitAndRetryPolicy);

            using (var client = new HttpClient())
            {
                totalRequests = 0;
                bool internalCancel = false;

                while (!internalCancel && !cancellationToken.IsCancellationRequested)
                {
                    totalRequests++;
                    watch = new Stopwatch();
                    watch.Start();

                    try
                    {
                        // Manage the call according to the whole policy wrap
                        string response = await policyWrap.ExecuteAsync(ct =>
                                                                        client.GetStringAsync(Configuration.WEB_API_ROOT + "/api/values/" + totalRequests), cancellationToken);

                        watch.Stop();

                        progress.Report(ProgressWithMessage("Response: " + response + "(after " + watch.ElapsedMilliseconds + "ms)", Color.Green));

                        eventualSuccesses++;
                    }
                    catch (Exception e) // try-catch not needed, now that we have a Fallback.Handle<Exception>.  It's only been left in to *demonstrate* it should never get hit.
                    {
                        throw new InvalidOperationException("Should never arrive here.  Use of fallbackForAnyException should have provided nice fallback value for any exceptions.", e);
                    }

                    // Wait half second
                    await Task.Delay(TimeSpan.FromSeconds(0.5), cancellationToken);

                    internalCancel = TerminateDemosByKeyPress && Console.KeyAvailable;
                }
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="T:EasyCaching.HybridCache.HybridCachingProvider"/> class.
        /// </summary>
        /// <param name="name">Name.</param>
        /// <param name="optionsAccs">Options accs.</param>
        /// <param name="factory">Providers factory</param>
        /// <param name="bus">Bus.</param>
        /// <param name="loggerFactory">Logger factory.</param>
        public HybridCachingProvider(
            string name
            , HybridCachingOptions optionsAccs
            , IEasyCachingProviderFactory factory
            , IEasyCachingBus bus          = null
            , ILoggerFactory loggerFactory = null
            )
        {
            ArgumentCheck.NotNull(factory, nameof(factory));

            this._name    = name;
            this._options = optionsAccs;

            ArgumentCheck.NotNullOrWhiteSpace(_options.TopicName, nameof(_options.TopicName));

            this._logger = loggerFactory?.CreateLogger <HybridCachingProvider>();

            // Here use the order to distinguish traditional provider
            var local = factory.GetCachingProvider(_options.LocalCacheProviderName);

            if (local.IsDistributedCache)
            {
                throw new NotFoundCachingProviderException("Can not found any local caching providers.");
            }
            else
            {
                this._localCache = local;
            }

            // Here use the order to distinguish traditional provider
            var distributed = factory.GetCachingProvider(_options.DistributedCacheProviderName);

            if (!distributed.IsDistributedCache)
            {
                throw new NotFoundCachingProviderException("Can not found any distributed caching providers.");
            }
            else
            {
                this._distributedCache = distributed;
            }

            this._bus = bus ?? NullEasyCachingBus.Instance;
            this._bus.Subscribe(_options.TopicName, OnMessage);

            this._cacheId = Guid.NewGuid().ToString("N");


            // policy

            retryAsyncPolicy = Policy.Handle <Exception>()
                               .WaitAndRetryAsync(this._options.BusRetryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt - 1)));

            retryPolicy = Policy.Handle <Exception>()
                          .WaitAndRetry(this._options.BusRetryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt - 1)));

            fallbackPolicy = Policy.Handle <Exception>().Fallback(() => { });

            fallbackAsyncPolicy = Policy.Handle <Exception>().FallbackAsync(ct =>
            {
                return(Task.CompletedTask);
            });

            _busSyncWrap  = Policy.Wrap(fallbackPolicy, retryPolicy);
            _busAsyncWrap = Policy.WrapAsync(fallbackAsyncPolicy, retryAsyncPolicy);
        }
        public static void Execute()
        {
            Console.WriteLine(MethodBase.GetCurrentMethod().DeclaringType.Name);
            Console.WriteLine("=======");
            // Let's call a web api service to make repeated requests to a server.
            // The service is programmed to fail after 3 requests in 5 seconds.

            var       client            = new WebClient();
            int       eventualSuccesses = 0;
            int       retries           = 0;
            int       eventualFailuresDueToCircuitBreaking = 0;
            int       eventualFailuresForOtherReasons      = 0;
            Stopwatch watch = null;

            // Define our waitAndRetry policy: keep retrying with 200ms gaps.
            RetryPolicy waitAndRetryPolicy = Policy
                                             .Handle <Exception>(e => !(e is BrokenCircuitException)) // Exception filtering!  We don't retry if the inner circuit-breaker judges the underlying system is out of commission!
                                             .WaitAndRetryForever(
                attempt => TimeSpan.FromMilliseconds(200),
                (exception, calculatedWaitDuration) =>
            {
                ConsoleHelper.WriteLineInColor(".Log,then retry: " + exception.Message, ConsoleColor.Yellow);
                retries++;
            });

            // Define our CircuitBreaker policy: Break if the action fails 4 times in a row.
            CircuitBreakerPolicy circuitBreakerPolicy = Policy
                                                        .Handle <Exception>()
                                                        .CircuitBreaker(
                exceptionsAllowedBeforeBreaking: 4,
                durationOfBreak: TimeSpan.FromSeconds(3),
                onBreak: (ex, breakDelay) =>
            {
                ConsoleHelper.WriteLineInColor(".Breaker logging: Breaking the circuit for " + breakDelay.TotalMilliseconds + "ms!", ConsoleColor.Magenta);
                ConsoleHelper.WriteLineInColor("..due to: " + ex.Message, ConsoleColor.Magenta);
            },
                onReset: () => ConsoleHelper.WriteLineInColor(".Breaker logging: Call ok! Closed the circuit again!", ConsoleColor.Magenta),
                onHalfOpen: () => ConsoleHelper.WriteLineInColor(".Breaker logging: Half-open: Next call is a trial!", ConsoleColor.Magenta)
                );


            // Define a fallback policy: provide a nice substitute message to the user, if we found the circuit was broken.
            FallbackPolicy <String> fallbackForCircuitBreaker = Policy <String>
                                                                .Handle <BrokenCircuitException>()
                                                                .Fallback(
                fallbackValue: /* Demonstrates fallback value syntax */ "Please try again later [Fallback for broken circuit]",
                onFallback: b =>
            {
                watch.Stop();
                ConsoleHelper.WriteInColor("Fallback catches failed with: " + b.Exception.Message, ConsoleColor.Red);
                ConsoleHelper.WriteLineInColor(" (after " + watch.ElapsedMilliseconds + "ms)", ConsoleColor.Red);
                eventualFailuresDueToCircuitBreaking++;
            }
                );

            // Define a fallback policy: provide a substitute string to the user, for any exception.
            FallbackPolicy <String> fallbackForAnyException = Policy <String>
                                                              .Handle <Exception>()
                                                              .Fallback(
                fallbackAction: /* Demonstrates fallback action/func syntax */ () => { return("Please try again later [Fallback for any exception]"); },
                onFallback: e =>
            {
                watch.Stop();
                ConsoleHelper.WriteInColor("Fallback catches eventually failed with: " + e.Exception.Message, ConsoleColor.Red);
                ConsoleHelper.WriteLineInColor(" (after " + watch.ElapsedMilliseconds + "ms)", ConsoleColor.Red);
                eventualFailuresForOtherReasons++;
            }
                );


            // As demo07: we combine the waitAndRetryPolicy and circuitBreakerPolicy into a PolicyWrap, using the *static* Policy.Wrap syntax.
            PolicyWrap myResilienceStrategy = Policy.Wrap(waitAndRetryPolicy, circuitBreakerPolicy);

            // Added in demo08: we wrap the two fallback policies onto the front of the existing wrap too.  Demonstrates the *instance* wrap syntax. And the fact that the PolicyWrap myResilienceStrategy from above is just another Policy, which can be onward-wrapped too.
            // With this pattern, you can build an overall resilience strategy programmatically, reusing some common parts (eg PolicyWrap myResilienceStrategy) but varying other parts (eg Fallback) individually for different calls.
            PolicyWrap <String> policyWrap = fallbackForAnyException.Wrap(fallbackForCircuitBreaker.Wrap(myResilienceStrategy));
            // For info: Equivalent to: PolicyWrap<String> policyWrap = Policy.Wrap(fallbackForAnyException, fallbackForCircuitBreaker, waitAndRetryPolicy, circuitBreakerPolicy);

            int i = 0;

            // Do the following until a key is pressed
            while (!Console.KeyAvailable)
            {
                i++;
                watch = new Stopwatch();
                watch.Start();

                try
                {
                    // Manage the call according to the whole policy wrap.
                    string msg = policyWrap.Execute(() => client.DownloadString(Configuration.WEB_API_ROOT + "/api/values/" + i));

                    watch.Stop();

                    // Display the response message on the console
                    ConsoleHelper.WriteInColor("Response : " + msg, ConsoleColor.Green);
                    ConsoleHelper.WriteLineInColor(" (after " + watch.ElapsedMilliseconds + "ms)", ConsoleColor.Green);

                    eventualSuccesses++;
                }
                catch (Exception e) // try-catch not needed, now that we have a Fallback.Handle<Exception>.  It's only been left in to *demonstrate* it should never get hit.
                {
                    throw new InvalidOperationException("Should never arrive here.  Use of fallbackForAnyException should have provided nice fallback value for any exceptions.", e);
                }

                // Wait half second
                Thread.Sleep(500);
            }

            Console.WriteLine("");
            Console.WriteLine("Total requests made                     : " + i);
            Console.WriteLine("Requests which eventually succeeded     : " + eventualSuccesses);
            Console.WriteLine("Retries made to help achieve success    : " + retries);
            Console.WriteLine("Requests failed early by broken circuit : " + eventualFailuresDueToCircuitBreaking);
            Console.WriteLine("Requests which failed after longer delay: " + eventualFailuresForOtherReasons);
        }
示例#28
0
        public override async Task ExecuteAsync(CancellationToken cancellationToken, IProgress <DemoProgress> progress)
        {
            if (cancellationToken == null)
            {
                throw new ArgumentNullException(nameof(cancellationToken));
            }
            if (progress == null)
            {
                throw new ArgumentNullException(nameof(progress));
            }

            // Let's call a web api service to make repeated requests to a server.
            // The service is programmed to fail after 3 requests in 5 seconds.

            eventualSuccesses = 0;
            retries           = 0;
            eventualFailuresDueToCircuitBreaking = 0;
            eventualFailuresForOtherReasons      = 0;

            progress.Report(ProgressWithMessage(typeof(AsyncDemo08_Wrap_Fallback_WaitAndRetry_CircuitBreaker).Name));
            progress.Report(ProgressWithMessage("======"));
            progress.Report(ProgressWithMessage(String.Empty));

            Stopwatch watch = null;

            // Define our waitAndRetry policy: keep retrying with 200ms gaps.
            var waitAndRetryPolicy = Policy
                                     .Handle <Exception>(e => !(e is BrokenCircuitException)) // Exception filtering!  We don't retry if the inner circuit-breaker judges the underlying system is out of commission!
                                     .WaitAndRetryForeverAsync(
                attempt => TimeSpan.FromMilliseconds(200),
                (exception, calculatedWaitDuration) =>
            {
                progress.Report(ProgressWithMessage(".Log,then retry: " + exception.Message, Color.Yellow));
                retries++;
            });

            // Define our CircuitBreaker policy: Break if the action fails 4 times in a row.
            var circuitBreakerPolicy = Policy
                                       .Handle <Exception>()
                                       .CircuitBreakerAsync(
                exceptionsAllowedBeforeBreaking: 4,
                durationOfBreak: TimeSpan.FromSeconds(3),
                onBreak: (ex, breakDelay) =>
            {
                progress.Report(ProgressWithMessage(".Breaker logging: Breaking the circuit for " + breakDelay.TotalMilliseconds + "ms!", Color.Magenta));
                progress.Report(ProgressWithMessage("..due to: " + ex.Message, Color.Magenta));
            },
                onReset: () => progress.Report(ProgressWithMessage(".Breaker logging: Call ok! Closed the circuit again!", Color.Magenta)),
                onHalfOpen: () => progress.Report(ProgressWithMessage(".Breaker logging: Half-open: Next call is a trial!", Color.Magenta))
                );

            // Define a fallback policy: provide a nice substitute message to the user, if we found the circuit was broken.
            FallbackPolicy <String> fallbackForCircuitBreaker = Policy <String>
                                                                .Handle <BrokenCircuitException>()
                                                                .FallbackAsync(
                fallbackValue: /* Demonstrates fallback value syntax */ "Please try again later [message substituted by fallback policy]",
                onFallbackAsync: async b =>
            {
                await Task.FromResult(true);
                watch.Stop();
                progress.Report(ProgressWithMessage("Fallback catches failed with: " + b.Exception.Message
                                                    + " (after " + watch.ElapsedMilliseconds + "ms)", Color.Red));
                eventualFailuresDueToCircuitBreaking++;
            }
                );

            // Define a fallback policy: provide a substitute string to the user, for any exception.
            FallbackPolicy <String> fallbackForAnyException = Policy <String>
                                                              .Handle <Exception>()
                                                              .FallbackAsync(
                fallbackAction: /* Demonstrates fallback action/func syntax */ async ct =>
            {
                await Task.FromResult(true);
                /* do something else async if desired */
                return("Please try again later [Fallback for any exception]");
            },
                onFallbackAsync: async e =>
            {
                await Task.FromResult(true);
                watch.Stop();
                progress.Report(ProgressWithMessage("Fallback catches eventually failed with: " + e.Exception.Message
                                                    + " (after " + watch.ElapsedMilliseconds + "ms)", Color.Red));
                eventualFailuresForOtherReasons++;
            }
                );

            // As demo07: we combine the waitAndRetryPolicy and circuitBreakerPolicy into a PolicyWrap, using the *static* Policy.Wrap syntax.
            PolicyWrap myResilienceStrategy = Policy.WrapAsync(waitAndRetryPolicy, circuitBreakerPolicy);

            // Added in demo08: we wrap the two fallback policies onto the front of the existing wrap too.  Demonstrates the *instance* wrap syntax. And the fact that the PolicyWrap myResilienceStrategy from above is just another Policy, which can be onward-wrapped too.
            // With this pattern, you can build an overall resilience strategy programmatically, reusing some common parts (eg PolicyWrap myResilienceStrategy) but varying other parts (eg Fallback) individually for different calls.
            PolicyWrap <String> policyWrap = fallbackForAnyException.WrapAsync(fallbackForCircuitBreaker.WrapAsync(myResilienceStrategy));

            // For info: Equivalent to: PolicyWrap<String> policyWrap = Policy.WrapAsync(fallbackForAnyException, fallbackForCircuitBreaker, waitAndRetryPolicy, circuitBreakerPolicy);

            totalRequests = 0;

            using (var client = new HttpClient())
            {
                bool internalCancel = false;
                // Do the following until a key is pressed
                while (!internalCancel && !cancellationToken.IsCancellationRequested)
                {
                    totalRequests++;
                    watch = new Stopwatch();
                    watch.Start();

                    try
                    {
                        // Manage the call according to the whole policy wrap
                        string response = await policyWrap.ExecuteAsync(ct =>
                                                                        client.GetStringAsync(Configuration.WEB_API_ROOT + "/api/values/" + totalRequests), cancellationToken);

                        watch.Stop();

                        // Display the response message on the console
                        progress.Report(ProgressWithMessage("Response : " + response + " (after " + watch.ElapsedMilliseconds + "ms)", Color.Green));

                        eventualSuccesses++;
                    }
                    catch (Exception e) // try-catch not needed, now that we have a Fallback.Handle<Exception>.  It's only been left in to *demonstrate* it should never get hit.
                    {
                        throw new InvalidOperationException("Should never arrive here.  Use of fallbackForAnyException should have provided nice fallback value for any exceptions.", e);
                    }

                    // Wait half second
                    await Task.Delay(TimeSpan.FromSeconds(0.5), cancellationToken);

                    internalCancel = TerminateDemosByKeyPress && Console.KeyAvailable;
                }
            }
        }
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

            //Polly içerisinde reactive ve proactive olarak ayrılmıs 2 tur policysi vardır.
            //reactive policyler => retry ve circuit breaker gibi
            //proactive policyler ise => timeout policy, bulkhead, caching... yüksek verimli sistemler için esnekligi arttırırlar.
            //Policyler sıra ile uygulanır.

            var registry = services.AddPolicyRegistry();

            #region RetryPolicy
            //HandleTransientHttpError :
            //varsayılan olarak alınabilecek errorlar tanımlıdır. HttpRequestException, HTTP 5xx (sunucu hataları), HTTP 408 (istek zaman asımı) gibi hatalar alındıgında retry mekanizması calisir.
            //Ancak bu hataların dısında da aldıgınız hatalarda retry mekanizmasının calismasını isteyebilirsiniz. O zaman policy e OrResult eklemesi yaparsınız.

            //Her bir retry da yapılmasını istediginiz bir sey varsa OnRetry ve OnRetryAsync içerisine yazabilirsiniz. Loglama vs.
            //Retry mekanizmasının iyi insaa edilmesi gerekir. Zaten cevap vermeyen bir sisteme tekrarlı denemeler yapmak ilave yuk getirebilir.
            //cevap veremeyen bir sistemi zorlamak yerine hızlı basarısızlık genellikle daha iyi bir kullanıcı deneyimidir. Circuitbreaker sistemi belli bir sure kapalı tutabilir ve ardından tekrar acarak isteklere cevap verilip verilmeyecegini dener.

            registry.Add("retryrules", HttpPolicyExtensions.HandleTransientHttpError() // varsayılanlar alındıgında
                         .OrResult(response => (int)response.StatusCode == 429)        // 429 alındıgında
                         .Or <TimeoutRejectedException>()                              // timeout policye takılıp ilgili exception calistiginda retry mekanizması devreye girer.
                         .WaitAndRetryAsync(new[]
            {
                TimeSpan.FromSeconds(3), // ilk denemeyi yapmadan evvel 3 saniye bekler
                TimeSpan.FromSeconds(8)  // ikinci denemeyi yapmadan evvel 8 saniye bekler
            },
                                            onRetryAsync: async(outcome, timespan, retryAttempt, context) =>
            {
                System.Diagnostics.Debug.WriteLine(string.Format("deneme {0}", DateTime.Now.ToString()));
            }
                                            ));

            //registry.Add("retryrules", HttpPolicyExtensions.HandleTransientHttpError() // varsayılanlar alındıgında
            //    .OrResult(response => (int)response.StatusCode == 429) // 429 alındıgında
            //    .Or<TimeoutRejectedException>() // timeout policye takılıp ilgili exception calistiginda retry mekanizması devreye girer.
            //    .WaitAndRetry(new[]
            //{
            //    TimeSpan.FromSeconds(3), // ilk denemeyi yapmadan evvel 3 saniye bekler
            //    TimeSpan.FromSeconds(8)  // ikinci denemeyi yapmadan evvel 8 saniye bekler
            //},
            //onRetry: (outcome, timespan, retryAttempt, context) =>
            //{
            //    System.Diagnostics.Debug.WriteLine(string.Format("deneme {0}", DateTime.Now.ToString()));
            //}

            //));

            #endregion

            #region CircuitBreaker
            //CircuitBreaker :
            //    failureThreshold: 0.5, (0 ile 1 arasında deger alır. arıza oranı olarak adlandırabiliriz. işlenen isteklerin basarisizlikla sonuclanma oranı %50 ve daha fazla ise sistem kesilir. )
            //    samplingDuration: TimeSpan.FromSeconds(5), // bu sure zarfında gerceklesen işlemler metriclerde kullanılır. daha eskisi kullanılmaz. 5 sanyedeki degerlere bakılır ve yuzde 50 basarisizlik varsa sistem kırılır. bu sure ne kadar uzun olursa o kadar duyarlılık azalır. dusuk olmasında fayda var. izin verilen min deger 20 miliseconds
            //    minimumThroughput: 20, // istatistik için gerekli olan cagrı sayısı. bu sayıya ulastıktan sonra metricler kullanılır ve devre kırılmayı dusunmeye baslar. izin verilen min deger 2 dir.
            //    durationOfBreak: TimeSpan.FromSeconds(30)

            //Advanced Kullanım
            registry.Add("circuitbreakerrules", HttpPolicyExtensions.HandleTransientHttpError()
                         .OrResult(response => (int)response.StatusCode == 429)
                         .Or <TimeoutRejectedException>()
                         .AdvancedCircuitBreakerAsync(
                             failureThreshold: 0.5,
                             samplingDuration: TimeSpan.FromSeconds(5),
                             minimumThroughput: 6,
                             durationOfBreak: TimeSpan.FromSeconds(120)
                             ));


            //var circuitbreakerPolicy = HttpPolicyExtensions.HandleTransientHttpError()
            //   .OrResult(response => (int)response.StatusCode == 429)
            //   .Or<TimeoutRejectedException>()
            //   .CircuitBreakerAsync(handledEventsAllowedBeforeBreaking: 5, durationOfBreak: TimeSpan.FromSeconds(30)
            //   );
            //registry.Add("circuitbreakerrules", circuitbreakerPolicy);


            #endregion

            #region TimeOutPolicy
            var timeoutPolicy = Policy.TimeoutAsync <HttpResponseMessage>(2);
            registry.Add("timeoutrules", timeoutPolicy); // Belirtilen surede response gelmez ise TimeoutRejectedException throw eder.
            #endregion

            #region Fallback

            FallbackPolicy <HttpResponseMessage> fallbackForCircuitBreaker = Policy <HttpResponseMessage>
                                                                             .Handle <TimeoutRejectedException>()
                                                                             .Or <BrokenCircuitException>()
                                                                             .FallbackAsync(FallbackStudent());


            registry.Add("fallbackrules", fallbackForCircuitBreaker);
            #endregion

            services.AddHttpClient(ClientNames.LocalClient, client =>
            {
                client.BaseAddress = new Uri("http://localhost:1157/api/");
                client.Timeout     = TimeSpan.FromSeconds(2);
            })
            .AddPolicyHandlerFromRegistry("fallbackrules")
            .AddPolicyHandlerFromRegistry("timeoutrules")
            //.AddPolicyHandlerFromRegistry("retryrules")
            .AddPolicyHandlerFromRegistry("circuitbreakerrules")
            ;
        }
示例#30
0
        private void ConfigurationChanged(PriusConfig config)
        {
            Action nullConfig = () =>
                {
                    _groups = new Group[0];
                };

            if (config == null || config.Repositories == null)
            {
                nullConfig();
                return;
            }

            var repositoryConfiguration = config.Repositories.FirstOrDefault(r => string.Equals(r.Name, Name, StringComparison.InvariantCultureIgnoreCase));
            if (repositoryConfiguration == null)
            {
                nullConfig();
                return;
            }

            var fallbackPolicies = config.FallbackPolicies == null
                ? new Dictionary<string, FallbackPolicy>()
                : config.FallbackPolicies.ToDictionary(p => p.Name);

            var databases = config.Databases == null
                ? new Dictionary<string, Database>()
                : config.Databases.ToDictionary(s => s.Name);

            var groups = repositoryConfiguration.Clusters
                .Where(cluster => cluster.Enabled)
                .OrderBy(cluster => cluster.SequenceNumber)
                .Select(cluster =>
                {
                    FallbackPolicy fallbackPolicy;
                    if (!fallbackPolicies.TryGetValue(cluster.FallbackPolicyName, out fallbackPolicy))
                        fallbackPolicy = new FallbackPolicy();

                    var servers = cluster.DatabaseNames
                        .Select(databaseName =>
                        {
                            Database database;
                            return databases.TryGetValue(databaseName, out database)
                                ? database
                                : null;
                        })
                        .Where(database => database != null && database.Enabled)
                        .OrderBy(database => database.SequenceNumber)
                        .Select(database => new Server(
                            database.ServerType,
                            database.ConnectionString,
                            database.StoredProcedures == null ? null : database.StoredProcedures.ToDictionary(p => p.Name.ToLower(), p => p.TimeoutSeconds)));

                    return new Group().Initialize
                        (
                            this,
                            fallbackPolicy.FailureWindowSeconds,
                            fallbackPolicy.AllowedFailurePercent / 100f,
                            fallbackPolicy.WarningFailurePercent / 100f,
                            fallbackPolicy.BackOffTime,
                            servers
                        );
                });
            _groups = groups.ToArray();
        }
示例#31
0
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            Log.Logger = new LoggerConfiguration()
                         .WriteTo.Console()
                         .WriteTo.File("log-.txt", rollingInterval: RollingInterval.Day)
                         .CreateLogger();

            _circuitBreakerPolicy = Policy.Handle <HttpRequestException>()
                                    .CircuitBreaker(
                // number of exceptions before breaking circuit
                5,
                // time circuit opened before retry
                TimeSpan.FromMinutes(1),
                (exception, duration) =>
            {
                // on circuit opened
                Log.Information("Circuit breaker opened");
            },
                () =>
            {
                // on circuit closed
                Log.Information("Circuit breaker reset");
            });



            _retryPolicy = Policy.Handle <HttpRequestException>()
                           .WaitAndRetry(
                // number of retries
                4,
                // exponential backofff
                retryAttempt => TimeSpan.FromSeconds(retryAttempt),
                // on retry
                (exception, timeSpan, retryCount, context) =>
            {
                var msg = $"Retry {retryCount} implemented with Polly's RetryPolicy " +
                          $"of {context.PolicyKey} " +
                          $"at {context.ExecutionKey}";
                Log.Warning(msg);
            });

            // Define a fallback policy: provide a nice substitute message to the user, if we found the circuit was broken.
            FallbackPolicy <UserPayload> fallbackForCircuitBreaker = Policy <UserPayload>
                                                                     .Handle <BrokenCircuitException>()
                                                                     .Fallback(
                fallbackValue: new UserPayload {
                Users = null, ErrorMessage = "Please try again later [Fallback for broken circuit]"
            },
                onFallback: b =>
            {
                Log.Information("Fallback catches failed with: " + b.Exception.Message, ConsoleColor.Red);
            }
                );

            // Define a fallback policy: provide a substitute string to the user, for any exception.
            FallbackPolicy <UserPayload> fallbackForAnyException = Policy <UserPayload>
                                                                   .Handle <Exception>()
                                                                   .Fallback(
                fallbackAction: /* Demonstrates fallback action/func syntax */ () => { return(new UserPayload {
                    Users = null, ErrorMessage = "Please try again later [Fallback for any exception]"
                }); },
                onFallback: e =>
            {
                Log.Information("Fallback catches failed with: " + e.Exception.Message, ConsoleColor.DarkMagenta);
            }
                );

            PolicyWrap myResilienceStrategy     = Policy.Wrap(_retryPolicy, _circuitBreakerPolicy);
            PolicyWrap <UserPayload> policyWrap = fallbackForAnyException.Wrap(fallbackForCircuitBreaker.Wrap(myResilienceStrategy));

            LoopCalls(policyWrap);
        }