Как реализовать политику повторов на основе содержимого ответа HTML?
Я использую WebClient для чтения некоторого HTML-контента с веб-сайта, используя класс System.Net.WebClient. Иногда этот веб-сайт дает мне 200 ответов с тегом заголовка, в котором говорится, что лимит вызовов превышен, и я должен повторить попытку через несколько секунд. То, что я ищу, - это некоторая политика Retry, которая читает этот тег заголовка и проверяет, что лимит вызовов превышает ошибку. Если эта ошибка присутствует, следует повторить попытку. Вот пример кода, который делает этот звонок на сайт
using (var wc = new GZipWebClient())
{
// this html sometimes contain <title> with error message
html = await wc.DownloadStringTaskAsync(url);
}
Я был бы очень признателен, если бы кто-нибудь смог предоставить пример кода о том, как реализовать логику повторных попыток с использованием Polly для этого сценария.
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());
Политики 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 также предоставляет специальные шаблоны, позволяющие вам создать политику, которая автоматически ожидает именно то время повторения, которое указано в ответе.