From da9db1bcc95e6f8b3bbc90b49decc18851a07551 Mon Sep 17 00:00:00 2001 From: martintmk <103487740+martintmk@users.noreply.github.com> Date: Mon, 4 Sep 2023 12:37:38 +0200 Subject: [PATCH] Cleanup samples (#1544) --- samples/DependencyInjection/Program.cs | 3 ++- samples/Directory.Build.props | 7 ++++++ samples/Extensibility/Program.cs | 32 ++++++++++++-------------- samples/GenericStrategies/Program.cs | 17 +++++++++----- samples/Intro/Program.cs | 22 +++++++++++++----- samples/Retries/ExecuteHelper.cs | 2 +- samples/Retries/Program.cs | 13 ++++------- samples/Samples.sln | 1 + 8 files changed, 58 insertions(+), 39 deletions(-) diff --git a/samples/DependencyInjection/Program.cs b/samples/DependencyInjection/Program.cs index 4e1ead5febb..1777960bdcf 100644 --- a/samples/DependencyInjection/Program.cs +++ b/samples/DependencyInjection/Program.cs @@ -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) => { @@ -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) diff --git a/samples/Directory.Build.props b/samples/Directory.Build.props index cb53b3c00ba..d320c685aed 100644 --- a/samples/Directory.Build.props +++ b/samples/Directory.Build.props @@ -1,8 +1,15 @@ + true true true latest + Library + false + $(NoWarn);SA1123;SA1515;CA2000;CA2007;CA1303;IDE0021;RS0037;RS0016;CS1591 + + + diff --git a/samples/Extensibility/Program.cs b/samples/Extensibility/Program.cs index e0cc969c91b..79d638781c8 100644 --- a/samples/Extensibility/Program.cs +++ b/samples/Extensibility/Program.cs @@ -12,7 +12,7 @@ { Console.WriteLine("OnCustomEvent"); return default; - } + }, }) .Build(); @@ -22,7 +22,6 @@ // ------------------------------------------------------------------------ // SIMPLE EXTENSIBILITY MODEL (INLINE STRATEGY) // ------------------------------------------------------------------------ - pipeline = new ResiliencePipelineBuilder() // Just add the strategy instance directly .AddStrategy(_ => new MySimpleStrategy(), new MySimpleStrategyOptions()) @@ -77,13 +76,13 @@ public class MySimpleStrategyOptions : ResilienceStrategyOptions // For reactive strategies, you can use ReactiveResilienceStrategy as base class. internal class MyResilienceStrategy : ResilienceStrategy { - private readonly ResilienceStrategyTelemetry telemetry; - private readonly Func? onCustomEvent; + private readonly ResilienceStrategyTelemetry _telemetry; + private readonly Func? _onCustomEvent; public MyResilienceStrategy(ResilienceStrategyTelemetry telemetry, MySimpleStrategyOptions options) { - this.telemetry = telemetry; - this.onCustomEvent = options.OnCustomEvent; + _telemetry = telemetry; + _onCustomEvent = options.OnCustomEvent; } protected override async ValueTask> ExecuteCore( @@ -101,15 +100,15 @@ protected override async ValueTask> ExecuteCore> ExecuteCore" - public static TBuilder AddMyResilienceStrategy(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(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 + } } diff --git a/samples/GenericStrategies/Program.cs b/samples/GenericStrategies/Program.cs index b5c12b61a3d..bf2772905ed 100644 --- a/samples/GenericStrategies/Program.cs +++ b/samples/GenericStrategies/Program.cs @@ -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; @@ -10,7 +12,6 @@ // The generic ResiliencePipelineBuilder creates a ResiliencePipeline // that can execute synchronous and asynchronous callbacks that return T. - ResiliencePipeline pipeline = new ResiliencePipelineBuilder() .AddFallback(new FallbackStrategyOptions { @@ -19,19 +20,20 @@ // 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(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 { @@ -39,6 +41,7 @@ ShouldHandle = new PredicateBuilder() .HandleResult(r => r.StatusCode == HttpStatusCode.InternalServerError) .Handle(), + // Register user callback called whenever retry occurs OnRetry = arguments => { @@ -47,17 +50,18 @@ }, 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(); @@ -65,6 +69,7 @@ async token => { await Task.Delay(10, token); + // This causes the action fail, thus using the fallback strategy above return new HttpResponseMessage(HttpStatusCode.InternalServerError); }, diff --git a/samples/Intro/Program.cs b/samples/Intro/Program.cs index f86536891ae..29ce393a7dd 100644 --- a/samples/Intro/Program.cs +++ b/samples/Intro/Program.cs @@ -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(); // ------------------------------------------------------------------------ @@ -28,7 +29,13 @@ 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"); @@ -36,8 +43,8 @@ // ------------------------------------------------------------------------ // 3. Create and execute a pipeline of strategies // ------------------------------------------------------------------------ - pipeline = new ResiliencePipelineBuilder() + // Add retries using the options .AddRetry(new RetryStrategyOptions { @@ -48,8 +55,9 @@ // The "PredicateResult.False" is just shorthand for "new ValueTask(true)" // You can also use "new PredicateBuilder().Handle()" - _ => PredicateResult.False() + _ => PredicateResult.False(), }, + // Register user callback called whenever retry occurs OnRetry = args => { @@ -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(); diff --git a/samples/Retries/ExecuteHelper.cs b/samples/Retries/ExecuteHelper.cs index 9104acb19ba..09aa2fe137e 100644 --- a/samples/Retries/ExecuteHelper.cs +++ b/samples/Retries/ExecuteHelper.cs @@ -2,7 +2,7 @@ namespace Retries; -internal class ExecuteHelper +internal sealed class ExecuteHelper { public bool Fail { get; set; } = true; diff --git a/samples/Retries/Program.cs b/samples/Retries/Program.cs index 245336fe916..6c8127bebe1 100644 --- a/samples/Retries/Program.cs +++ b/samples/Retries/Program.cs @@ -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()) @@ -20,7 +19,6 @@ // ------------------------------------------------------------------------ // 2. Customize the retry behavior // ------------------------------------------------------------------------ - pipeline = new ResiliencePipelineBuilder() .AddRetry(new RetryStrategyOptions { @@ -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(); @@ -42,7 +40,6 @@ // ------------------------------------------------------------------------ // 3. Register the callbacks // ------------------------------------------------------------------------ - pipeline = new ResiliencePipelineBuilder() .AddRetry(new RetryStrategyOptions { @@ -56,7 +53,7 @@ { Console.WriteLine($"Retrying attempt {outcome.AttemptNumber}..."); return default; - } + }, }) .Build(); @@ -66,7 +63,6 @@ // ------------------------------------------------------------------------ // 4. Create an HTTP retry pipeline that handles both exceptions and results // ------------------------------------------------------------------------ - ResiliencePipeline httpPipeline = new ResiliencePipelineBuilder() .AddRetry(new RetryStrategyOptions { @@ -74,7 +70,8 @@ ShouldHandle = new PredicateBuilder() .Handle() .Handle() - .HandleResult(r=>r.StatusCode == HttpStatusCode.InternalServerError), + .HandleResult(r => r.StatusCode == HttpStatusCode.InternalServerError), + // Specify delay generator DelayGenerator = arguments => { @@ -87,7 +84,7 @@ // Return delay hinted by the retry strategy return new ValueTask(default(TimeSpan?)); - } + }, }) .Build(); diff --git a/samples/Samples.sln b/samples/Samples.sln index 056777613b5..191919364eb 100644 --- a/samples/Samples.sln +++ b/samples/Samples.sln @@ -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