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

Updates for alpha.9 #1526

Merged
merged 3 commits into from
Aug 30, 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
44 changes: 44 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,47 @@
## 8.0.0-alpha.9

* Updates for alpha.8 by [@martincostello](https://github.com/martincostello) in https://github.com/App-vNext/Polly/pull/1465
* Fix unstable build by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1466
* Improve samples by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1467
* Specify DebuggerDisplay for ReactiveResilienceStrategyBridge by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1468
* Drop the `Extensions` from `Polly.Extensions` namespace by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1469
* Remove Moq by [@martincostello](https://github.com/martincostello) in https://github.com/App-vNext/Polly/pull/1472
* Add new metering tests to cover uncovered lines by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1474
* Default names for individual resilience strategies by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1475
* Introduce `NonReactiveResilienceStrategy` by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1476
* Drop `TelemetryResilienceStrategy` by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1482
* API Review feedback (1) by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1484
* Rename ResilienceStrategy to ResiliencePipeline by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1483
* API Review Feedback (2) by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1485
* Introduce TelemetryListener by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1486
* Improve documentation by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1487
* Fix metering tests by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1488
* Hide validation APIs by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1490
* Logging improvements by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1489
* Hide/drop some unused APIs by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1491
* Cleanup internals by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1492
* ResilienceContextPool improvements by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1493
* Hide IsSynchronous property by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1494
* Drop unused ResiliencePipelineRegistry APIs by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1495
* `ResiliencePipelineRegistry` is now disposable by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1496
* Move pipeline-related internals into `Pipeline` folder by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1497
* Update benchmarks by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1503
* Minor ResiliencePipelineRegistry cleanup of internals by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1505
* API Review Feedback by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1506
* Minor API cleanup by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1508
* Clenaup rate limiter API by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1509
* Cleanup ResiliencePipelineRegistry internals by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1510
* Allow to dispose linked resources on pipeline disposal by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1511
* Simplify and enhance the pipeline reloads by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1512
* Drop `OutcomeArguments` struct by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1513
* API Review Feedback by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1520
* Got rid of some warnings in the Polly project by [@IgorIgorevich94](https://github.com/IgorIgorevich94) in https://github.com/App-vNext/Polly/pull/1514
* API Review Feedback by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1521
* Cleanup Outcome internals and drop unused hedging and fallbacks APIs by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1523
* Improve debugging experience for `ResilienceProperties` by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1524
* Protect against retry delay overflows by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1522
* Fix DelayAsync extension by [@martintmk](https://github.com/martintmk) in https://github.com/App-vNext/Polly/pull/1525

## 8.0.0-alpha.8

* Updates for 8.0.0-alpha.7 by [@martincostello](https://github.com/martincostello) in https://github.com/App-vNext/Polly/pull/1433
Expand Down
2 changes: 1 addition & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<PropertyGroup>
<MicrosoftExtensionsVersion>7.0.0</MicrosoftExtensionsVersion>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<PollyVersion>8.0.0-alpha.8</PollyVersion>
<PollyVersion>8.0.0-alpha.9</PollyVersion>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="coverlet.msbuild" Version="6.0.0" />
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
> Major performance improvements are on the way! Please see our [blog post](https://www.thepollyproject.org/2023/03/03/we-want-your-feedback-introducing-polly-v8/) to learn more and provide feedback in the [related GitHub issue](https://github.com/App-vNext/Polly/issues/1048).
>
> :rotating_light::rotating_light: **Polly v8 feature-complete!** :rotating_light::rotating_light:
> - Polly v8 Alpha 8 is now available on [NuGet.org](https://www.nuget.org/packages/Polly/8.0.0-alpha.8)
> - The Alpha 8 version is considered feature-complete. After completing [review of the API](https://github.com/App-vNext/Polly/pull/1233) to address unresolved issues, we will move on to a Beta release.
> - Polly v8 Alpha 9 is now available on [NuGet.org](https://www.nuget.org/packages/Polly/8.0.0-alpha.9)
> - The Alpha 9 version is considered feature-complete. After completing [review of the API](https://github.com/App-vNext/Polly/pull/1233) to address unresolved issues, we will move on to a Beta release.
> - The v8 docs are not yet finished, but you can take a look at sample code in these locations:
> - Within the repo's new [Samples folder](https://github.com/App-vNext/Polly/tree/main/samples)
> - By reading `Polly.Core`'s [README](https://github.com/App-vNext/Polly/blob/main/src/Polly.Core/README.md)
Expand Down
32 changes: 16 additions & 16 deletions samples/DependencyInjection/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,49 +5,49 @@
using Polly.Timeout;

// ------------------------------------------------------------------------
// 1. Register your resilience strategy
// 1. Register your resilience pipeline
// ------------------------------------------------------------------------

var serviceProvider = new ServiceCollection()
.AddLogging(builder => builder.AddConsole().SetMinimumLevel(LogLevel.Debug))
// Use "AddResilienceStrategy" extension method to configure your named strategy
.AddResilienceStrategy("my-strategy", (builder, context) =>
// Use "AddResiliencePipeline" extension method to configure your named pipeline
.AddResiliencePipeline("my-pipeline", (builder, context) =>
{
// You can resolve any service from DI when building the strategy
// You can resolve any service from DI when building the pipeline
context.ServiceProvider.GetRequiredService<ILoggerFactory>();

builder.AddTimeout(TimeSpan.FromSeconds(1));
})
// You can also register result-based (generic) resilience strategies
// 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)
.AddResilienceStrategy<string, HttpResponseMessage>("my-http-strategy", builder =>
.AddResiliencePipeline<string, HttpResponseMessage>("my-http-pipeline", builder =>
{
builder.AddTimeout(TimeSpan.FromSeconds(1));
})
.BuildServiceProvider();

// ------------------------------------------------------------------------
// 2. Retrieve and use your resilience strategy
// 2. Retrieve and use your resilience pipeline
// ------------------------------------------------------------------------

// Resolve the resilience strategy provider for string-based keys
ResilienceStrategyProvider<string> strategyProvider = serviceProvider.GetRequiredService<ResilienceStrategyProvider<string>>();
// Resolve the resilience pipeline provider for string-based keys
ResiliencePipelineProvider<string> pipelineProvider = serviceProvider.GetRequiredService<ResiliencePipelineProvider<string>>();

// Retrieve the strategy by name
ResilienceStrategy strategy = strategyProvider.GetStrategy("my-strategy");
// Retrieve the pipeline by name
ResiliencePipeline pipeline = pipelineProvider.GetPipeline("my-pipeline");

// Retrieve the generic strategy by name
ResilienceStrategy<HttpResponseMessage> genericStrategy = strategyProvider.GetStrategy<HttpResponseMessage>("my-http-strategy");
// Retrieve the generic pipeline by name
ResiliencePipeline<HttpResponseMessage> genericPipeline = pipelineProvider.GetPipeline<HttpResponseMessage>("my-http-pipeline");

try
{
// Execute the strategy
// Execute the pipeline
// Notice in console output that telemetry is automatically enabled
await strategy.ExecuteAsync(async token => await Task.Delay(10000, token), CancellationToken.None);
await pipeline.ExecuteAsync(async token => await Task.Delay(10000, token), CancellationToken.None);
}
catch (TimeoutRejectedException)
{
// The timeout strategy cancels the user callback and throws this exception
// The timeout pipeline cancels the user callback and throws this exception
Console.WriteLine("Timeout!");
}
33 changes: 14 additions & 19 deletions samples/Extensibility/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
// ------------------------------------------------------------------------
// Usage of custom strategy
// ------------------------------------------------------------------------
var strategy = new CompositeStrategyBuilder()
var pipeline = new ResiliencePipelineBuilder()
// This is custom extension defined in this sample
.AddMyResilienceStrategy(new MyResilienceStrategyOptions
.AddMyResilienceStrategy(new MySimpleStrategyOptions
{
OnCustomEvent = args =>
{
Expand All @@ -16,20 +16,20 @@
})
.Build();

// Execute the strategy
strategy.Execute(() => { });
// Execute the pipeline
pipeline.Execute(() => { });

// ------------------------------------------------------------------------
// SIMPLE EXTENSIBILITY MODEL (INLINE STRATEGY)
// ------------------------------------------------------------------------

strategy = new CompositeStrategyBuilder()
pipeline = new ResiliencePipelineBuilder()
// Just add the strategy instance directly
.AddStrategy(new MySimpleStrategy())
.AddStrategy(_ => new MySimpleStrategy(), new MySimpleStrategyOptions())
.Build();

// Execute the strategy
strategy.Execute(() => { });
// Execute the pipeline
pipeline.Execute(() => { });

internal class MySimpleStrategy : ResilienceStrategy
{
Expand All @@ -40,11 +40,6 @@ protected override ValueTask<Outcome<TResult>> ExecuteCore<TResult, TState>(
{
Console.WriteLine("MySimpleStrategy executing!");

// The "context" holds information about execution mode
Console.WriteLine("context.IsSynchronous: {0}", context.IsSynchronous);
Console.WriteLine("context.ResultType: {0}", context.ResultType);
Console.WriteLine("context.IsVoid: {0}", context.IsVoid);

// The "state" is an ambient value passed by the caller that holds the state.
// Here, we do not do anything with it, just pass it to the callback.

Expand All @@ -65,7 +60,7 @@ protected override ValueTask<Outcome<TResult>> ExecuteCore<TResult, TState>(
public readonly record struct OnCustomEventArguments(ResilienceContext Context);

// 1.B Define the options.
public class MyResilienceStrategyOptions : ResilienceStrategyOptions
public class MySimpleStrategyOptions : ResilienceStrategyOptions
{
// Use the arguments in the delegates.
// The recommendation is to use asynchronous delegates.
Expand All @@ -79,13 +74,13 @@ public class MyResilienceStrategyOptions : ResilienceStrategyOptions
// The strategy should be internal and not exposed as part of any public API.
// Instead, expose options and extensions for resilience strategy builder.
//
// For reactive startegies, you can use ReactiveResilienceStrategy<T> as base class.
// 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;

public MyResilienceStrategy(ResilienceStrategyTelemetry telemetry, MyResilienceStrategyOptions options)
public MyResilienceStrategy(ResilienceStrategyTelemetry telemetry, MySimpleStrategyOptions options)
{
this.telemetry = telemetry;
this.onCustomEvent = options.OnCustomEvent;
Expand Down Expand Up @@ -122,13 +117,13 @@ protected override async ValueTask<Outcome<TResult>> ExecuteCore<TResult, TState
}

// ------------------------------------------------------------------------
// 3. Expose new extensions for CompositeStrategyBuilder
// 3. Expose new extensions for ResiliencePipelineBuilder
// ------------------------------------------------------------------------

public static class MyResilienceStrategyExtensions
{
// Add new extension that works for both "CompositeStrategyBuilder" and "CompositeStrategyBuilder<T>"
public static TBuilder AddMyResilienceStrategy<TBuilder>(this TBuilder builder, MyResilienceStrategyOptions options) where TBuilder : CompositeStrategyBuilderBase
// 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),
Expand Down
38 changes: 25 additions & 13 deletions samples/GenericStrategies/Program.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
using Polly;
using System.Net;
using Polly;
using Polly.Fallback;
using Polly.Retry;
using Polly.Timeout;
using System.Net;

// ----------------------------------------------------------------------------
// Create a generic resilience strategy using CompositeStrategyBuilder<T>
// Create a generic resilience pipeline using ResiliencePipelineBuilder<T>
// ----------------------------------------------------------------------------

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

ResilienceStrategy<HttpResponseMessage> strategy = new CompositeStrategyBuilder<HttpResponseMessage>()
ResiliencePipeline<HttpResponseMessage> pipeline = new ResiliencePipelineBuilder<HttpResponseMessage>()
.AddFallback(new FallbackStrategyOptions<HttpResponseMessage>
{
FallbackAction = _ =>
Expand All @@ -20,14 +20,18 @@
return Outcome.FromResultAsTask(new HttpResponseMessage(HttpStatusCode.OK));
},
// You can also use switch expressions for succinct syntax
ShouldHandle = outcome => outcome switch
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
},
OnFallback = _ => { Console.WriteLine("Fallback!"); return default; }
OnFallback = _ =>
{
Console.WriteLine("Fallback!");
return default;
}
})
.AddRetry(new RetryStrategyOptions<HttpResponseMessage>
{
Expand All @@ -36,20 +40,28 @@
.HandleResult(r => r.StatusCode == HttpStatusCode.InternalServerError)
.Handle<HttpRequestException>(),
// Register user callback called whenever retry occurs
OnRetry = outcome => { Console.WriteLine($"Retrying '{outcome.Result?.StatusCode}'..."); return default; },
BaseDelay = TimeSpan.FromMilliseconds(400),
BackoffType = RetryBackoffType.Constant,
RetryCount = 3
OnRetry = arguments =>
{
Console.WriteLine($"Retrying '{arguments.Outcome.Result?.StatusCode}'...");
return default;
},
Delay = TimeSpan.FromMilliseconds(400),
BackoffType = DelayBackoffType.Constant,
MaxRetryAttempts = 3
})
.AddTimeout(new TimeoutStrategyOptions
{
Timeout = TimeSpan.FromSeconds(1),
// Register user callback called whenever timeout occurs
OnTimeout = _ => { Console.WriteLine("Timeout occurred!"); return default; }
OnTimeout = _ =>
{
Console.WriteLine("Timeout occurred!");
return default;
}
})
.Build();

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