Установите политику Polly по умолчанию с помощью Flurl

В настоящее время я использую Polly и Flurl вместе, но у меня есть общая политика повторных попыток, которую я должен добавлять к каждому запросу. Я заметил, что Polly позволяет вам установить значение по умолчанию с помощью AddPolicyHandler (...), но для этого требуется IHttpClientBuilder, и я не вижу никакого способа получить его от Flurl.

Я думал, что перегрузка DefaultHttpClientFactory может быть подходящим вариантом, но это дает мне доступ только к HttpClient, а не к IHttpClientBuilder.

Я знаю, что могу создавать свои собственные HttpClients и передавать их во Flurl, но я бы предпочел избежать этого, если смогу, поскольку я бы хотел, чтобы Flurl управлял их жизненным циклом.

Есть ли в настоящее время способ делать то, что я хочу делать?


person Iain Brown    schedule 11.09.2018    source источник


Ответы (1)


Отличный вопрос. Flurl предоставляет для этого все необходимые ловушки. Сначала определите DelegatingHandler, который принимает политику Polly:

public class PollyHandler : DelegatingHandler
{
    private readonly IAsyncPolicy<HttpResponseMessage> _policy;

    public PollyHandler(IAsyncPolicy<HttpResponseMessage> policy) {
        _policy = policy;
    }

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
        return _policy.ExecuteAsync(ct => base.SendAsync(request, ct), cancellationToken);
    }
}

Затем создайте настраиваемый IHttpClientFactory, который возвращает ваш настраиваемый обработчик с обработчиком по умолчанию в качестве InnerHandler:

public class PollyFactory : DefaultHttpClientFactory
{
    private readonly IAsyncPolicy<HttpResponseMessage> _policy;

    public PollyFactory(IAsyncPolicy<HttpResponseMessage> policy) {
        _policy = policy;
    }

    public override HttpMessageHandler CreateMessageHandler() {
        return new PollyHandler(_policy) {
            InnerHandler = base.CreateMessageHandler()
        };
    }
}

Наконец, при запуске приложения определите свою политику и зарегистрируйте ее во Flurl:

var policy = Policy
    .Handle<HttpRequestException>()
    .OrResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
    .RetryAsync(5);

FlurlHttp.Configure(settings => settings.HttpClientFactory = new PollyFactory(policy));

Одно важное замечание: этот подход не будет работать с политикой, обрабатывающей FlurlHttpException. Это потому, что вы здесь перехватываете звонки на уровне HttpMessageHandler. Flurl преобразует ответы и ошибки в FlurlHttpExceptionсек выше в стеке, поэтому при таком подходе они не будут перехвачены / повторены. Политика в приведенном выше примере перехватывает HttpRequestException и HttpResponseMessage (с кодами состояния, отличными от 2XX), которые будут работать.

person Todd Menier    schedule 11.09.2018
comment
Когда возникает исключение FlurlHttpException по сравнению с HttpRequestException? - person Robin; 15.04.2019
comment
@Robin HttpRequestException выбрасывается внутри любого обработчика сообщений, который вы настроили, как указано выше. FlurlHttpException генерируется Flurl после завершения любого HTTP-вызова после того, как эти обработчики были запущены. Если вы выполняете команду try / catch в рамках обычного потока логики вашего приложения, FlurlHttpException - это то, что вам нужно поймать. - person Todd Menier; 16.04.2019
comment
Как пользоваться без фабрики? Это вызывает его только один раз string s = await Policy .Handle<HttpRequestException> () .OrResult <HttpResponseMessage> (r => !r.IsSuccessStatusCode) .RetryAsync (5) .ExecuteAsync (() => { Console.WriteLine ("Retry"); return "http://127.0.0:7071/".GetAsync (); }) .ReceiveString () .ConfigureAwait (false); - person Robin; 16.04.2019
comment
@Robin Задайте новый вопрос. - person Todd Menier; 16.04.2019
comment
Хорошая идея, форматирование не работает в комментариях, внесено множество изменений и невозможно отформатировать должным образом stackoverflow.com/questions/55718410/ - person Robin; 17.04.2019
comment
@ToddMenier По словам Стивена Клири, не рекомендуется использовать Polly внутри HttpClient: stackoverflow.com/questions/56769241/ - person AndersBaumann; 15.12.2019