仅在条件下使用 Polly 重试改装请求

问题描述 投票:0回答:1

我在我的 UWP 应用程序中使用 Refit 客户端和用于依赖注入的 Polly 策略设置了以下服务集合:

var serviceCollection = new ServiceCollection();

serviceCollection
    .AddRefitClient(typeof(IClassevivaAPI))
    .ConfigureHttpClient(
        (sp, client) =>
        {
            client.BaseAddress = new Uri(Endpoint.CurrentEndpoint);
        }
    )
    .AddPolicyHandler(
        Policy<HttpResponseMessage>
            .HandleResult(r => r.StatusCode == System.Net.HttpStatusCode.Unauthorized)
            .RetryAsync(
                1,
                async (ex, count) =>
                {
                    Debug.WriteLine("Retry {0} times", count);

                    var loginCredentials = new CredUtils().GetCredentialFromLocker();

                    if (loginCredentials != null)
                    {
        //the retry can continue
                    }
                }
            )
    );           

当 http 响应的 StatusCode 为 401(在我使用的 API 中意味着会话已过期)时,应用程序会检查凭据是否已存储在我的应用程序中(在我的应用程序中,在登录阶段我可以选择是否这样做是不保存凭据的临时会话)或不。

如果存储了凭据,Polly 策略可以继续重试请求。

但我希望在未存储凭据的情况下,策略不执行重试而是关闭应用程序。

有没有办法告诉 Polly 策略在处理特定的 http 事件时有条件地执行重试,而不需要任何技巧?

c# dotnet-httpclient polly retry-logic refit
1个回答
0
投票

由于

HandleResult
可以接受返回
true
false
(
Func<T, bool>
)
的同步委托,这就是为什么您可以结合状态代码和凭证检查

Policy<HttpResponseMessage>
    .HandleResult(r => 
       r.StatusCode == HttpStatusCode.Unauthorized
       && new CredUtils().GetCredentialFromLocker() != null)
    .RetryAsync(1, (_, count) => Debug.WriteLine("Retry {0} times", count));               

更新#1

但是如果凭证检查为空,我如何在策略中执行代码(在我的情况下关闭应用程序)?

由于您已经对整个

HttpClient
应用了重试逻辑(作为引擎盖下的
DelegatingHandler
),这就是为什么您不应该尝试从策略中退出应用程序的原因。

更好的方法可能是从策略或

GetCredentialFromLocker
中抛出自定义异常,并使用 try-catch 包装您的改装客户端调用,以通过退出应用程序来处理该异常。

如果您将重试策略添加到

PolicyRegistry
(而不是在
HttpClient
上),那么您还有另一个选择。
ExecuteAsync
可以接收一个
Context
对象
,您可以在策略中对其进行操作。所以,如果
GetCredentialFromLocker
方法调用返回
null
那么你就在上下文中设置了一个“标志”。在
ExecuteAsync
调用之后,您可以评估上下文并在需要时退出应用程序。

© www.soinside.com 2019 - 2024. All rights reserved.