Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate sync demos from 01 to 03 #40

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
namespace PollyDemos.Sync
{
/// <summary>
/// Uses no policy. Demonstrates behaviour of 'faulting server' we are testing against.
/// Uses no strategy. Demonstrates behavior of 'faulting server' we are testing against.
/// Loops through a series of Http requests, keeping track of each requested
/// item and reporting server failures when encountering exceptions.
/// </summary>
public class Demo00_NoPolicy : SyncDemo
public class Demo00_NoStrategy : SyncDemo
{
private int totalRequests;
private int eventualSuccesses;
Expand All @@ -22,7 +22,12 @@ public override void Execute(CancellationToken cancellationToken, IProgress<Demo

// 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.
progress.Report(ProgressWithMessage(nameof(Demo00_NoPolicy)));

eventualSuccesses = 0;
eventualFailures = 0;
totalRequests = 0;

progress.Report(ProgressWithMessage(nameof(Demo00_NoStrategy)));
progress.Report(ProgressWithMessage("======"));
progress.Report(ProgressWithMessage(string.Empty));

Expand Down
114 changes: 59 additions & 55 deletions PollyDemos/Sync/Demo01_RetryNTimes.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
using System.Net;
using PollyDemos.OutputHelpers;
using PollyDemos.OutputHelpers;

namespace PollyDemos.Sync
{
/// <summary>
/// Demonstrates the Retry policy coming into action.
/// Demonstrates the Retry strategy coming into action.
/// Loops through a series of Http requests, keeping track of each requested
/// item and reporting server failures when encountering exceptions.
///
/// Observations: There's no wait among these retries. Can be appropriate sometimes.
///
/// Observations: There's no wait among these retries. Can be appropriate sometimes.
/// In this case, no wait hasn't given underlying system time to recover, so calls still fail despite retries.
/// </summary>
public class Demo01_RetryNTimes : SyncDemo
Expand All @@ -23,80 +22,85 @@ public class Demo01_RetryNTimes : SyncDemo

public override void Execute(CancellationToken cancellationToken, IProgress<DemoProgress> progress)
{
if (progress == null) throw new ArgumentNullException(nameof(progress));
ArgumentNullException.ThrowIfNull(progress);

// Let's call a web api service to make repeated requests to a server.
// 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;
eventualFailures = 0;
totalRequests = 0;

progress.Report(ProgressWithMessage(nameof(Demo01_RetryNTimes)));
progress.Report(ProgressWithMessage("======"));
progress.Report(ProgressWithMessage(string.Empty));

// Let's call a web api service to make repeated requests to a server.
// 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.

// Define our policy:
var policy = Policy.Handle<Exception>().Retry(3, (exception, attempt) =>
// Define our strategy:
var strategy = new ResiliencePipelineBuilder().AddRetry(new()
{
// This is your new exception handler!
// Tell the user what they've won!
progress.Report(ProgressWithMessage("Policy logging: " + exception.Message, Color.Yellow));
retries++;
});
ShouldHandle = new PredicateBuilder().Handle<Exception>(),
MaxRetryAttempts = 3, // Retry up to 3 times
OnRetry = args =>
{
// Due to how we have defined ShouldHandle, this delegate is called only if an exception occurred.
// Note the ! sign (null-forgiving operator) at the end of the command.
var exception = args.Outcome.Exception!; //The Exception property is nullable

// Tell the user what happened
progress.Report(ProgressWithMessage("Strategy logging: " + exception.Message, Color.Yellow));
retries++;
return default;
}
}).Build();

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

try
{
// Retry the following call according to the policy - 3 times.
policy.Execute(
ct => // The Execute() overload takes a CancellationToken, but it happens the executed code does not honour it.
{
// This code is executed within the Policy

// Make a request and get a response
var response =
client.DownloadString(Configuration.WEB_API_ROOT + "/api/values/" + totalRequests);

// Display the response message on the console
progress.Report(ProgressWithMessage("Response : " + response, Color.Green));
eventualSuccesses++;
}
, cancellationToken // The cancellationToken passed in to Execute() enables the policy instance to cancel retries, when the token is signalled.
);
}
catch (Exception e)
try
{
// Retry the following call according to the strategy - 3 times.
// The cancellationToken passed in to Execute() enables the strategy to cancel retries, when the token is signalled.
strategy.Execute(ct =>
{
progress.Report(ProgressWithMessage(
"Request " + totalRequests + " eventually failed with: " + e.Message, Color.Red));
eventualFailures++;
}
// This code is executed within the strategy

// Make a request and get a response
var url = $"{Configuration.WEB_API_ROOT}/api/values/{totalRequests}";
var response = client.Send(new HttpRequestMessage(HttpMethod.Get, url), ct);

// Wait half second
Thread.Sleep(500);
// Display the response message on the console
using var stream = response.Content.ReadAsStream(ct);
using var streamReader = new StreamReader(stream);
progress.Report(ProgressWithMessage($"Response : {streamReader.ReadToEnd()}", Color.Green));
eventualSuccesses++;

internalCancel = TerminateDemosByKeyPress && Console.KeyAvailable;
}, cancellationToken);
}
catch (Exception e)
{
progress.Report(ProgressWithMessage($"Request {totalRequests} eventually failed with: {e.Message}", Color.Red));
eventualFailures++;
}

Thread.Sleep(500);
internalCancel = TerminateDemosByKeyPress && Console.KeyAvailable;
}
}

public override Statistic[] LatestStatistics => new[]
public override Statistic[] LatestStatistics => new Statistic[]
{
new Statistic("Total requests made", totalRequests),
new Statistic("Requests which eventually succeeded", eventualSuccesses, Color.Green),
new Statistic("Retries made to help achieve success", retries, Color.Yellow),
new Statistic("Requests which eventually failed", eventualFailures, Color.Red),
new("Total requests made", totalRequests),
new("Requests which eventually succeeded", eventualSuccesses, Color.Green),
new("Retries made to help achieve success", retries, Color.Yellow),
new("Requests which eventually failed", eventualFailures, Color.Red),
};
}
}
}
115 changes: 58 additions & 57 deletions PollyDemos/Sync/Demo02_WaitAndRetryNTimes.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
using System.Net;
using PollyDemos.OutputHelpers;
using PollyDemos.OutputHelpers;

