I am trying to upgrade Polly to v8, re-writing policies to utilize new ResiliencePipiline. At couple of places I am using HttpPolicyExtensions.HandleTransientHttpError()
HttpPolicyExtensions
.HandleTransientHttpError()
.WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
Looking at the source code I've endup with something like this:
new ResiliencePipelineBuilder<HttpResponseMessage>()
.AddRetry(
new RetryStrategyOptions<HttpResponseMessage>()
{
ShouldHandle = new PredicateBuilder<HttpResponseMessage>()
.Handle<HttpRequestException>()
.HandleResult(response => response.StatusCode >= HttpStatusCode.InternalServerError || response.StatusCode == HttpStatusCode.RequestTimeout),
MaxRetryAttempts = 3,
DelayGenerator = static opt => ValueTask.FromResult((TimeSpan?)TimeSpan.FromSeconds(Math.Pow(2, opt.AttemptNumber))),
})
.Build();
Yes, that looks good. If you want to have a bit more performant version then you can use switch expression instead of PredicateBuilder
var options = new RetryStrategyOptions<HttpResponseMessage>
{
ShouldHandle = static args => args.Outcome switch
{
{ Exception: HttpRequestException } => PredicateResult.True(),
{ Result.StatusCode: HttpStatusCode.RequestTimeout} => PredicateResult.True(),
{ Result.StatusCode: >= HttpStatusCode.InternalServerError } => PredicateResult.True(),
_ => PredicateResult.False()
}
};
Please also note here the usage of static anonymous functions
.
Update #1
This could be easily extracted into a util method to embrace reusablity.
public static class PollyUtils
{
public static ValueTask<bool> HandleTransientHttpError(
Outcome<HttpResponseMessage> outcome)
=> outcome switch
{
{ Exception: HttpRequestException } => PredicateResult.True(),
{ Result.StatusCode: HttpStatusCode.RequestTimeout} => PredicateResult.True(),
{ Result.StatusCode: >= HttpStatusCode.InternalServerError } => PredicateResult.True(),
_ => PredicateResult.False()
};
}