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

Cleanup samples #1544

Merged
merged 2 commits into from
Sep 4, 2023
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
3 changes: 2 additions & 1 deletion samples/DependencyInjection/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
// ------------------------------------------------------------------------
// 1. Register your resilience pipeline
// ------------------------------------------------------------------------

var serviceProvider = new ServiceCollection()
.AddLogging(builder => builder.AddConsole().SetMinimumLevel(LogLevel.Debug))

// Use "AddResiliencePipeline" extension method to configure your named pipeline
.AddResiliencePipeline("my-pipeline", (builder, context) =>
{
Expand All @@ -18,6 +18,7 @@

builder.AddTimeout(TimeSpan.FromSeconds(1));
})

// You can also register result-based (generic) resilience pipelines
// First generic parameter is the key type, the second one is the result type
// This overload does not use the context argument (simple scenarios)
Expand Down
7 changes: 7 additions & 0 deletions samples/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
<Project>

<PropertyGroup>
<RunAnalyzers>true</RunAnalyzers>
<RunAnalyzersDuringBuild>true</RunAnalyzersDuringBuild>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<AnalysisLevel>latest</AnalysisLevel>
<ProjectType>Library</ProjectType>
<GenerateDocumentationFile>false</GenerateDocumentationFile>
<NoWarn>$(NoWarn);SA1123;SA1515;CA2000;CA2007;CA1303;IDE0021;RS0037;RS0016;CS1591</NoWarn>
</PropertyGroup>

<Import Project="$(MsBuildThisFileDirectory)..\eng\Library.targets" />

</Project>
32 changes: 15 additions & 17 deletions samples/Extensibility/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
{
Console.WriteLine("OnCustomEvent");
return default;
}
},
})
.Build();

Expand All @@ -22,7 +22,6 @@
// ------------------------------------------------------------------------
// SIMPLE EXTENSIBILITY MODEL (INLINE STRATEGY)
// ------------------------------------------------------------------------

