![](/img/trans.png)
[英]Pass ILogger<T> to Polly retry policy without HttpRequestMessage
[英]Reusing HttpRequestMessage in Polly retry policies
一个HttpRequestMessage
object 只能使用一次; 以后尝试使用相同的 object 会引发异常。 我正在使用 Polly 重试一些请求,我遇到了这个问题。 我知道如何克隆请求,有很多关于 SO 的示例,但我不知道如何克隆请求并在 Polly 重试时发送新请求。 我怎样才能做到这一点?
这些是我的政策,供参考。 这是一个 Xamarin 应用程序。 如果出现网络故障,我想重试几次,如果响应未经授权,我想使用保存的凭据重新验证并再次尝试原始请求。
public static PolicyWrap<HttpResponseMessage> RetryPolicy
{
get => WaitAndRetryPolicy.WrapAsync(ReAuthPolicy);
}
private static IAsyncPolicy WaitAndRetryPolicy
{
get => Policy.Handle<WebException>().WaitAndRetryAsync(4, _ => TimeSpan.FromSeconds(2));
}
private static IAsyncPolicy<HttpResponseMessage> ReAuthPolicy
{
get => Policy.HandleResult<HttpResponseMessage>(x => x.StatusCode == HttpStatusCode.Unauthorized)
.RetryAsync((_, __) => CoreService.LogInWithSavedCredsAsync(true));
}
由于HttpRequestMessage
重用,这不起作用,但这是我想要完成的:
var request = new HttpRequestMessage(HttpMethod.Post, "some_endpoint")
{
Content = new StringContent("some content")
};
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var policyResponse = await ConnectivityHelper.RetryPolicy
.ExecuteAndCaptureAsync(() => _client.SendAsync(request)).ConfigureAwait(false);
// handle outcome
如果HttpRequestMessage
被重用,则抛出InvalidOperationException
的代码是HttpClient
本身中的验证步骤。
private static void CheckRequestMessage(HttpRequestMessage request)
{
if (!request.MarkAsSent())
{
throw new InvalidOperationException(SR.net_http_client_request_already_sent);
}
}
internal bool MarkAsSent()
{
return Interlocked.Exchange(ref sendStatus, messageAlreadySent) == messageNotYetSent;
}
您可以将 polly 重试策略放在DelegatingHandler
,这样就可以了。 它还提供了一个很好的 SoC(关注点分离)。 如果在未来,你想不重试或改变重试的行为,你只需删除DelegatingHandler
或改变它。 注意处理HttpRequestMessage
和中间HttpResponseMessage
对象。
嗯,最简单的解决方案是将HttpRequestMessage
的创建移动到ExecuteAndCaptureAsync
委托中。 换句话说,不要重用而是重新创建它:
var policyResponse = await ConnectivityHelper.RetryPolicy
.ExecuteAndCaptureAsync(async () => {
var request = new HttpRequestMessage(HttpMethod.Post, "some_endpoint")
{
Content = new StringContent("some content", Encoding.UT8, "application/json")
};
return await _client.SendAsync(request)).ConfigureAwait(false);
});
或者只是更喜欢PostAsync
而不是SendAsync
var policyResponse = await ConnectivityHelper.RetryPolicy.ExecuteAndCaptureAsync(
async () =>
await _client.PostAsync("some_endpoint",
new StringContent("some content", Encoding.UT8, "application/json"))
.ConfigureAwait(false)
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.