Polly v6 breaking changes - App-vNext/Polly GitHub Wiki
âšī¸ This documentation describes the previous Polly v7 API. If you are using the new v8 API, please refer to pollydocs.org.
Polly v6 introduced a number of breaking changes over v5.
Change | Summary rationale |
---|---|
Rationalise Execute() / ExecuteAsync() overloads |
Reduce the number of overloads; standardise to build a more consistent overload set going forward |
Rename ExecutionKey as OperationKey
|
Better communicate purpose; reduce confusion with similar-named key |
Rename ExecutionGuid as CorrelationId
|
Better communicate purpose; reduce confusion with similar-named key |
Publish Polly as strong-named only | Avoid diamond-dependency conflicts in the market going forward |
Upgrade supported targets | Modernise |
All .cs
changes are deprecated in Polly v5.9 with [Obsolete]
attributes.
As well as taking the delegate to execute, Polly Execute()
/ ExecuteAsync()
overloads commonly exist offering the following two parameters:
Parameter | Purpose |
---|---|
Context |
an execution Context , or dictionary data to populate that context |
CancellationToken |
a CancellationToken , when you want to pass a token to control cancellation of the policy or the executing delegate |
In Polly v5, some overloads existed where the Context context
or CancellationToken
parameters were passed but not used as input parameters to the delegate executed:
Task ExecuteAsync(Func<Task> action, Context context)
With such overloads, the passed Context
or CancellationToken
parameters influenced policy behaviour, but not executed delegate behaviour.
In v6 all such overloads were deprecated in favour of overloads where the action
delegate executed takes all passed parameters. For example, the overload quoted above would be deprecated in favour of:
Task ExecuteAsync(Func<Context, Task> action, Context context)
By aligning the parameters passed to the executed delegate with the input parameters to the executed delegate, we open up the possibility for adding future generic overloads allowing user-defined input parameters to be passed into the executed delegate without the use of closures:
Task<TResult> ExecuteAsync<T1, TResult>(Func<T1, Context, CancellationToken, Task<TResult>> func, T1 t1, Context context, CancellationToken token);
Task<TResult> ExecuteAsync<T1, T2, TResult>(Func<T1, T2, Context, CancellationToken, Task<TResult>> func, T1 t1, T2 t2, Context context, CancellationToken token);
Without the v6 standardisation of overloads, this would not be possible.
If you receive a compilation error that the overload no longer exists in v6, simply add Context
or CancellationToken
(as appropriate) as an input to the executed delegate.
ExecuteAsync()
overloads also offer the bool continueOnCapturedContext
optional parameter. This has never featured as an input parameter to async delegates executed through policies and no changes were made to this.
The following properties on Context
were renamed:
Old name | New name |
---|---|
ExecutionKey |
OperationKey |
ExecutionGuid |
CorrelationId |
Use the new property names.
To v5.9 Polly was published as separate nuget packages Polly
(unsigned) and Polly-Signed
. In the Polly <=v5.9 context, Signed actually means strong-named.
From Polly v6.0 only a single package, Polly
, is published, and it is strong-named.
ASPNET Core 2.1 offers deep integration with Polly for HttpClient
instances created through HttpClientFactory
. This allows the easy application of Polly resilience strategies to outbound calls through HttpClient
.
ASPNET Core 2.1 is strong-named so this was expected to significantly increase consumption of a strong-named form of Polly. That however would risk creating diamond-dependency conflicts which apparently have no solution for packages or projects which until then had consumed non-strong-named Polly (example) (good summary).
If we had left both non-strong-named and strong-named Polly in the market, we would have prolonged the possibility of these irresoluble conflicts into future months and years. Switching to a single, strong-named Polly limits the possibility of these diamond-dependency conflicts occurring, by there being only a single version in the market. The single strong-named package strategy is also the strategy used by high-download nuget packages such as NewtonSoft.Json, FluentValidation, and Serilog, and is the strategy recommended by the Microsoft ASP.NET team.
From v6.0 Polly also adopts the so-called Newtonsoft.Json versioning strategy described here to minimise onward impact:
- nuget package numbers follow full semver (Major.Minor.Patch increments) to differentiate bug-fixes, new-functionality-without-breaking-changes, and breaking-changes.
- Dlls partially follow Major.0.0 version numbering only (even if the true version is Major.Minor.Patch). This reduces the burden on projects which consume Polly of introducing excessive assembly binding redirects.
Reference: Further discussion.
Switch packages as follows:
Old package used | New package to use |
---|---|
Polly-Signed | Polly |
Polly | Polly |
Both non-strong-named DLLs and strong-named DLLs can reference strong-named DLLs, so whether your project uses strong-naming or not, you will be able to reference the new Polly v6 strong-named packages.