4

我正在尝试测试我在基本 .NET Core 应用程序中的一些 Polly“重试”代码。我必须实现一个异步方法(通过继承的接口):

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

注意上面的方法没有用async关键字修饰吗?我是故意这样做的。

当我尝试连接到第 3 方服务(RabbitMQ 服务器)时,我在其中设置了该服务的主机名,不正确/错别字,我的同步代码尝试并失败并引发异常。伟大的!但在那之后,代码只是挂起?我认为代码应该继续重试。

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(..)如果那里有断点,则会被调用/中断),然后挂起。

我如何调试这里发生的事情?

编辑

根据@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 次。

4

1 回答 1

2

您应该始终尝试在演示您面临的问题的问题中提供一个最小的工作示例。我拿了你的代码并试图让它成为一个运行的例子,但一切似乎都按预期工作。它重新连接了 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);
    }
}
于 2018-11-26T07:56:19.430 回答