При запуске Политики Polly в приложении.NET Core она зависает после того, как перехвачено исключение

Я пытаюсь протестировать некоторый код повторной попытки Полли, который у меня есть в базовом приложении.NET Core. Я должен реализовать асинхронный метод (через унаследованный интерфейс):

public Task AddMessageAsync( ... ) { .. }

ПРИМЕЧАНИЕ: обратите внимание, что вышеописанный метод НЕ украшен async ключевое слово? Я сделал это нарочно.

Когда я пытаюсь подключиться к сторонней службе (серверу MQ кролика), где я сделал имя хоста этой службы, неправильно / опечатка... мой код синхронизации пытается... пытается.. и не удается и выдает исключение, Большой! но после этого.... код просто виснет? Я думал, что код должен просто повторять попытки:(

private static Policy CheckRabbitMQPolicy(ILogger logger)
{
    return Policy
        .Handle<Exception>()
        .WaitAndRetry(15, _ => TimeSpan.FromSeconds(2), (exception, timeSpan, __) => logger.LogWarning(...));
}

public Task AddMessageAsync(string content,
                            TimeSpan? timeToLive,
                            TimeSpan? initialVisibilityDelay,
                            CancellationToken cancellationToken)
{
    CheckRabbitMQPolicy(_logger).Execute(() =>
    {
        using (var connection = _factory.CreateConnection())
        {
            .... // snipped //
        }
    });

    return Task.CompletedTask;
}

Поэтому я подумал, что могу просто вернуть Task.CompletedTask; потому что в этом методе нет кода, который async/await, Но когда выдается исключение, оно обрабатывается (log.Warning(..) вызывается / прерывается, если там есть точка останова) ... но затем зависает.

Кто-нибудь может помочь подсказать, что здесь происходит?


РЕДАКТИРОВАТЬ 1:

Согласно ответу @jeremy-thompson ниже, я подумал, что могу попробовать изменить код на:

var policyResult = CheckRabbitMQPolicy(_logger).ExecuteAndCapture(() =>
{
    using (var connection = _factory.CreateConnection())
    {
        .... // snipped //
    }
});


return policyResult.Outcome == OutcomeType.Successful
    ? Task.CompletedTask
    : Task.FromException(policyResult.FinalException);

Так что тогда - пытается подключиться к плохому серверу - не удается и выдает исключение - сейчас выходит из ExecuteAndCapture() (не возвращается еще 14 раз...) - возвращает Task.FromException...

так что... немного ближе... но все равно не повторяю еще 14 раз...

1 ответ

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

Возможно, упрощая ваш код подобным образом, вы сможете выяснить, что не так в вашем случае. Удачи!

class Program
{
    static void Main()
    {
        var msg = new MyMessageClass();
        msg.AddMessageAsync("content", TimeSpan.MaxValue, TimeSpan.MaxValue, new CancellationToken());
    }
}

class MyMessageClass
{
    readonly ILogger _logger = NLog.LogManager.GetCurrentClassLogger();
    private static Policy CheckRabbitMQPolicy(ILogger logger)
    {
        return Policy
            .Handle<Exception>()
            .WaitAndRetry(14, _ => TimeSpan.FromSeconds(2),
                (exception, timeSpan, __) =>
                {
                    logger.Warn(exception.Message);
                });
    }
    public Task AddMessageAsync(string content,
        TimeSpan? timeToLive,
        TimeSpan? initialVisibilityDelay,
        CancellationToken cancellationToken)
    {
        var policyResult = CheckRabbitMQPolicy(_logger).ExecuteAndCapture(() => throw new Exception("Connection error"));

        return policyResult.Outcome == OutcomeType.Successful
            ? Task.CompletedTask
            : Task.FromException(policyResult.FinalException);
    }
}
Другие вопросы по тегам