Как я могу получить счетчик повторных попыток в делегате, выполняемом с помощью политики повторных попыток Polly?

Я использую Polly для повторения запросов в моем веб-приложении C #. Мой образец кода включен в этот пост. Код работает, как ожидалось, но последний параметр, переданный в CreateFile () (в настоящее время жестко заданный как 0), должен быть значением retryAttempt. Как я могу получить значение retryAttempt в Execute Action?

return Policy
    .Handle<HttpException>(x => x.StatusCode == (HttpStatusCode)429)
    .Or<StorageException>()
    .WaitAndRetry(maxRetryCount, retryAttempt => TimeSpan.FromMilliseconds(Math.Pow(retryIntervalMs, retryAttempt)))
    .Execute(() => CreateFile(fileContent, containerName, fileName, connectionString, 0));

person user10816949    schedule 20.12.2018    source источник
comment
Также обратите внимание, что у Полли есть особые перегрузки повторных попыток, полезные для 429 ответов. если в ответе 429 указано, как долго ждать. Политика повторных попыток может быть настроена на ожидание ровно той продолжительности повторной попытки, которая указана в ответе 429.   -  person mountain traveller    schedule 21.12.2018


Ответы (1)


Polly не предоставляет .Execute(...) перегрузку, в которой счетчик повторов является одним из входных параметров делегата, переданного .Execute(...). Это связано с тем, что повторная попытка - это только одна из многих политик Polly, тогда как форма .Execute(...) перегрузок должна быть общей для всех типов политик.

Для случая использования, описанного в вопросе, просто:

int count = 0;
return Policy
    .Handle<HttpException>(x => x.StatusCode == (HttpStatusCode)429)
    .Or<StorageException>()
    .WaitAndRetry(maxRetryCount, retryAttempt => TimeSpan.FromMilliseconds(Math.Pow(retryIntervalMs, retryAttempt)))
    .Execute(() => CreateFile(fileContent, containerName, fileName, connectionString, count++));

В альтернативном подходе используется область видимости выполнения Polly Polly.Context: ее экземпляр перемещается с каждым выполнением и доступен для всех частей выполнения.

Политика повторных попыток уже передает счетчик повторных попыток onRetry делегату, поэтому политика может зафиксировать его в Context области выполнения:

var retryPolicyCapturingCountIntoContext =
    Policy
        .Handle<HttpException>(x => x.StatusCode == (HttpStatusCode)429)
        .Or<StorageException>()
        .WaitAndRetry(
            maxRetryCount,
            retryAttempt => TimeSpan.FromMilliseconds(Math.Pow(retryIntervalMs, retryAttempt)),
            onRetry: (response, delay, retryCount, context) =>
            {
                context["retrycount"] = retryCount;
            });

В делегате, выполняемом с помощью политики, мы можем выбрать счетчик повторов из Context (заботясь о том, чтобы обработать случай, когда повторных попыток еще не было):

retryPolicyCapturingCountIntoContext
    .Execute(context =>
    {
        int retryCount = (context.TryGetValue("retrycount", out var retryObject) && retryObject is int count) ? count : 0;
        CreateFile(fileContent, containerName, fileName, connectionString, retryCount);
    }, new Context());

Если вы предпочитаете избегать шума context.TryGetValue(...) защитного кода, вы также можете выбрать, чтобы вы всегда инициализировали context["retrycount"] перед запуском выполнения:

var myContext = new Polly.Context { {"retrycount ", 0} };
retryPolicyCapturingCountIntoContext
    .Execute(
         context => CreateFile(fileContent, containerName, fileName, connectionString, (int)context["retrycount"]),
         myContext);


Для пользователей, которые хотят фиксировать количество повторов для каждой попытки, как это происходит, например, для ведения журнала, см. Примеры повторных попыток Polly, показывающие, как retryCount передается в качестве входного параметра onRetry делегату, который можно настроить в политике. Дополнительные примеры здесь.

Для пользователей, которые хотят фиксировать общее количество повторных попыток, использованных для успешной операции, обобщенным способом - скажем, для телеметрии как части некоторого общего кода инфраструктуры диспетчеризации выполнения - см. эти примеры в блоге Стива Гордона, в которых используется подход на основе Context.

person mountain traveller    schedule 21.12.2018