Skip to content

Commit

Permalink
Add Wpf demos to Polly-Samples
Browse files Browse the repository at this point in the history
* Add Wpf demos to Polly-Samples
* Separate demo implementations into independent PollyDemos project
* Provide two separate clients, PollyTestClientConsole and
PollyTestClientWpf
* Move demo implementatinos to separate sync and async folders
* Update readme
  • Loading branch information
reisenberger committed Nov 8, 2017
1 parent 70a7a8c commit cbf1e54
Show file tree
Hide file tree
Showing 55 changed files with 4,376 additions and 44 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -6,6 +6,7 @@
*.user
*.sln.docstates
.vs/
[Pp]ackages/

# Build results
[Dd]ebug/
Expand Down
18 changes: 15 additions & 3 deletions Polly-Samples.sln
@@ -1,11 +1,15 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.40629.0
# Visual Studio 15
VisualStudioVersion = 15.0.26430.16
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PollyTestApp", "PollyTestApp\PollyTestApp.csproj", "{A0C3DAF0-4F18-4DAB-8A16-8A5C5F6CAEC1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PollyTestClient", "PollyTestClient\PollyTestClient.csproj", "{69789838-8A79-4D0D-9723-8C0A8435E802}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PollyDemos", "PollyDemos\PollyDemos.csproj", "{69789838-8A79-4D0D-9723-8C0A8435E802}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PollyTestClientConsole", "PollyTestClientConsole\PollyTestClientConsole.csproj", "{A724DE86-8F09-4EF6-BF26-289C28189C53}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PollyTestClientWpf", "PollyTestClientWpf\PollyTestClientWpf.csproj", "{89432E40-AEB5-4020-AC43-E8BB9CAC6AD6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand All @@ -21,6 +25,14 @@ Global
{69789838-8A79-4D0D-9723-8C0A8435E802}.Debug|Any CPU.Build.0 = Debug|Any CPU
{69789838-8A79-4D0D-9723-8C0A8435E802}.Release|Any CPU.ActiveCfg = Release|Any CPU
{69789838-8A79-4D0D-9723-8C0A8435E802}.Release|Any CPU.Build.0 = Release|Any CPU
{A724DE86-8F09-4EF6-BF26-289C28189C53}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A724DE86-8F09-4EF6-BF26-289C28189C53}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A724DE86-8F09-4EF6-BF26-289C28189C53}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A724DE86-8F09-4EF6-BF26-289C28189C53}.Release|Any CPU.Build.0 = Release|Any CPU
{89432E40-AEB5-4020-AC43-E8BB9CAC6AD6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{89432E40-AEB5-4020-AC43-E8BB9CAC6AD6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{89432E40-AEB5-4020-AC43-E8BB9CAC6AD6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{89432E40-AEB5-4020-AC43-E8BB9CAC6AD6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
15 changes: 15 additions & 0 deletions PollyDemos/Async/AsyncDemo.cs
@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using PollyDemos.OutputHelpers;

namespace PollyDemos.Async
{
public abstract class AsyncDemo : DemoBase
{
public abstract Task ExecuteAsync(CancellationToken cancellationToken, IProgress<DemoProgress> progress);
}
}
77 changes: 77 additions & 0 deletions PollyDemos/Async/AsyncDemo00_NoPolicy.cs
@@ -0,0 +1,77 @@
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using PollyDemos.OutputHelpers;

namespace PollyDemos.Async
{
/// <summary>
/// Uses no policy. Demonstrates behaviour 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 AsyncDemo00_NoPolicy : AsyncDemo
{
private int totalRequests;
private int eventualSuccesses;
private int retries;
private int eventualFailures;

public override string Description => "This demo demonstrates how our faulting server behaves, with no Polly policies in use.";

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

eventualSuccesses = 0;
retries = 0;
eventualFailures = 0;

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

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

try
{
// Make a request and get a response
string msg = await client.GetStringAsync(Configuration.WEB_API_ROOT + "/api/values/" + totalRequests);

// Display the response message on the console
progress.Report(ProgressWithMessage("Response : " + msg, Color.Green));
eventualSuccesses++;
}
catch (Exception e)
{
progress.Report(ProgressWithMessage("Request " + totalRequests + " eventually failed with: " + e.Message, Color.Red));
eventualFailures++;
}

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

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

public override Statistic[] LatestStatistics => new[]
{
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),
};

}
}
97 changes: 97 additions & 0 deletions PollyDemos/Async/AsyncDemo01_RetryNTimes.cs
@@ -0,0 +1,97 @@
using Polly;
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using PollyDemos.OutputHelpers;

namespace PollyDemos.Async
{
/// <summary>
/// Demonstrates the Retry policy 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.
/// In this case, no wait hasn't given underlying system time to recover, so calls still fail despite retries.
/// </summary>
public class AsyncDemo01_RetryNTimes : AsyncDemo
{
private int totalRequests;
private int eventualSuccesses;
private int retries;
private int eventualFailures;

public override string Description => "This demo demonstrates a first Retry. It retries three times, immediately.";

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

eventualSuccesses = 0;
retries = 0;
eventualFailures = 0;

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

// 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!
progress.Report(ProgressWithMessage("Policy logging: " + exception.Message, Color.Yellow));
retries++;
});

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

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/" + totalRequests);
// Display the response message on the console
progress.Report(ProgressWithMessage("Response : " + msg, Color.Green));
eventualSuccesses++;
});
}
catch (Exception e)
{
progress.Report(ProgressWithMessage("Request " + totalRequests + " eventually failed with: " + e.Message, Color.Red));
eventualFailures++;
}

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

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

public override Statistic[] LatestStatistics => new[]
{
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),
};

}
}
103 changes: 103 additions & 0 deletions PollyDemos/Async/AsyncDemo02_WaitAndRetryNTimes.cs
@@ -0,0 +1,103 @@
using Polly;
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using PollyDemos.OutputHelpers;

namespace PollyDemos.Async
{
/// <summary>
/// Demonstrates the WaitAndRetry policy.
/// 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.
/// </summary>
public class AsyncDemo02_WaitAndRetryNTimes : AsyncDemo
{
private int totalRequests;
private int eventualSuccesses;
private int retries;
private int eventualFailures;

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

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

eventualSuccesses = 0;
retries = 0;
eventualFailures = 0;

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

// Define our policy:
var policy = Policy.Handle<Exception>().WaitAndRetryAsync(
retryCount: 3, // Retry 3 times
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!
progress.Report(ProgressWithMessage("Policy logging: " + exception.Message, Color.Yellow));
retries++;
});

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

// Do the following until a key is pressed
while (!internalCancel && !cancellationToken.IsCancellationRequested)
{
totalRequests++;

try
{
// Retry the following call according to the policy - 3 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/" + totalRequests);
// Display the response message on the console
progress.Report(ProgressWithMessage("Response : " + msg, Color.Green));
eventualSuccesses++;
}, cancellationToken);
}
catch (Exception e)
{
progress.Report(ProgressWithMessage("Request " + totalRequests + " eventually failed with: " + e.Message, Color.Red));
eventualFailures++;
}

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

internalCancel = TerminateDemosByKeyPress && Console.KeyAvailable;
}
}

}

public override Statistic[] LatestStatistics => new[]
{
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),
};

}
}

0 comments on commit cbf1e54

Please sign in to comment.