【问题标题】:Polly: Honoring Retry-After that is communicated with a custom exception?波莉:尊重重试 - 之后与自定义异常通信?
【发布时间】:2020-03-11 04:16:23
【问题描述】:

所以我必须使用一个库,该库本质上是对可能选择限制流量的远程系统执行 POST。如果是这样,它会返回 429 和特定的秒数以在 Retry-After 标头中回退......此时框架读取并解析此值,并且本质上是这样做的

throw new ThrottledException(retryAfterSeconds);

如何设置将捕获此自定义异常的 Polly 策略,然后在 exception.RetryAfter 秒后重试?

【问题讨论】:

  • 想必你在计算重试周期的时候可以通过上下文访问异常?
  • Polly 提供了这方面的文档,以及示例代码的链接,这里:github.com/App-vNext/Polly/wiki/…
  • @mountaintraveller 如果你想获得荣誉,你必须输入答案而不是评论......
  • @AndersSewerinJohansen 我知道,但 StackOverflow 社区不赞成仅提供链接的答案。

标签: c# polly


【解决方案1】:

好的,这比它需要的要复杂一些,但这只是因为I was sent on several wild goose chases by inscrutable compiler messages.

在这种情况下,重试通过 SigsThrottledException 类型的自定义异常进行通信,该异常具有包含请求的退避时间(以秒为单位)的字段。

var policy = Policy
    .Handle<SigsThrottledException>(e => e.RetryAfterInSeconds > 0)
    .WaitAndRetryAsync(
        retryCount: retries,
        sleepDurationProvider: (i, e, ctx) =>
        {
            var ste = (SigsThrottledException)e;
            return TimeSpan.FromSeconds((double)ste.RetryAfterInSeconds);
        },
        onRetryAsync: async (e, ts, i, ctx) =>
        {
            // Do something here
        };);

这是一个如何使用策略的示例。你不能只是add it to an existing HttpClient or HttpClientFactory。你必须明确地使用它。

[TestMethod]
public async Task SigsPollyRetriesOnThrottle()
{
    var retryResponse = new HttpResponseMessage
    {
        StatusCode = (HttpStatusCode)429,
        Content = new StringContent("{}"),
    };

    retryResponse.Headers.Add("Retry-After", "1");

    var mockMessageHandler = new Mock<HttpMessageHandler>();
    mockMessageHandler.Protected()
        .SetupSequence<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
        .ReturnsAsync(retryResponse)
        .ReturnsAsync(new HttpResponseMessage
        {
            StatusCode = HttpStatusCode.OK
        });

    var client = new HttpClient(mockMessageHandler.Object);

    // Retry once after waiting 1 second
    var retryPolicy = Policy
    .Handle<SigsThrottledException>(e => e.RetryAfterInSeconds > 0)
    .WaitAndRetryAsync(
        retryCount: 1,
        sleepDurationProvider: (i, e, ctx) =>
        {
            var ste = (SigsThrottledException)e;
            return TimeSpan.FromSeconds((double)ste.RetryAfterInSeconds);
        },
        onRetryAsync: async (e, ts, i, ctx) =>
        {
            // Do something here
        };);

    Stopwatch stopWatch = new Stopwatch();
    stopWatch.Start();
    var response = await retryPolicy.ExecuteAsync(async () =>
    {
        Uri substrateurl = new Uri("https://substrate.office.com/");
        return await SIGSClient.Instance.PostAsync(client, substrateurl, new UserInfo(), "faketoken", new Signal(), Guid.NewGuid()).ConfigureAwait(false);
    }
    );

    Assert.AreEqual(response.StatusCode, HttpStatusCode.OK);
    stopWatch.Stop();
    Assert.IsTrue(stopWatch.ElapsedMilliseconds > 1000); // Make sure we actually waited at least a second
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-01
    • 2023-02-25
    • 1970-01-01
    • 2015-01-11
    • 1970-01-01
    • 1970-01-01
    • 2020-09-16
    • 2022-10-06
    相关资源
    最近更新 更多