Платформа Polly CircuitBreakerAsync не повторяет попытку при возникновении исключения

Я использую платформу Polly для обработки временных сбоев. Для синхронных операций политика автоматического выключателя Polly работает нормально, но когда я создал ее асинхронную версию, она не пытается выполнить повторно. Пожалуйста, предложите:

Асинхронный метод:

private async static Task HelloWorld()
    {
        if (DateTime.Now < programStartTime.AddSeconds(10))
        {
            Console.WriteLine("Task Failed.");
            throw new TimeoutException();
        }
        await Task.Delay(TimeSpan.FromSeconds(1));
        Console.WriteLine("Task Completed.");
    }

Политика асинхронности автоматического выключателя Polly

private static void AsyncDemo3(Func<Task> action)
    {
        programStartTime = DateTime.Now;

        Policy policy = Policy
            .Handle<TimeoutException>()
            .CircuitBreakerAsync(3, TimeSpan.FromSeconds(2));
        try
        {
            var a = policy.ExecuteAndCaptureAsync(action, true).GetAwaiter().GetResult();
        }
        catch (AggregateException ex)
        {
            Console.WriteLine("Exception: " + ex.Message);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Exception: " + ex.Message);
        }
    }

Выполнение политики автоматического выключателя Polly:

AsyncDemo3 (HelloWorld);

Пожалуйста, помогите найти и решить проблему.


person Demon Hunter    schedule 04.04.2016    source источник


Ответы (2)


Я полагаю, вы неправильно поняли, что делает политика автоматического выключателя.

Что он делает, так это то, что если вы вызываете его заданное количество раз, и каждый раз он терпит неудачу, он перестанет вызывать данный метод на определенное время. Но сам по себе не повторяет попытку.

Итак, чтобы сделать то, что я думаю, вы хотите сделать, вам нужно объединить политику повторных попыток с политикой автоматического выключателя. Один из способов сделать это:

Policy retryPolicy = Policy.Handle<TimeoutException>().RetryAsync(3);

Policy circuitBreakerPolicy = Policy
    .Handle<TimeoutException>()
    .CircuitBreakerAsync(3, TimeSpan.FromSeconds(2));

try
{
    retryPolicy.ExecuteAsync(() => circuitBreakerPolicy.ExecuteAsync(action, true))
        .GetAwaiter().GetResult();
}
…

Вывод этого кода:

Task Failed.
Task Failed.
Task Failed.
Exception: The circuit is now open and is not allowing calls.
person svick    schedule 04.04.2016
comment
Полли также добавила PolicyWrap, который может улучшить синтаксис для объединения политик. краткий: retryPolicy.WrapAsync(circuitBreakerPolicy).ExecuteAsync(...) - person mountain traveller; 01.04.2017

Рекомендуем создать обе политики и объединить их с помощью PolicyWrap следующим образом.

Создание политики

 var circuitBreakerPolicy = Policy
        .Handle<TimeoutException>()
        .CircuitBreakerAsync(3, TimeSpan.FromSeconds(2));
 var retryPolicy = Policy.Handle<TimeoutException>().RetryAsync(3);

 // Combined policy: outermost first, innermost last
 var policy = Policy.WrapAsync(retryPolicy, circuitBreakerPolicy);

Использование политики

 await this.policy.ExecuteAsync(async () => await SomeFooMethodAsync(cancellationToken));
person user3613932    schedule 18.02.2020