Ejemplo n.º 1
0
        public NameService()
        {
            timeoutPolicy  = Policy.Timeout(2, TimeoutStrategy.Pessimistic);
            fallbackPolicy = Policy <string>
                             .Handle <TimeoutRejectedException>()
                             .Fallback(fallbackMessage);

            wrapPolicy = fallbackPolicy.Wrap(timeoutPolicy);

            breaker = Policy
                      .Handle <Exception>()
                      .CircuitBreakerAsync(2, TimeSpan.FromMinutes(1),
                                           (exception, timeout) =>
            {
                Console.WriteLine("================================= I broke =================================");
                return;
            },
                                           () => Console.WriteLine("I reset"));

            fallbackForCircuitBreaker = Policy <string>
                                        .Handle <BrokenCircuitException>()
                                        .FallbackAsync("Service unvailable at the moment [broken circuit]");

            fallbackForAnyException = Policy <string>
                                      .Handle <Exception>()
                                      .FallbackAsync(fallbackMessage);

            breakerWrap = fallbackForAnyException.WrapAsync(fallbackForCircuitBreaker.WrapAsync(breaker));
        }
        public override void Execute(CancellationToken cancellationToken, IProgress <DemoProgress> progress)
        {
            Init(progress);

            var timeoutPolicy = Policy.Timeout(TimeSpan.FromSeconds(2), TimeoutStrategy.Pessimistic, (context, span, task) =>
            {
                if (task.Status == TaskStatus.Running)
                {
                    progress.Report(ProgressWithMessage($"Timeout policy called: call exceeded {span.TotalSeconds}s", Color.Magenta));
                }
            });

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

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

            // Wrap the policies (timeout check on every request)
            var policyWrap = fallbackForAnyException.Wrap(waitAndRetryPolicy).Wrap(timeoutPolicy);

            using (var client = new WebClient())
            {
                _totalRequests = 0;
                try
                {
                    // Manage the call according to the whole policy wrap.
                    progress.Report(ProgressWithMessage("Start polywrap"));
                    string response = policyWrap.Execute(ct => client.DownloadString(Configuration.WEB_API_ROOT + "/api/speed/veryslow"), cancellationToken);
                    progress.Report(ProgressWithMessage("Response: " + response, Color.Green));
                    progress.Report(ProgressWithMessage("==============================================="));

                    _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);
                }
            }
        }
