public static async Task ExecuteAsync(CancellationToken cancellationToken) { Console.WriteLine(typeof(AsyncDemo01_RetryNTimes).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 HttpClient(); int eventualSuccesses = 0; int retries = 0; int eventualFailures = 0; // Define our policy: var policy = Policy.Handle <Exception>().RetryAsync(3, (exception, attempt) => { // This is your new exception handler! // Tell the user what they've won! ConsoleHelper.WriteLineInColor("Policy logging: " + exception.Message, ConsoleColor.Yellow); retries++; }); int i = 0; // Do the following until a key is pressed while (!Console.KeyAvailable && !cancellationToken.IsCancellationRequested) { i++; try { // Retry the following call according to the policy - 3 times. await policy.ExecuteAsync(async() => { // This code is executed within the Policy // Make a request and get a response string msg = await client.GetStringAsync(Configuration.WEB_API_ROOT + "/api/values/" + i); // Display the response message on the console ConsoleHelper.WriteLineInColor("Response : " + msg, ConsoleColor.Green); eventualSuccesses++; }); } catch (Exception e) { ConsoleHelper.WriteLineInColor("Request " + i + " eventually failed with: " + e.Message, ConsoleColor.Red); eventualFailures++; } // Wait half second await Task.Delay(TimeSpan.FromSeconds(0.5), cancellationToken); } 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 which eventually failed : " + eventualFailures); }
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 eventualFailures = 0; // Define our policy: var policy = Policy.Handle <Exception>().Retry(3, (exception, attempt) => { // This is your new exception handler! // Tell the user what they've won! ConsoleHelper.WriteLineInColor("Policy logging: " + exception.Message, ConsoleColor.Yellow); retries++; }); int i = 0; // Do the following until a key is pressed while (!Console.KeyAvailable) { i++; try { // Retry the following call according to the policy - 3 times. policy.Execute(() => { // This code is executed within the Policy // Make a request and get a response var msg = client.DownloadString(Configuration.WEB_API_ROOT + "/api/values/" + i.ToString()); // Display the response message on the console ConsoleHelper.WriteLineInColor("Response : " + msg, ConsoleColor.Green); eventualSuccesses++; }); } catch (Exception e) { ConsoleHelper.WriteLineInColor("Request " + i + " eventually failed with: " + e.Message, ConsoleColor.Red); eventualFailures++; } // 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 which eventually failed : " + eventualFailures); }
public static void OutputState() { ConsoleHelper.WriteInColor(String.Format(" Good endpoint: requested {0:00}, ", goodRequestsMade), ConsoleColor.White); ConsoleHelper.WriteInColor(String.Format("succeeded {0:00}, ", goodRequestsSucceeded), ConsoleColor.Green); ConsoleHelper.WriteInColor(String.Format("pending {0:00}, ", goodRequestsMade - goodRequestsSucceeded - goodRequestsFailed), ConsoleColor.Yellow); ConsoleHelper.WriteLineInColor(String.Format("failed {0:00}.", goodRequestsFailed), ConsoleColor.Red); ConsoleHelper.WriteInColor(String.Format("Faulting endpoint: requested {0:00}, ", faultingRequestsMade), ConsoleColor.White); ConsoleHelper.WriteInColor(String.Format("succeeded {0:00}, ", faultingRequestsSucceeded), ConsoleColor.Green); ConsoleHelper.WriteInColor(String.Format("pending {0:00}, ", faultingRequestsMade - faultingRequestsSucceeded - faultingRequestsFailed), ConsoleColor.Yellow); ConsoleHelper.WriteLineInColor(String.Format("failed {0:00}.", faultingRequestsFailed), ConsoleColor.Red); Console.WriteLine(); }
public static async Task ExecuteAsync(CancellationToken cancellationToken) { Console.WriteLine(typeof(AsyncDemo00_NoPolicy).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 HttpClient(); int eventualSuccesses = 0; int retries = 0; int eventualFailures = 0; int i = 0; // Do the following until a key is pressed while (!Console.KeyAvailable && !cancellationToken.IsCancellationRequested) { i++; try { // Make a request and get a response string msg = await client.GetStringAsync(Configuration.WEB_API_ROOT + "/api/values/" + i); // Display the response message on the console ConsoleHelper.WriteLineInColor("Response : " + msg, ConsoleColor.Green); eventualSuccesses++; } catch (Exception e) { ConsoleHelper.WriteLineInColor("Request " + i + " eventually failed with: " + e.Message, ConsoleColor.Red); eventualFailures++; } // Wait half second await Task.Delay(TimeSpan.FromSeconds(0.5), cancellationToken); } 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 which eventually failed : " + eventualFailures); }
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 eventualFailures = 0; int i = 0; // Do the following until a key is pressed while (!Console.KeyAvailable) { i++; try { // Make a request and get a response var msg = client.DownloadString(Configuration.WEB_API_ROOT + "/api/values/" + i.ToString()); // Display the response message on the console ConsoleHelper.WriteLineInColor("Response : " + msg, ConsoleColor.Green); eventualSuccesses++; } catch (Exception e) { ConsoleHelper.WriteLineInColor("Request " + i + " eventually failed with: " + e.Message, ConsoleColor.Red); eventualFailures++; } // 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 which eventually failed : " + eventualFailures); }
public static async Task ExecuteAsync(CancellationToken cancellationToken) { Console.WriteLine(typeof(AsyncDemo03_WaitAndRetryNTimes_WithEnoughRetries).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 HttpClient(); int eventualSuccesses = 0; int retries = 0; int eventualFailures = 0; // Define our policy: var policy = Policy.Handle <Exception>().WaitAndRetryAsync( retryCount: 20, // Retry up to 20 times! - should be enough that we eventually succeed. sleepDurationProvider: attempt => TimeSpan.FromMilliseconds(200), // Wait 200ms between each try. onRetry: (exception, calculatedWaitDuration) => // Capture some info for logging! { // This is your new exception handler! // Tell the user what they've won! ConsoleHelper.WriteLineInColor("Policy logging: " + exception.Message, ConsoleColor.Yellow); retries++; }); int i = 0; // Do the following until a key is pressed while (!Console.KeyAvailable && !cancellationToken.IsCancellationRequested) { i++; try { // Retry the following call according to the policy - 15 times. await policy.ExecuteAsync(async token => { // This code is executed within the Policy // Make a request and get a response string msg = await client.GetStringAsync(Configuration.WEB_API_ROOT + "/api/values/" + i); // Display the response message on the console ConsoleHelper.WriteLineInColor("Response : " + msg, ConsoleColor.Green); eventualSuccesses++; }, cancellationToken); } catch (Exception e) { ConsoleHelper.WriteLineInColor("Request " + i + " eventually failed with: " + e.Message, ConsoleColor.Red); eventualFailures++; } // Wait half second before the next request. await Task.Delay(TimeSpan.FromSeconds(0.5), cancellationToken); } 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 which eventually failed : " + eventualFailures); }
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 static async Task ExecuteAsync(CancellationToken cancellationToken) { Console.WriteLine(typeof(AsyncDemo06_WaitAndRetryNestingCircuitBreaker).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 HttpClient(); int eventualSuccesses = 0; int retries = 0; int eventualFailuresDueToCircuitBreaking = 0; int eventualFailuresForOtherReasons = 0; // 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) => { // This is your new exception handler! // Tell the user what they've won! ConsoleHelper.WriteLineInColor(".Log,then retry: " + exception.Message, ConsoleColor.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) => { 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) ); int i = 0; // Do the following until a key is pressed while (!Console.KeyAvailable && !cancellationToken.IsCancellationRequested) { i++; Stopwatch watch = new Stopwatch(); watch.Start(); try { // Retry the following call according to the policy - 3 times. await waitAndRetryPolicy.ExecuteAsync(async token => { // This code is executed within the waitAndRetryPolicy string msg = await circuitBreakerPolicy.ExecuteAsync <String>(() => // Note how we can also Execute() a Func<TResult> and pass back the value. { // This code is executed within the circuitBreakerPolicy // Make a request and get a response return(client.GetStringAsync(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++; }, cancellationToken); } catch (BrokenCircuitException b) { watch.Stop(); ConsoleHelper.WriteInColor("Request " + i + " failed with: " + b.GetType().Name, ConsoleColor.Red); ConsoleHelper.WriteLineInColor(" (after " + watch.ElapsedMilliseconds + "ms)", ConsoleColor.Red); eventualFailuresDueToCircuitBreaking++; } catch (Exception e) { watch.Stop(); ConsoleHelper.WriteInColor("Request " + i + " eventually failed with: " + e.Message, ConsoleColor.Red); ConsoleHelper.WriteLineInColor(" (after " + watch.ElapsedMilliseconds + "ms)", ConsoleColor.Red); eventualFailuresForOtherReasons++; } // Wait half second await Task.Delay(TimeSpan.FromSeconds(0.5), cancellationToken); } 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 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; // 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) => { // This is your new exception handler! // Tell the user what they've won! 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) ); // New for demo07: combine the waitAndRetryPolicy and circuitBreakerPolicy into a PolicyWrap. PolicyWrap policyWrap = Policy.Wrap(waitAndRetryPolicy, circuitBreakerPolicy); int i = 0; // Do the following until a key is pressed while (!Console.KeyAvailable) { i++; Stopwatch watch = new Stopwatch(); watch.Start(); try { // Retry the following call according to the policy wrap string msg = policyWrap.Execute <String>(() => { // This code is executed through both policies in the wrap: WaitAndRetry outer, then CircuitBreaker inner. Demo 06 shows a broken-out version of what this is equivalent to. return(client.DownloadString(Configuration.WEB_API_ROOT + "/api/values/" + i)); }); // Without the extra comments in the anonymous method { } above, it could even be as concise as this: // 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 (BrokenCircuitException b) { watch.Stop(); ConsoleHelper.WriteInColor("Request " + i + " failed with: " + b.GetType().Name, ConsoleColor.Red); ConsoleHelper.WriteLineInColor(" (after " + watch.ElapsedMilliseconds + "ms)", ConsoleColor.Red); eventualFailuresDueToCircuitBreaking++; } catch (Exception e) { watch.Stop(); ConsoleHelper.WriteInColor("Request " + i + " eventually failed with: " + e.Message, ConsoleColor.Red); ConsoleHelper.WriteLineInColor(" (after " + watch.ElapsedMilliseconds + "ms)", ConsoleColor.Red); eventualFailuresForOtherReasons++; } // 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 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 eventualFailures = 0; var policy = Policy.Handle <Exception>() .WaitAndRetry(6, // We can also do this with WaitAndRetryForever... but chose WaitAndRetry this time. attempt => TimeSpan.FromSeconds(0.1 * Math.Pow(2, attempt)), // Back off! 2, 4, 8, 16 etc times 1/4-second (exception, calculatedWaitDuration) => // Capture some info for logging! { // This is your new exception handler! // Tell the user what they've won! ConsoleHelper.WriteLineInColor("Exception: " + exception.Message, ConsoleColor.Yellow); ConsoleHelper.WriteLineInColor(" ... automatically delaying for " + calculatedWaitDuration.TotalMilliseconds + "ms.", ConsoleColor.Yellow); retries++; }); int i = 0; // Do the following until a key is pressed while (!Console.KeyAvailable) { i++; try { // Retry the following call according to the policy - 15 times. policy.Execute(() => { // This code is executed within the Policy // Make a request and get a response var msg = client.DownloadString(Configuration.WEB_API_ROOT + "/api/values/" + i.ToString()); // Display the response message on the console ConsoleHelper.WriteLineInColor("Response : " + msg, ConsoleColor.Green); eventualSuccesses++; }); } catch (Exception e) { ConsoleHelper.WriteLineInColor("Request " + i + " eventually failed with: " + e.Message, ConsoleColor.Red); eventualFailures++; } // Wait half second before the next request. 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 which eventually failed : " + eventualFailures); }
public static async Task ExecuteAsync(CancellationToken externalCancellationToken) { Console.WriteLine(typeof(BulkheadAsyncDemo00_NoBulkhead).Name); Console.WriteLine("======="); // Let's imagine this caller has some theoretically limited capacity. const int callerParallelCapacity = 8; // (artificially low - but easier to follow, to illustrate principle) var limitedCapacityCaller = new LimitedConcurrencyLevelTaskScheduler(callerParallelCapacity); var client = new HttpClient(); var rand = new Random(); int i = 0; IList <Task> tasks = new List <Task>(); CancellationTokenSource internalCancellationTokenSource = new CancellationTokenSource(); CancellationToken combinedToken = CancellationTokenSource.CreateLinkedTokenSource( externalCancellationToken, internalCancellationTokenSource.Token).Token; while (!Console.KeyAvailable && !externalCancellationToken.IsCancellationRequested) { i++; // Randomly make either 'good' or 'faulting' calls. if (rand.Next(0, 2) == 0) //if (i % 2 == 0) { goodRequestsMade++; // Call 'good' endpoint. tasks.Add(Task.Factory.StartNew(async j => { try { // Make a request and get a response, from the good endpoint string msg = (await client.GetAsync(Configuration.WEB_API_ROOT + "/api/nonthrottledgood/" + j, combinedToken)).Content.ReadAsStringAsync().Result; if (!combinedToken.IsCancellationRequested) { ConsoleHelper.WriteLineInColor("Response : " + msg, ConsoleColor.Green); } goodRequestsSucceeded++; } catch (Exception e) { if (!combinedToken.IsCancellationRequested) { ConsoleHelper.WriteLineInColor("Request " + j + " eventually failed with: " + e.Message, ConsoleColor.Red); } goodRequestsFailed++; } }, i, combinedToken, TaskCreationOptions.LongRunning, limitedCapacityCaller).Unwrap() ); } else { faultingRequestsMade++; // call 'faulting' endpoint. tasks.Add(Task.Factory.StartNew(async j => { try { // Make a request and get a response, from the faulting endpoint string msg = (await client.GetAsync(Configuration.WEB_API_ROOT + "/api/nonthrottledfaulting/" + j, combinedToken)).Content.ReadAsStringAsync().Result; if (!combinedToken.IsCancellationRequested) { ConsoleHelper.WriteLineInColor("Response : " + msg, ConsoleColor.Green); } faultingRequestsSucceeded++; } catch (Exception e) { if (!combinedToken.IsCancellationRequested) { ConsoleHelper.WriteLineInColor("Request " + j + " eventually failed with: " + e.Message, ConsoleColor.Red); } faultingRequestsFailed++; } }, i, combinedToken, TaskCreationOptions.LongRunning, limitedCapacityCaller).Unwrap() ); } OutputState(); // Wait briefly await Task.Delay(TimeSpan.FromSeconds(0.1), externalCancellationToken); } Console.WriteLine(""); Console.WriteLine("Total requests made : " + i); Console.WriteLine(""); OutputState(); Console.WriteLine(""); // Cancel any unstarted and running tasks. internalCancellationTokenSource.Cancel(); try { Task.WaitAll(tasks.ToArray()); } catch { // Swallow any shutdown exceptions eg TaskCanceledException - we don't care - we are shutting down the demo. } }
public static async Task ExecuteAsync(CancellationToken cancellationToken) { Console.WriteLine(typeof(AsyncDemo09_Wrap_Fallback_Timeout_WaitAndRetry).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 HttpClient(); 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 .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) => { 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>() .FallbackAsync( fallbackValue: /* Demonstrates fallback value syntax */ "Please try again later [Fallback for timeout]", onFallbackAsync: async 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>() .FallbackAsync( fallbackAction: /* Demonstrates fallback action/func syntax */ async ct => { /* do something else async if desired */ return("Please try again later [Fallback for any exception]"); }, onFallbackAsync: async 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.WrapAsync(fallbackForTimeout).WrapAsync(timeoutPolicy).WrapAsync(waitAndRetryPolicy).WrapAsync(waitAndRetryPolicy); int i = 0; while (!Console.KeyAvailable && !cancellationToken.IsCancellationRequested) { i++; watch = new Stopwatch(); watch.Start(); try { // Manage the call according to the whole policy wrap string msg = await policyWrap.ExecuteAsync(ct => client.GetStringAsync(Configuration.WEB_API_ROOT + "/api/values/" + i), cancellationToken); 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 await Task.Delay(TimeSpan.FromSeconds(0.5), cancellationToken); } 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 static async Task ExecuteAsync(CancellationToken cancellationToken) { Console.WriteLine(typeof(AsyncDemo05_WaitAndRetryWithExponentialBackoff).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 HttpClient(); int eventualSuccesses = 0; int retries = 0; int eventualFailures = 0; var policy = Policy.Handle <Exception>() .WaitAndRetryAsync(6, // We can also do this with WaitAndRetryForever... but chose WaitAndRetry this time. attempt => TimeSpan.FromSeconds(0.1 * Math.Pow(2, attempt)), // Back off! 2, 4, 8, 16 etc times 1/4-second (exception, calculatedWaitDuration) => // Capture some info for logging! { // This is your new exception handler! // Tell the user what they've won! ConsoleHelper.WriteLineInColor("Exception: " + exception.Message, ConsoleColor.Yellow); ConsoleHelper.WriteLineInColor(" ... automatically delaying for " + calculatedWaitDuration.TotalMilliseconds + "ms.", ConsoleColor.Yellow); retries++; }); int i = 0; // Do the following until a key is pressed while (!Console.KeyAvailable && !cancellationToken.IsCancellationRequested) { i++; try { // Retry the following call according to the policy - 15 times. await policy.ExecuteAsync(async token => { // This code is executed within the Policy // Make a request and get a response string msg = await client.GetStringAsync(Configuration.WEB_API_ROOT + "/api/values/" + i); // Display the response message on the console ConsoleHelper.WriteLineInColor("Response : " + msg, ConsoleColor.Green); eventualSuccesses++; }, cancellationToken); } catch (Exception e) { ConsoleHelper.WriteLineInColor("Request " + i + " eventually failed with: " + e.Message, ConsoleColor.Red); eventualFailures++; } // Wait half second before the next request. await Task.Delay(TimeSpan.FromSeconds(0.5), cancellationToken); } 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 which eventually failed : " + eventualFailures); }