2

鉴于此代码尝试调用AuthenticationManager.Authenticate()10 次,然后在 10 次CustomException尝试失败后抛出:

string res = Policy
    .Handle<Exception>() // Handles any exception
    .OrResult<string>(result => string.IsNullOrWhiteSpace(result)) // or if result is null
    .Fallback(() => throw new CustomException("Exception!")) // Not being thrown after 10 unsuccessful attempts
    .Wrap(
        Policy
            .Handle<Exception>()
            .OrResult<string>(result => string.IsNullOrWhiteSpace(result))
            .WaitAndRetry(
                10,
                retryAttempt => TimeSpan.FromSeconds(60),
                onRetry: (response, delay, retryCount, context) => Trace.WriteLine($"[{DateTime.UtcNow}] Authentication failed. Retrying after 60 seconds...(Attempt {retryCount} of 10)")))
    .ExecuteAndCapture(() => AuthenticationManager.Authenticate())
    .Result;

为什么CustomException没有从后备动作中抛出?正确的方法应该是什么?

4

2 回答 2

1

这些单元测试通过:(xUnit)

[Fact]
public void Test1()
{
    var policy = Policy<string>
        .Handle<Exception>()
        .OrResult(result => string.IsNullOrWhiteSpace(result))
        .Fallback(() => throw new CustomException())
        .Wrap(
              Policy<string>
                 .Handle<Exception>()
                 .OrResult(result => string.IsNullOrWhiteSpace(result))
                 .WaitAndRetry(
                  10,
                  _ => TimeSpan.FromSeconds(1),
                  onRetry: (response, delay, retryCount, context) => Trace.WriteLine($"[{DateTime.UtcNow}] Authentication failed. Retrying after 1 second...(Attempt {retryCount} of 10)")
                  )
        );

    var result = policy.ExecuteAndCapture(() => throw new Exception("Muh"));
    Assert.IsType<CustomException>(result.FinalException);
    Assert.Null(result.Result);
    Assert.Equal(OutcomeType.Failure, result.Outcome);
}

[Fact]
public void Test2()
{
    var policy = Policy<string>
        .Handle<Exception>()
        .OrResult(result => string.IsNullOrWhiteSpace(result))
        .Fallback(() => throw new CustomException())
        .Wrap(
              Policy<string>
                 .Handle<Exception>()
                 .OrResult(result => string.IsNullOrWhiteSpace(result))
                 .WaitAndRetry(
                  10,
                  _ => TimeSpan.FromSeconds(1),
                  onRetry: (response, delay, retryCount, context) => Trace.WriteLine($"[{DateTime.UtcNow}] Authentication failed. Retrying after 1 second...(Attempt {retryCount} of 10)")
                  )
        );

    Assert.Throws<CustomException>(() => policy.Execute(() => throw new Exception("Muh")));
}

所以,我想,你可以使用Execute,或者检查结果并重新抛出异常,如下所示:

var result = policy.ExecuteAndCapture(() => AuthenticationManager.Authenticate());
if( result.Outcome == OutcomeType.Failure && result.FinalException is not null)
{
    throw result.FinalException;
}
return result.Result;
于 2021-05-21T12:35:24.340 回答
0

发现只是使用WaitAndRetry并检查为Outcome我工作的工作(以防有人遇到这个问题):

var policyResult = Policy
    .Handle<Exception>()
    .OrResult<AuthenticationResult>(result => result is null)
        .WaitAndRetry(
            10,
            retryAttempt => TimeSpan.FromSeconds(60),
            onRetry: (response, delay, retryCount, context) => Trace.WriteLine($"[{DateTime.UtcNow}] Call failed. Retrying after 60 seconds...(Attempt {retryCount} of 10)"))
    .ExecuteAndCapture(() => AuthenticationManager.Authenticate());

if (policyResult.Outcome == OutcomeType.Failure)
{
    throw new CustomException("FAILED", policyResult.FinalException);
}

else
{
    string value = policyResult.FinalHandledResult;
}
于 2021-05-24T03:31:56.573 回答