当前位置: 首页 > 知识库问答 >
问题:

Polly在重试时更改查询字符串

公孙驰
2023-03-14

这是波莉适合的场景吗?或者从设计的角度来看,在业务逻辑中处理这个是干净的方式吗?然后我需要包装这个逻辑以避免重复我自己。

var response = await client.GetStringAsync("https://test.com");
if (!response.IsSuccessStatusCode && response.StatusCode == 4xx)
  response = await client.GetStringAsync("https://test.com?key=XXX")

// continue with regular workflow - handling errors or process response

共有1个答案

冀崇凛
2023-03-14

getStringAsync返回一个任务 ,所以您不能检查reponse的statuscode
因此,您需要使用getAsync返回一个任务

因为请求uri是调用之间唯一变化的东西,所以需要将其作为参数接收:

private static HttpClient client = new HttpClient(); //or use IHttpClientFactory
static async Task<HttpResponseMessage> PerformRequest(string uri)
{
    Console.WriteLine(uri);
    return await client.GetAsync(uri);
}

为了使重试策略能够执行无参数操作,我们需要一个地址迭代器和围绕performrequest的包装器:

static IEnumerable<string> GetAddresses()
{
    yield return "https://test.com";
    yield return "https://test.com?key=XXX";
    ...
}
private static readonly IEnumerator<string> UrlIterator = GetAddresses().GetEnumerator();
static async Task<HttpResponseMessage> GetNewAddressAndPerformRequest()
{
    if (UrlIterator.MoveNext())
        return await PerformRequest(UrlIterator.Current);
    return null;
}

剩下的是重试策略本身:

var retryPolicyForNotSuccessAnd4xx = Policy
    .HandleResult<HttpResponseMessage>(response => response != null && !response.IsSuccessStatusCode)
    .OrResult(response => response != null && (int)response.StatusCode > 400 && (int)response.StatusCode < 500)
    .WaitAndRetryForeverAsync(_ => TimeSpan.FromSeconds(1));
  • 如果GetNewAddresSandPerformRequest返回null,因为我们已经用完了回退URL,那么我们将退出重试
  • 如果statusCode在200到299之间,则退出重试
  • 如果statusCode在300到400之间或大于500,则退出重试
  • 在其他情况下,我们执行重试

用法可能如下所示:

var response = await retryPolicyForNotSuccessAnd4xx.ExecuteAsync(async () => await GetNewAddressAndPerformRequest());
if (response == null)
{
    Console.WriteLine("All requests failed");
    Environment.Exit(1);
}
    
Console.WriteLine(await response.Content.ReadAsStringAsync());
class Program
{
    private static HttpClient client = new HttpClient();
    static async Task Main(string[] args)
    {
        var retryPolicyForNotSuccessAnd4xx = Policy
            .HandleResult<HttpResponseMessage>(response => response != null && !response.IsSuccessStatusCode)
            .OrResult(response => response != null && (int)response.StatusCode > 400 && (int)response.StatusCode < 500)
            .WaitAndRetryForeverAsync(_ => TimeSpan.FromSeconds(1));

        var response = await retryPolicyForNotSuccessAnd4xx.ExecuteAsync(async () => await GetNewAddressAndPerformRequest());
        if (response == null)
        {
            Console.WriteLine("All requests failed");
            Environment.Exit(1);
        }

        Console.WriteLine(await response.Content.ReadAsStringAsync());
    }

    static IEnumerable<string> GetAddresses()
    {
        yield return "https://test.com";
        yield return "https://test.com?key=XXX";
    }

    private static readonly IEnumerator<string> UrlIterator = GetAddresses().GetEnumerator();
    
    static async Task<HttpResponseMessage> GetNewAddressAndPerformRequest()
        => UrlIterator.MoveNext() ? await PerformRequest(UrlIterator.Current) : null;
    
    static async Task<HttpResponseMessage> PerformRequest(string uri)
    {
        Console.WriteLine(uri);
        return await client.GetAsync(uri);
    }
}
 类似资料:
  • 这是我的代码,查询Notification.create_time 在另一个地方,需要将json.dumps查询结果转储到前端,datetime格式不能使用json.dumps,所以我想这样做: 那么,如何在sqlalchemy查询中将datetime更改为字符串呢?

  • 问题1:如果网络中断,断路器已达到exceptionsAllowedBeforeBreaking编号,进入open状态并等待DurationOfBreaking周期,则电路将为新请求打开,但已发送的请求将抛出异常? 问题2:如果期望的行为是重试那些有异常的请求,而不是断路器抛出异常,那么除了断路器策略之外,还需要实现重试策略。我对此的理解是,将发生问题1中的行为,然后将尝试重试。 a.如果存在网络

  • 我想在SQLite查询的每个ORDER BY子句之前插入一个COLLATE NOCASE。这就是我到目前为止所拥有的: 输出为: 从'test'顺序中选择'x','y',按'x'整理NOCASE ASC,'z'ASC限制0,10 第一个实例被匹配和替换。第二个实例不被替换(因为模式中的ORDER BY子句)。

  • 这家餐厅是猫鼬的典范。我试图在适当的地方改变事情,但没有成功: 我认为是一个模型对象。我试图看到检查属性描述符与以下内容,它说: 为什么删除对象不起作用?为什么我看不到属性描述符? 编辑:所以这是一个猫鼬文件。但是,用Javascript术语来说,像Mongoose文档这样的对象可以基于Javascript对象以外的其他对象吗?一些基于内部C代码的包装器还是什么?

  • 问题内容: 我正在处理项目,其中用户具有以常规格式存储的日期的数据库, 2013年3月8日 ,我想对输出进行日期排序。或将该日期字段转换为mysql查询中的时间戳 我想要这样的东西 但我知道这行不通…有没有出路 问题答案: 由于它不是日期,所以用于将字符串转换为日期 SQLFiddle演示

  • 问题内容: 我有一个带有链接的“主页”组件,当您单击链接时,产品组件就会随产品一起加载。我还有另一个始终可见的组件,其中显示了“最近访问过的产品”的链接。 在产品页面上时,这些链接不起作用。当我单击链接时,URL会更新,并且会进行渲染,但是产品组件不会随新产品一起更新。 请参见以下示例: Codesandbox示例 以下是index.js中的路由: ProductHistory中的链接如下所示: