如果从未满足结果标准,策略能否抛出异常?

Can a policy throw an exception if the result criteria is never met?

我想使用 Polly 来处理我需要进行的 HTTP API 调用的结果。我将政策定义为:

var r = await Policy
    .HandleResult<DescribeApplicationVersionsResponse>(x => x.ApplicationVersions[0]?.Status != ApplicationVersionStatus.Processed)
    .WaitAndRetryAsync(10, retryAttempt => TimeSpan.FromSeconds(1), onRetry: (describeResponse, timeSpan, context) => {
        Console.WriteLine($"Application version was '{describeResponse.Result.ApplicationVersions[0].Status}', retrying in {timeSpan}");
    })
    .ExecuteAsync(() =>
        BeanstalkClient.DescribeApplicationVersionsAsync(describeApplicationVersionRequest)
    );

如果策略永远不会成功(即永远不会满足结果标准并且已超过重试限制)我想抛出一个异常,因为我的应用程序无法继续。

是否可以通过 Polly 策略构建器扩展方法来定义它?

如果为 Polly 重试策略配置的所有重试都用完而执行的委托没有成功,则重试策略将重新抛出不允许更多重试的异常,如记录in the Polly readme (foot of retry section) and Polly retry wiki


如果您想抛出与委托传播的异常不同的异常,您可以执行以下任一操作:

  • try/catch 然后扔别的东西; (或)
  • 使用 Polly .ExecuteAndCapture(...) 捕获,然后检查最终执行结果,并抛出您自己的自定义异常; (或)
  • 在重试策略之外使用 PolicyWrap to wrap a FallbackPolicy,并在 FallbackPolicy 中处理重试失败的异常,并在回退操作中重新抛出不同的自定义异常。

EDITED:反映 OP 的原始政策是处理结果而不是异常的事实。使用 FallbackPolicyPolicyWrap 的方法如下:

var retry = Policy
    .HandleResult<DescribeApplicationVersionsResponse>(x => x.ApplicationVersions[0]?.Status != ApplicationVersionStatus.Processed)
    .WaitAndRetryAsync(10, retryAttempt => TimeSpan.FromSeconds(1), onRetry: (describeResponse, timeSpan, context) => {
        Console.WriteLine($"Application version was '{describeResponse.Result.ApplicationVersions[0].Status}', retrying in {timeSpan}");
    });

var fallback = Policy
    .HandleResult<DescribeApplicationVersionsResponse>(x => x.ApplicationVersions[0]?.Status != ApplicationVersionStatus.Processed) // Probably worth factoring the predicate out into a method so that it is only stated once.
    .FallbackAsync(async () => { throw new ReplacementException(); });

var r = await fallback.WrapAsync(retry)
    .ExecuteAsync(() =>
   BeanstalkClient.DescribeApplicationVersionsAsync(describeApplicationVersionRequest)
);