Reputation: 45
How to filter specific endpoint for retry policy using Polly
All client requests MyServiceHttpClient
will retry. How disable retry policy specific api?
services.AddHttpClient<MyServiceHttpClient>(client =>
{
/* configuration */
})
.AddPolicyHandler((serviceProvider, request) =>
HttpPolicyExtensions.HandleTransientHttpError()
.WaitAndRetryAsync(3,
sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
onRetry: (outcome, timespan, retryAttempt, context) =>
{
serviceProvider.GetService<ILogger<MyServiceHttpClient>>()
.LogWarning("Delaying for {delay}ms, then making retry {retry}.", timespan.TotalMilliseconds, retryAttempt);
}
));
Upvotes: 3
Views: 971
Reputation: 22829
Even though Guru Stron's proposed solution works it is pretty hard to maintain IMHO.
Let me present you an alternative solution. The WaitAndRetryAsync
has many different overloads. Some requires a retryCount
parameters, while others don't. If you use an overload which requires a IEnumerable<TimeSpan> retryDurations
parameter then you can do the following:
.AddPolicyHandler((serviceProvider, request) =>
HttpPolicyExtensions.HandleTransientHttpError()
.WaitAndRetryAsync(
GetRetryDelays(request),
(_, timespan, retryAttempt, __) =>
{
//logging
}));
Now lets see the related GetRetryDelays
implementation
private static readonly Uri DoNotRetryUri = new("https://...");
private const int MaxRetryAttempt = 3;
private static IEnumerable<TimeSpan> GetRetryDelays(HttpRequestMessage request)
{
if (request.RequestUri == DoNotRetryUri)
return Array.Empty<TimeSpan>();
return Enumerable.Range(0, MaxRetryAttempt)
.Select(retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)))
.ToArray();
}
[
00:00:01
,
00:00:02
,
00:00:04
]
Upvotes: 1
Reputation: 143098
You can try using no-op policy:
builder.Services.AddHttpClient<MyServiceHttpClient>(client =>
{
/* configuration */
})
.AddPolicyHandler((serviceProvider, request) =>
request.RequestUri.PathAndQuery.StartsWith("/api/") // your predicate
? Policy.NoOpAsync<HttpResponseMessage>() // <- no op for matching predicate
: HttpPolicyExtensions.HandleTransientHttpError()
.WaitAndRetryAsync(3,
sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
onRetry: (outcome, timespan, retryAttempt, context) =>
{
serviceProvider.GetService<ILogger<MyServiceHttpClient>>()
.LogWarning("Delaying for {delay}ms, then making retry {retry}.",
timespan.TotalMilliseconds, retryAttempt);
}
));
Or another approach would be to repeat the HandleTransientHttpError
logic but with adding corresponding filter.
Upvotes: 2