在我的应用程序中,我使用 Polly调用 API 的库。
API 可以在响应中返回警告和错误。对于其中一些警告,我想重试 2 次,下一次我想 将响应返回给调用者 .
这可以做到吗?
编辑:
@StephenCleary 指出我应该只处理响应而不抛出异常。
要检查响应,我需要等待内容。以下将无法编译,任何人都可以看到我该怎么做吗?
static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
return HttpPolicyExtensions
.HandleTransientHttpError()
.OrResult(async msg =>
{
var content = await msg.Content.ReadAsStringAsync();
return content.Contains("errorcode123");
})
.WaitAndRetryAsync(2, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
}
最佳答案
这有几个部分。
首先,如果结果有警告,你不想抛出异常。那时也许你想重试,也许你不想;那里的代码还不能说。但是抛出异常意味着响应被丢弃,所以此时抛出是不正确的。
相反,该处理程序应使用“有警告”标志标记响应。这可以使用 HttpRequestMessage.Properties
(HttpRequestMessage.Options
在 .NET 5 中)。像这样的东西:
private static readonly string IsInternalServerResponseKey = Guid.NewGuid().ToString("N");
...
var httpResponse = ...
var responseContent = ...
if (InternalServerResponse(responseContent))
{
httpResponse.RequestMessage.Properties[IsInternalServerResponseKey] = true;
}
这样,请求/响应就会附加一个标志,代码的其他部分可以读取该标志,特别是 Polly 重试处理程序。解决方案的另一部分是重试计数。通常,Polly 具有决定是否应该重试的委托(delegate),并且这些委托(delegate)是自包含的 - 重试这种类型的异常,或重试类似的响应。在这种情况下,您想重试匹配特定形状的响应,但前提是重试次数不多,并且如果重试次数过多并且响应匹配“重试”形状,那么您不希望抛出异常但返回响应。
这是不寻常的,但可行的。您需要在 Polly 上下文中捕获“外部注意事项”(在本例中为重试计数)。然后,您的重试委托(delegate)可以从上下文中提取重试计数并以此为基础做出决定。像这样的东西应该工作:
private static readonly string RetryCountKey = Guid.NewGuid().ToString("N");
static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
return HttpPolicyExtensions
.HandleTransientHttpError()
.OrResult(response =>
{
return IsInternalServerResponse() && RetryCount() <= 2;
bool IsInternalServerResponse()
{
if (!response.RequestMessage.Properties.TryGetValue(IsInternalServerResponseKey, out var objValue) ||
objValue is not bool boolValue)
return false;
return boolValue;
}
int RetryCount()
{
if (!response.RequestMessage.GetPolicyExecutionContext().TryGetValue(RetryCountKey, out var objValue) ||
objValue is not int intValue)
return 0;
return intValue;
}
})
.WaitAndRetryAsync(2,
(retryAttempt, _) => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
(_, _, retryAttempt, context) => context[RetryCountKey] = retryAttempt);
}
我没有测试过这个; 2
之间可能存在一个错误。传递给 WaitAndRetryAsync
和 2
用于比较 retryCount
.
关于c# - 如何使用 Polly 根据响应内容重试 x 次,然后返回响应?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67386496/