Я хочу переехать из Полли в Microsoft.Extensions.Http.Resilience
AddStandardResilienceHandler
. Мой сокращенный код Polly следующий:
services.AddHttpClient<MyService>()
.AddPolicyHandler((_, _) =>
{
return HttpPolicyExtensions.HandleTransientHttpError()
.Or<HttpRequestException>(exception => exception.StatusCode == HttpStatusCode.Conflict)
.WaitAndRetryAsync(3, sleepDurationProvider: i => TimeSpan.FromSeconds(i * 2));
});
Важнейшая часть здесь — HttpPolicyExtensions.HandleTransientHttpError().Or<HttpRequestException>(exception => exception.StatusCode == HttpStatusCode.Conflict)
, где я хочу добавить собственный случай ошибки, в котором я хочу повторить попытку.
Я действительно не знаю, как преобразовать это в новую конфигурацию.
Насколько я понимаю документацию, я могу установить пользовательскую функцию options.Retry.ShouldHandle
(получает или устанавливает предикат, который определяет, следует ли выполнять повторную попытку для данного результата.)
Но тогда я не могу добавить регистр, вместо этого мне придется установить всю функцию. Реализация Microsoft по умолчанию ShouldHandle
выглядит следующим образом:
public static readonly Func<TArgs, ValueTask<bool>> HandleOutcome = args => args.Outcome.Exception switch
{
OperationCanceledException => PredicateResult.False(),
Exception => PredicateResult.True(),
_ => PredicateResult.False()
};
Моя текущая конфигурация выглядит так:
services.AddHttpClient<MyService>()
.AddStandardResilienceHandler()
.Configure((options, _) =>
{
options.Retry.ShouldHandle = args =>
{
if (args.Outcome.Result?.StatusCode == HttpStatusCode.Conflict)
{
return PredicateResult.True();
}
return args.Outcome.Exception switch
{
OperationCanceledException => PredicateResult.False(),
not null => PredicateResult.True(),
_ => PredicateResult.False()
};
};
});
Эквивалентно ли это первоначальной реализации Polly?
Исходный HandleTransientHttpError
можно перенести на V8 следующим образом:
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()
};
}
Значение по умолчанию ShouldHandle
определено для срабатывания каждого исключения, кроме OperationCanceledException
. Если вы отменили операцию, возможно, вам не захочется ее повторять.
Это значение по умолчанию может иметь смысл не для каждого варианта использования. Например, HttpClient во многих случаях может выдавать InvalidOperationException
:
BaseAddress
или Timeout
после отправки запросаПовторная попытка не изменит результат операции.
Вышеупомянутую служебную функцию можно легко расширить и для запуска Conflict
.
Кстати, AddStandardResilienceHandler
регистрирует стратегию повтора (среди других стратегий). В результате повтора MustHandle происходит следующих событий:
HttpRequestException
TimeoutRejectedException
HttpStatusCode.InternalServerErrorCode
(5XX)HttpStatusCode.RequestTimeout
(408)HttpStatusCode.TooManyRequests
(429)