pipeline = new ResiliencePipelineBuilder()
// Just add the strategy instance directly
.AddStrategy(_ => new MySimpleStrategy(), new MySimpleStrategyOptions())
Expand Down Expand Up @@ -77,13 +76,13 @@ public class MySimpleStrategyOptions : ResilienceStrategyOptions
// For reactive strategies, you can use ReactiveResilienceStrategy<T> as base class.
internal class MyResilienceStrategy : ResilienceStrategy
{
private readonly ResilienceStrategyTelemetry telemetry;
private readonly Func<OnCustomEventArguments, ValueTask>? onCustomEvent;
private readonly ResilienceStrategyTelemetry _telemetry;
private readonly Func<OnCustomEventArguments, ValueTask>? _onCustomEvent;

public MyResilienceStrategy(ResilienceStrategyTelemetry telemetry, MySimpleStrategyOptions options)
{
this.telemetry = telemetry;
this.onCustomEvent = options.OnCustomEvent;
_telemetry = telemetry;
_onCustomEvent = options.OnCustomEvent;
}

protected override async ValueTask<Outcome<TResult>> ExecuteCore<TResult, TState>(
Expand All @@ -101,15 +100,15 @@ protected override async ValueTask<Outcome<TResult>> ExecuteCore<TResult, TState
// ...

// You can then report important telemetry events
telemetry.Report(
_telemetry.Report(
new ResilienceEvent(ResilienceEventSeverity.Information, "MyCustomEvent"),
context,
new OnCustomEventArguments(context));

// Call the delegate if provided by the user
if (onCustomEvent is not null)
if (_onCustomEvent is not null)
{
await onCustomEvent(new OnCustomEventArguments(context));
await _onCustomEvent(new OnCustomEventArguments(context));
}

return outcome;
Expand All @@ -119,15 +118,14 @@ protected override async ValueTask<Outcome<TResult>> ExecuteCore<TResult, TState
// ------------------------------------------------------------------------
// 3. Expose new extensions for ResiliencePipelineBuilder
// ------------------------------------------------------------------------

public static class MyResilienceStrategyExtensions
{
// Add new extension that works for both "ResiliencePipelineBuilder" and "ResiliencePipelineBuilder<T>"
public static TBuilder AddMyResilienceStrategy<TBuilder>(this TBuilder builder, MySimpleStrategyOptions options) where TBuilder : ResiliencePipelineBuilderBase
=> builder.AddStrategy(
// Provide a factory that creates the strategy
context => new MyResilienceStrategy(context.Telemetry, options),

// Pass the options, note that the options instance is automatically validated by the builder
options);
public static TBuilder AddMyResilienceStrategy<TBuilder>(this TBuilder builder, MySimpleStrategyOptions options)
where TBuilder : ResiliencePipelineBuilderBase
{
return builder.AddStrategy(
context => new MyResilienceStrategy(context.Telemetry, options), // Provide a factory that creates the strategy
options); // Pass the options, note that the options instance is automatically validated by the builder
}
}
17 changes: 11 additions & 6 deletions samples/GenericStrategies/Program.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Net;
#pragma warning disable SA1633 // File should have header
using System.Net;
#pragma warning restore SA1633 // File should have header
using Polly;
using Polly.Fallback;
using Polly.Retry;
Expand All @@ -10,7 +12,6 @@

// The generic ResiliencePipelineBuilder<T> creates a ResiliencePipeline<T>
// that can execute synchronous and asynchronous callbacks that return T.

ResiliencePipeline<HttpResponseMessage> pipeline = new ResiliencePipelineBuilder<HttpResponseMessage>()
.AddFallback(new FallbackStrategyOptions<HttpResponseMessage>
{
Expand All @@ -19,26 +20,28 @@
// Return fallback result
return Outcome.FromResultAsValueTask(new HttpResponseMessage(HttpStatusCode.OK));
},

// You can also use switch expressions for succinct syntax
ShouldHandle = arguments => arguments.Outcome switch
{
// The "PredicateResult.True" is shorthand to "new ValueTask<bool>(true)"
{ Exception: HttpRequestException } => PredicateResult.True(),
{ Result: HttpResponseMessage response } when response.StatusCode == HttpStatusCode.InternalServerError => PredicateResult.True(),
_ => PredicateResult.False()
_ => PredicateResult.False(),
},
OnFallback = _ =>
{
Console.WriteLine("Fallback!");
return default;
}
},
})
.AddRetry(new RetryStrategyOptions<HttpResponseMessage>
{
// You can use "PredicateBuilder" to configure the predicates
ShouldHandle = new PredicateBuilder<HttpResponseMessage>()
.HandleResult(r => r.StatusCode == HttpStatusCode.InternalServerError)
.Handle<HttpRequestException>(),

// Register user callback called whenever retry occurs
OnRetry = arguments =>
{
Expand All @@ -47,24 +50,26 @@
},
Delay = TimeSpan.FromMilliseconds(400),
BackoffType = DelayBackoffType.Constant,
MaxRetryAttempts = 3
MaxRetryAttempts = 3,
})
.AddTimeout(new TimeoutStrategyOptions
{
Timeout = TimeSpan.FromSeconds(1),

// Register user callback called whenever timeout occurs
OnTimeout = _ =>
{
Console.WriteLine("Timeout occurred!");
return default;
}
},
})
.Build();

var response = await pipeline.ExecuteAsync(
async token =>
{
await Task.Delay(10, token);

// This causes the action fail, thus using the fallback strategy above
return new HttpResponseMessage(HttpStatusCode.InternalServerError);
},
Expand Down
22 changes: 16 additions & 6 deletions samples/Intro/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
// that can be executed synchronously or asynchronously
// and for both void and result-returning user-callbacks.
ResiliencePipeline pipeline = new ResiliencePipelineBuilder()

// Use convenience extension that accepts TimeSpan
.AddTimeout(TimeSpan.FromSeconds(5))
.AddTimeout(TimeSpan.FromSeconds(5))
.Build();

// ------------------------------------------------------------------------
Expand All @@ -28,16 +29,22 @@
pipeline.Execute(token => "some-result");

// Asynchronously with result
await pipeline.ExecuteAsync(async token => { await Task.Delay(10, token); return "some-result"; }, CancellationToken.None);
await pipeline.ExecuteAsync(
async token =>
{
await Task.Delay(10, token);
return "some-result";
},
CancellationToken.None);

// Use state to avoid lambda allocation
pipeline.Execute(static state => state, "my-state");

// ------------------------------------------------------------------------
// 3. Create and execute a pipeline of strategies
// ------------------------------------------------------------------------

pipeline = new ResiliencePipelineBuilder()

// Add retries using the options
.AddRetry(new RetryStrategyOptions
{
Expand All @@ -48,8 +55,9 @@

// The "PredicateResult.False" is just shorthand for "new ValueTask<bool>(true)"
// You can also use "new PredicateBuilder().Handle<TimeoutRejectedException>()"
_ => PredicateResult.False()
_ => PredicateResult.False(),
},

// Register user callback called whenever retry occurs
OnRetry = args =>
{
Expand All @@ -58,18 +66,20 @@
},
Delay = TimeSpan.FromMilliseconds(400),
BackoffType = DelayBackoffType.Constant,
MaxRetryAttempts = 3
MaxRetryAttempts = 3,
})