namespace PollyDemos.Sync
{
/// <summary>
/// Demonstrates the WaitAndRetry policy.
/// Demonstrates the Retry strategy with delays between retry attempts.
/// Loops through a series of Http requests, keeping track of each requested
/// item and reporting server failures when encountering exceptions.
///
///
/// Observations: We now have waits among the retries.
/// In this case, still not enough wait - or not enough retries - for the underlying system to have recovered.
/// So we still fail some calls.
Expand All @@ -20,87 +19,89 @@ public class Demo02_WaitAndRetryNTimes : SyncDemo
private int eventualFailures;

public override string Description =>
"Compared to previous demo, this demo adds waits between the retries. Not always enough wait to ensure success, tho.";
"Compared to previous demo, this demo adds waits between the retry attempts. Not always enough wait to ensure success, tho.";

public override void Execute(CancellationToken cancellationToken, IProgress<DemoProgress> progress)
{
if (progress == null) throw new ArgumentNullException(nameof(progress));
ArgumentNullException.ThrowIfNull(progress);

// Let's call a web api service to make repeated requests to a server.
// 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;
eventualFailures = 0;
totalRequests = 0;

progress.Report(ProgressWithMessage(nameof(Demo02_WaitAndRetryNTimes)));
progress.Report(ProgressWithMessage("======"));
progress.Report(ProgressWithMessage(string.Empty));

// Let's call a web api service to make repeated requests to a server.
// 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.

// Define our policy:
var policy = Policy.Handle<Exception>().WaitAndRetry(
3, // Retry 3 times
attempt => TimeSpan.FromMilliseconds(200), // Wait 200ms between each try.
(exception, calculatedWaitDuration) => // Capture some info for logging!
{
// This is your new exception handler!
// Tell the user what they've won!
progress.Report(ProgressWithMessage("Policy logging: " + exception.Message, Color.Yellow));
retries++;
});

using (var client = new WebClient())
// Define our strategy:
var strategy = new ResiliencePipelineBuilder().AddRetry(new()
{
totalRequests = 0;
var internalCancel = false;
// Do the following until a key is pressed
while (!internalCancel && !cancellationToken.IsCancellationRequested)
ShouldHandle = new PredicateBuilder().Handle<Exception>(),
MaxRetryAttempts = 3,
Delay = TimeSpan.FromMilliseconds(200), // Wait 200ms between each try
OnRetry = args =>
{
totalRequests++;
// Due to how we have defined ShouldHandle, this delegate is called only if an exception occurred.
// Note the ! sign (null-forgiving operator) at the end of the command.
var exception = args.Outcome.Exception!; //The Exception property is nullable

try
{
// Retry the following call according to the policy - 3 times.
policy.Execute(
ct => // The Execute() overload takes a CancellationToken, but it happens the executed code does not honour it.
{
// This code is executed within the Policy
// Tell the user what happened
progress.Report(ProgressWithMessage("Strategy logging: " + exception.Message, Color.Yellow));
retries++;
return default;
}
}).Build();

// Make a request and get a response
var response =
client.DownloadString(Configuration.WEB_API_ROOT + "/api/values/" + totalRequests);
var client = new HttpClient();
var internalCancel = false;
// Do the following until a key is pressed
while (!(internalCancel || cancellationToken.IsCancellationRequested))
{
totalRequests++;

// Display the response message on the console
progress.Report(ProgressWithMessage("Response : " + response, Color.Green));
eventualSuccesses++;
}
, cancellationToken // The cancellationToken passed in to Execute() enables the policy instance to cancel retries, when the token is signalled.
);
}
catch (Exception e)
try
{
// Retry the following call according to the strategy - 3 times.
// The cancellationToken passed in to Execute() enables the strategy to cancel retries, when the token is signalled.
strategy.Execute(ct =>
{
progress.Report(ProgressWithMessage(
"Request " + totalRequests + " eventually failed with: " + e.Message, Color.Red));
eventualFailures++;
}
// This code is executed within the strategy

// Wait half second
Thread.Sleep(500);
// Make a request and get a response
var url = $"{Configuration.WEB_API_ROOT}/api/values/{totalRequests}";
var response = client.Send(new HttpRequestMessage(HttpMethod.Get, url), ct);

internalCancel = TerminateDemosByKeyPress && Console.KeyAvailable;
// Display the response message on the console
using var stream = response.Content.ReadAsStream(ct);
using var streamReader = new StreamReader(stream);
progress.Report(ProgressWithMessage($"Response : {streamReader.ReadToEnd()}", Color.Green));
eventualSuccesses++;
}, cancellationToken);
}
catch (Exception e)
{
progress.Report(ProgressWithMessage($"Request {totalRequests} eventually failed with: {e.Message}", Color.Red));
eventualFailures++;
}

Thread.Sleep(500);
internalCancel = TerminateDemosByKeyPress && Console.KeyAvailable;
}
}

public override Statistic[] LatestStatistics => new[]
public override Statistic[] LatestStatistics => new Statistic[]
{
new Statistic("Total requests made", totalRequests),
new Statistic("Requests which eventually succeeded", eventualSuccesses, Color.Green),
new Statistic("Retries made to help achieve success", retries, Color.Yellow),
new Statistic("Requests which eventually failed", eventualFailures, Color.Red),
new("Total requests made", totalRequests),
new("Requests which eventually succeeded", eventualSuccesses, Color.Green),
new("Retries made to help achieve success", retries, Color.Yellow),
new("Requests which eventually failed", eventualFailures, Color.Red),
};
}
}
}
Loading
Loading