Используя Polly v8 и RestSharp, как мне построить Generic ResiliencePipeline для учета повторных попыток заголовка ответC#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Используя Polly v8 и RestSharp, как мне построить Generic ResiliencePipeline для учета повторных попыток заголовка ответ

Сообщение Anonymous »

У меня есть клиентский класс API, созданный с использованием _client = new RestSharp.RestClient(...); с методами этой формы:
public async Task PostAsync(string resource, TRequest payload) where TRequest : class
{
var request = new RestRequest(resource);
request.AddJsonBody(payload);
var response = await PolicyFactory.RestSharpPolicy(_logger).ExecuteAsync(
async token => await _client.ExecuteAsync(request, Method.Post, token));
LogAndRaiseErrors(request, response);
return response.Data.Data;
}

Вот метод LogAndRaiseErrors:
protected void LogAndRaiseErrors(RestRequest request, RestResponse response)
{
if (response.StatusCode != HttpStatusCode.OK)
{
_logger.LogError("API Error:{response}", SerializeResponse(response));
throw new BigCommerceException(response.Content);
}
_logger.LogDebug("B2B API Call:\n{response}", SerializeResponse(response));
}

Я просмотрел документацию Polly, но она немного скудна.

Как мне построить ResiliencePipeline, используемый в PostAsync метод для достижения следующих основных целей:
  • Прочитайте ответ.Headers.FirstOrDefault(h=>h.Name?.ToLower() == "retry -after")?.Значение и задержка для указанных секунд, чего существующий код вообще не делает.
  • Я считаю, что повторная попытка после должна влиять на все потоки, которые могут вызывать данный API? добавить автоматический выключатель?
Были бы полезны любые указания на второстепенные цели:
  • Регистрируйте каждый запрос (в настоящее время это делается в LogAndRaiseErrorsMethod).
  • Регистрируйте повторные попытки, включая задержку, указанную в заголовке.
  • Переместите LogAndRaiseErrors(... ) в политику, чтобы политика могла обрабатывать журналирование и любые исключения.
  • Добавьте политику для повторных попыток в случае сетевых сбоев/тайм-аутов и т. д.
  • Я подозреваю, что нам нужен некоторый джиттер (это для чего он нужен?), чтобы не все потоки одновременно загружали API?
ОБНОВЛЕНИЕ здесь что я пробовал:

Я думаю, что повторная попытка работала правильно, но не автоматический выключатель.
Я перенес создание конвейера в конструктор, поэтому существует только один конвейер (журнал показывает, что это звонили один раз)
public ApiClient(..., ILogger logger)
{
...
_client = client;
_resiliencePipeline = PolicyFactory.GetRestSharpPolicy(_logger);
}

public async Task GetAsync(string resource)
{...}

public async Task PostAsync(string resource, TRequest payload) where TRequest : class
{
var request = new RestRequest(resource);
request.AddJsonBody(payload);
var response = await _resiliencePipeline.ExecuteAsync(
async token => await _client.ExecuteAsync(request, Method.Post, token));
LogAndRaiseErrors(request, response);
return response.Data.Data;
}

Вот мой конвейер, но я никогда не вижу записей в журнале прерывателя цепи, но вижу много записей в журнале повторных попыток.
public static class PolicyFactory
{

public static ResiliencePipeline GetRestSharpPolicy(ILogger logger)
{
logger.LogInformation("Building ResiliencePipeline");
return new ResiliencePipelineBuilder()
.AddCircuitBreaker(new CircuitBreakerStrategyOptions
{
FailureRatio = 0,
ShouldHandle = new PredicateBuilder()
.HandleResult(static result => result.StatusCode == HttpStatusCode.TooManyRequests),

OnOpened = args =>
{
logger.LogWarning("Circuit Breaker Opened on {StatusCode} for {Duration}s ({ResponseUri})",
args.Outcome.Result.StatusCode, args.BreakDuration.TotalSeconds, args.Outcome.Result.ResponseUri);
return ValueTask.CompletedTask;
},
OnClosed = args =>
{
logger.LogWarning("Circuit Breaker Closed on {StatusCode} ({ResponseUri})",
args.Outcome.Result.StatusCode, args.Outcome.Result.ResponseUri);
return ValueTask.CompletedTask;
}
})
.AddRetry(new RetryStrategyOptions
{
ShouldHandle = new PredicateBuilder()
.HandleResult(static result => result.StatusCode == HttpStatusCode.TooManyRequests),
DelayGenerator = delayArgs =>
{
var retryAfter = delayArgs.Outcome.Result.Headers.FirstOrDefault(h => h.Name?.ToLower() == "retry-after")?.Value.ToString();
return int.TryParse(retryAfter, out var seconds)
? new ValueTask(TimeSpan.FromSeconds(seconds))
: new ValueTask(TimeSpan.FromSeconds(0.5));
},
MaxRetryAttempts = 5,
OnRetry = args =>
{
logger.LogWarning("Retry Attempt:{Attempt} Delay:{Delay}",
args.AttemptNumber, args.RetryDelay);
return ValueTask.CompletedTask;
}
})
.Build();
}
}


Подробнее здесь: https://stackoverflow.com/questions/787 ... ipeline-to
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Как политики повторных попыток Polly указывают на превышение количества повторных попыток?
    Anonymous » » в форуме C#
    0 Ответы
    18 Просмотры
    Последнее сообщение Anonymous
  • Как политики повторных попыток Polly указывают на превышение количества повторных попыток?
    Anonymous » » в форуме C#
    0 Ответы
    24 Просмотры
    Последнее сообщение Anonymous
  • Метод не найден: RestSharp.IRestReuqest RestSharp.RestRequest.AddFile
    Anonymous » » в форуме C#
    0 Ответы
    73 Просмотры
    Последнее сообщение Anonymous
  • C# Polly, Polly не работает, если функция завершится
    Anonymous » » в форуме C#
    0 Ответы
    21 Просмотры
    Последнее сообщение Anonymous
  • Как я могу подавить журнал попыток выполнения при использовании Polly V8 ResiliencePipelineBuilder?
    Anonymous » » в форуме C#
    0 Ответы
    6 Просмотры
    Последнее сообщение Anonymous

Вернуться в «C#»