Как реализовать политику повторных попыток на основе содержимого ответа HTML?

Я использую WebClient для чтения некоторого html-контента с веб-сайта с использованием класса System.Net.WebClient. Иногда этот веб-сайт дает мне ответ 200 с тегом заголовка, в котором говорится, что лимит вызовов превышен, и я должен повторить попытку через несколько секунд. То, что я ищу, - это некоторая политика повторных попыток, которая читает, что читает этот тег заголовка и проверяет, не превышен ли лимит вызовов. Если эта ошибка присутствует, он должен повторить попытку. Вот пример кода, который делает этот вызов на веб-сайт

        using (var wc = new GZipWebClient())
        {
            // this html sometimes contain <title> with error message
            html = await wc.DownloadStringTaskAsync(url);
        }

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


person nafr1    schedule 15.02.2019    source источник


Ответы (2)


Используйте Polly, как обычно, и сгенерируйте пользовательское исключение, когда получите ошибку в html. Простой пример ниже.

    private async Task DownloadAsync()
    {
       using (var wc = new GZipWebClient())
       {
          // this html sometimes contain <title> with error message
          html = await wc.DownloadStringTaskAsync(url);

          if (html.Contains("My Error Message")) 
          {
              // Log Error
              throw new MyDownloadFailedException(html);
          }
      }
   }

   // In your calling method
   var p = Policy
            .Handle<MyDownloadFailedException>()
            .RetryForever(exception =>  
            {
                // log.Warning("Failed, retrying....");
            });

   p.ExecuteAsync(async() => await DownloadAsync());
person Murray Foxcroft    schedule 15.02.2019
comment
Спасибо .... Я пробовал это, но похоже, что он вообще не выполняет этот веб-вызов (даже не выдает исключение) - person nafr1; 15.02.2019
comment
Обновлен ответ на лучший пример - person Murray Foxcroft; 15.02.2019
comment
Также добавлена ​​ссылка на документацию Polly - person Murray Foxcroft; 15.02.2019

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

var retryPolicy = Policy
    .HandleResult<string>(s => s.Contains("whatever text triggers retry")) // or whatever more complicated predicate you want
    .Retry...Async(...); // whatever flavour of retry overload you want

private async Task DownloadAsync()
{
   using (var wc = new GZipWebClient())
   {
      // this html sometimes contain <title> with error message
      html = await retryPolicy.ExecuteAsync(() => wc.DownloadStringTaskAsync(url));
   }
}

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


Если ответ от вызываемого API также включает информацию о сколько времени ждать перед повторной попыткой ("RetryAfter"), то Polly также предоставляет конкретные шаблоны, позволяющие вам создать политику, которая автоматически ожидает точное время повторной попытки после указано в ответе.

person mountain traveller    schedule 16.02.2019