Ejemplo n.º 3
0
        static void Wrap()
        {
            bool check = false;

            RetryPolicy waitAndRetryPolicy = Policy
                                             .Handle <Exception>()
                                             .Retry(6,
                                                    onRetry: (exception, retryCount) =>
            {
                Console.WriteLine($"====Retry===== : 呼叫 API 異常, 進行第 {retryCount} 次重試");
                if (retryCount == 5)
                {
                    check = true;
                }
            });

            TimeoutPolicy timeoutPolicys = Policy
                                           .Timeout(TimeSpan.FromMilliseconds(1000), TimeoutStrategy.Pessimistic,
                                                    onTimeout: (context, timespan, task) =>
            {
                Console.WriteLine($"====TimeOut===== : execution timed out after {timespan} seconds.");
            });


            FallbackPolicy <String> fallbackForAnyException = Policy <String>
                                                              .Handle <Exception>()
                                                              .Fallback(
                fallbackAction: () => { Console.WriteLine("999999999"); return("123"); },
                onFallback: e => { Console.WriteLine($"[Polly fallback] : 重試失敗, say goodbye"); }
                );

            CircuitBreakerPolicy circuitPolicy = Policy
                                                 .Handle <Exception>()
                                                 .CircuitBreaker(3, TimeSpan.FromSeconds(0), (ex, ts) =>
            {
                Console.WriteLine($"====CircuitBreaker [OnBreak]=====  ts = {ts.Seconds}s ,ex.message = {ex.Message}");
            }, () =>
            {
                Console.WriteLine("AService OnReset");
            });

            try
            {
                PolicyWrap <String> policyWrap = fallbackForAnyException
                                                 .Wrap(waitAndRetryPolicy)
                                                 .Wrap(circuitPolicy)
                                                 .Wrap(timeoutPolicys);
                policyWrap.Execute(() => doMockHTTPRequest(check));
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }
Ejemplo n.º 4
0
        //Wrap function body in Retry and Circuit breaker policies
        public HttpResponseMessage ExecuteWithRetryandCircuitBreaker(string uri, Func <HttpResponseMessage> func)
        {
            //      PolicyWrap<HttpResponseMessage> resiliencePolicyWrap = Policy.Wrap(_retryPolicy, _circuitBreakerPolicy);
            //    PolicyWrap<HttpResponseMessage> fallbackPolicyWrap = _fallbackForAnyExceptionPolicy.Wrap(resiliencePolicyWrap);
            //  var res= fallbackPolicyWrap.Execute(() => func());
            // var res = _fallbackPolicy.Execute(() =>_retryPolicy.Wrap(_circuitBreakerPolicy).Execute(() => func()));

            PolicyWrap <HttpResponseMessage> resiliencePolicyWrap = Policy.Wrap(_timeoutPolicy, _retryPolicy, _circuitBreakerPolicy);

            PolicyWrap <HttpResponseMessage> fallbackPolicyWrap = _fallbackPolicy.Wrap(_fallbackCircuitBreakerPolicy.Wrap(resiliencePolicyWrap));

            var res = fallbackPolicyWrap.Execute(() => func());

            return(res);
            //var res = _fallbackPolicy.Execute(() => _retryPolicy.Execute(() => func()));
            //return res;
        }
Ejemplo n.º 5
0
        private static PolicyWrap <List <TestUser> > CreateWaitPolicy()
        {
            var fallBackValue = new List <TestUser>();

            fallBackValue.Add(new TestUser {
                Username = "******", Password = "******", IsActive = true
            });
            int retries = 0;
            // Define our timeout policy: time out after 50 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(50), 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) =>
            {
                Console.WriteLine(".Log,then retry: " + exception.Message);
                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 <List <TestUser> > fallbackForTimeout = Policy <List <TestUser> >
                                                                   .Handle <TimeoutRejectedException>()
                                                                   .Fallback(
                fallbackValue: fallBackValue,
                onFallback: b =>
            {
                //Handle Exception information...
                Console.WriteLine(b.Exception.Message);
                return;
            }
                );


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

            return(policyWrap);
        }
Ejemplo n.º 6
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       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);
        }
        public override void Execute(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(Demo09_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
                                .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) =>
            {
                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>()
                                                         .Fallback(
                fallbackValue: /* Demonstrates fallback value syntax */ "Please try again later [Fallback for timeout]",
                onFallback: b =>
            {
                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>()
                                                              .Fallback(
                fallbackAction: /* Demonstrates fallback action/func syntax */ () => { return("Please try again later [Fallback for any exception]"); },
                onFallback: e =>
            {
                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.Wrap(fallbackForTimeout).Wrap(timeoutPolicy).Wrap(waitAndRetryPolicy);

            using (var client = new WebClient())
            {
                bool internalCancel = false;
                totalRequests = 0;
                while (!internalCancel && !cancellationToken.IsCancellationRequested)
                {
                    totalRequests++;
                    watch = new Stopwatch();
                    watch.Start();

                    try
                    {
                        // Manage the call according to the whole policy wrap.
                        string response = policyWrap.Execute(ct => client.DownloadString(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
                    Thread.Sleep(500);

                    internalCancel = TerminateDemosByKeyPress && Console.KeyAvailable;
                }
            }
        }
Ejemplo n.º 9
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);
        }
        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 override void Execute(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(Demo08_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.
            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) =>
            {
                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.
            CircuitBreakerPolicy circuitBreakerPolicy = Policy
                                                        .Handle <Exception>()
                                                        .CircuitBreaker(
                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>()
                                                                .Fallback(
                fallbackValue: /* Demonstrates fallback value syntax */ "Please try again later [message substituted by fallback policy]",
                onFallback: b =>
            {
                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>()
                                                              .Fallback(
                fallbackAction: /* Demonstrates fallback action/func syntax */ () => { return("Please try again later [Fallback for any exception]"); },
                onFallback: e =>
            {
                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.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);

            using (var client = new WebClient())
            {
                bool internalCancel = false;
                totalRequests = 0;
                // 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 =
                            policyWrap.Execute(ct => client.DownloadString(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
                    Thread.Sleep(500);

                    internalCancel = TerminateDemosByKeyPress && Console.KeyAvailable;
                }
            }
        }
Ejemplo n.º 12
0
        public T Execute<T>(Func<T> operation, Func<T> openStateOperation)
        {
            // Define our waitAndRetry policy: keep retrying with n ms 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(SiteSettings.Instance.SleepDurationsMilliseconds),
                    (exception, calculatedWaitDuration) =>
                    {
                        _log.Error(".Log, then retry: ", exception);
                    });

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

            // Define a fallback policy: provide a secondary services or substitute result to the user, for any exception.
            FallbackPolicy<T> fallbackForAnyException = Policy<T>
                .Handle<Exception>()
                .Fallback(
                    fallbackAction: openStateOperation,
                    onFallback: e =>
                    {
                        _log.Error($"Fallback catches eventually failed with: {e.Exception.Message}");
                    }
                );

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

            // We wrap the two fallback policies onto the front of the existing wrap too. 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<T> policyWrap = fallbackForAnyException.Wrap(myResilienceStrategy);

            try
            {
                // Manage the call according to the whole policy wrap.
                var response =
                    policyWrap.Execute(operation);
                return response;

            }
            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.
            {
                _log.Error("Should never arrive here.  Use of fallbackForAnyException should have provided nice fallback value for any exceptions.", e);

                return default(T);
            }
        }
        public override void Execute(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(Demo09_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
                                .Timeout(TimeSpan.FromSeconds(2), TimeoutStrategy.Pessimistic,
                                         // This use of onTimeout demonstrates the point about capturing walked-away-from Tasks with TimeoutStrategy.Pessimistic discussed in the Polly wiki, here: https://github.com/App-vNext/Polly/wiki/Timeout#pessimistic-timeout-1
                                         onTimeout: (ctx, span, abandonedTask) =>
            {
                {
                    abandonedTask.ContinueWith(t =>
                    {
                        // ContinueWith important!: the abandoned task may very well still be executing, when the caller times out on waiting for it!

                        if (t.IsFaulted)
                        {
                            progress.Report(ProgressWithMessage(".The task previously walked-away-from now terminated with exception: " + t.Exception.Message,
                                                                Color.Yellow));
                        }
                        else if (t.IsCanceled)
                        {
                            // (If the executed delegates do not honour cancellation, this IsCanceled branch may never be hit.  It can be good practice however to include, in case a Policy configured with TimeoutStrategy.Pessimistic is used to execute a delegate honouring cancellation.)
                            progress.Report(ProgressWithMessage(".The task previously walked-away-from now was canceled.", Color.Yellow));
                        }
                        else
                        {
                            // extra logic (if desired) for tasks which complete, despite the caller having 'walked away' earlier due to timeout.
                            progress.Report(ProgressWithMessage(".The task previously walked-away-from now eventually completed.", Color.Yellow));
                        }
                    });
                }
            }
                                         );

            // 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) =>
            {
                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>()
                                                         .Fallback(
                fallbackValue: /* Demonstrates fallback value syntax */ "Please try again later [Fallback for timeout]",
                onFallback: b =>
            {
                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>()
                                                              .Fallback(
                fallbackAction: /* Demonstrates fallback action/func syntax */ () => { return("Please try again later [Fallback for any exception]"); },
                onFallback: e =>
            {
                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.Wrap(fallbackForTimeout).Wrap(timeoutPolicy).Wrap(waitAndRetryPolicy);

            using (var client = new WebClient())
            {
                bool internalCancel = false;
                totalRequests = 0;
                while (!internalCancel && !cancellationToken.IsCancellationRequested)
                {
                    totalRequests++;
                    watch = new Stopwatch();
                    watch.Start();

                    try
                    {
                        // Manage the call according to the whole policy wrap.
                        string response = policyWrap.Execute(ct => client.DownloadString(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
                    Thread.Sleep(500);

                    internalCancel = TerminateDemosByKeyPress && Console.KeyAvailable;
                }
            }
        }