// Add timeout using the options
.AddTimeout(new TimeoutStrategyOptions
{
Timeout = TimeSpan.FromSeconds(1),

// Register user callback called whenever timeout occurs
OnTimeout = args =>
{
Console.WriteLine($"Timeout occurred after {args.Timeout}!");
return default;
}
},
})
.Build();

Expand Down
2 changes: 1 addition & 1 deletion samples/Retries/ExecuteHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Retries;

internal class ExecuteHelper
internal sealed class ExecuteHelper
{
public bool Fail { get; set; } = true;

Expand Down
13 changes: 5 additions & 8 deletions samples/Retries/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
// ------------------------------------------------------------------------
// 1. Create a retry pipeline that handles all exceptions
// ------------------------------------------------------------------------

ResiliencePipeline pipeline = new ResiliencePipelineBuilder()
// Default retry options handle all exceptions
.AddRetry(new RetryStrategyOptions())
Expand All @@ -20,7 +19,6 @@
// ------------------------------------------------------------------------
// 2. Customize the retry behavior
// ------------------------------------------------------------------------

pipeline = new ResiliencePipelineBuilder()
.AddRetry(new RetryStrategyOptions
{
Expand All @@ -32,7 +30,7 @@
// The recommended backoff type for HTTP scenarios
// See here for more information: https://github.com/App-vNext/Polly/wiki/Retry-with-jitter#more-complex-jitter
BackoffType = DelayBackoffType.Exponential,
UseJitter = true
UseJitter = true,
})
.Build();

Expand All @@ -42,7 +40,6 @@
// ------------------------------------------------------------------------
// 3. Register the callbacks
// ------------------------------------------------------------------------

pipeline = new ResiliencePipelineBuilder()
.AddRetry(new RetryStrategyOptions
{
Expand All @@ -56,7 +53,7 @@
{
Console.WriteLine($"Retrying attempt {outcome.AttemptNumber}...");
return default;
}
},
})
.Build();

Expand All @@ -66,15 +63,15 @@
// ------------------------------------------------------------------------
// 4. Create an HTTP retry pipeline that handles both exceptions and results
// ------------------------------------------------------------------------

ResiliencePipeline<HttpResponseMessage> httpPipeline = new ResiliencePipelineBuilder<HttpResponseMessage>()
.AddRetry(new RetryStrategyOptions<HttpResponseMessage>
{
// Specify what exceptions or results should be retried
ShouldHandle = new PredicateBuilder<HttpResponseMessage>()
.Handle<HttpRequestException>()
.Handle<InvalidOperationException>()
.HandleResult(r=>r.StatusCode == HttpStatusCode.InternalServerError),
.HandleResult(r => r.StatusCode == HttpStatusCode.InternalServerError),

// Specify delay generator
DelayGenerator = arguments =>
{
Expand All @@ -87,7 +84,7 @@

// Return delay hinted by the retry strategy
return new ValueTask<TimeSpan?>(default(TimeSpan?));
}
},
})
.Build();

Expand Down
1 change: 1 addition & 0 deletions samples/Samples.sln
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{CE7916FD-6C1A-48CE-8919-F4BAB4E3770F}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
Directory.Build.props = Directory.Build.props
Directory.Build.targets = Directory.Build.targets
README.md = README.md
Expand Down