将自定义上下文传递到 OnRetry

Pass custom context into OnRetry

提问人:sharpener 提问时间:9/16/2023 最后编辑:sharpener 更新时间:9/18/2023 访问量:152

问:

  • 我想使用 Polly v8,它引入了新的 API。ResiliencePipeline
  • 我想使用该策略处理提供的异步操作的执行。ResiliencePipeline.ExecuteAsync()Retry
  • 我需要在回调中提供自定义上下文,该上下文是在构建阶段(通过 )定义的。OnRetryResiliencePipelineResiliencePipelineBuilder
  • 回调中似乎只有一个可用。OnRetryArgumentsOnRetry
  • 如果我没有遗漏任何内容,则只有属性(类型)可用于自定义数据传递,即(类型)。ContextResilienceContextPropertiesResilienceProperties

我还没有找到任何方法,如何“配置”给定调用中使用的特定实例,除了自己创建它并将其直接传递给适当的重载。这似乎有点复杂,因为它需要从池中获取实例,然后在执行完成后将其返回(看起来可以服务于它)。ResilienceContextExecuteAsyncResilienceContextPool.Shared

这是首选方式,还是我遗漏了一些明显的东西?

是否考虑用于这些目的?ResilienceContextPool.Shared

编辑:

public static class ResiliencePipelineExtensions
{
    public static async ValueTask ExecuteAsync(this ResiliencePipeline resilience, Func<CancellationToken, ValueTask> action, string operation, IDictionary<string, object> context, CancellationToken cancellationToken)
    {
        var resilienceContext = ResilienceContextPool.Shared.Get(operation, cancellationToken);

        foreach (var property in context)
        {
            resilienceContext.Properties.Set(new ResiliencePropertyKey<object>(property.Key), property.Value);
        }

        try
        {
            await resilience.ExecuteAsync(ctx => action(ctx.CancellationToken), resilienceContext);
        }
        finally
        {
            ResilienceContextPool.Shared.Return(resilienceContext);
        }
    }
}

看起来这按预期工作......

c# 波莉 重试逻辑

评论

0赞 Peter Csala 9/17/2023
您正在玩哪个 V8 预发布版本?

答:

1赞 Peter Csala 9/18/2023 #1

在撰写本文时,Polly V8 尚未完成。目前 V8 beta 2 可用,这意味着它已准备好功能,并且 API 被认为(大部分)稳定。

这意味着仍然有机会对 V8 API 的外观产生影响。已经有几次或公开的 API 审查会议,并且已经接受了许多建议并将其纳入代码库。

因此,如果您发现当前的 API 难以使用,请随时在 Polly 的 github 上提出问题。

例如,ResilienceProperties 的当前实现不允许键值对的“批量加载”。但在引擎盖下,它正在使用一个集合。使用“批量加载”功能扩展此类可能是一个很好的反馈。Dictionary<string, object?>


使用全新的 API 是否打算如此“复杂”?

V8 与我们前几年的版本大不相同。这是一次彻底的重写,并采用了一些新的设计原则。

从头开始异步

例如,API 是从头开始异步的。这意味着所有用户定义的委托也应该是异步的。在以前的预发布版本中,您必须编写一些样板代码才能以同步方式使用 API

ShouldRetry = outcome => new ValueTask<bool>(outcome.Exception is TimeoutRejectedException),

但根据反馈,引入了一些帮助程序类以及几个隐式转换运算符

ShouldRetry = new PredicateBuilder().Handle<TimeoutRejectedException>()

公开类似的 API

此外,V8 还尝试遵循一些在前几年中经过了战斗强化的 .NET 约定。就像 的 API 非常相似(除了一些例外,比如 .需要使用 Shared.Get 而不是 .Shared.Rent)。ResilienceContextPoolArrayPool

重用现有组件

另一个例子是 .NET 7 引入了 RateLimiter,Polly V8 使用该组件而不是两个单独的实现。当然,必须引入一些包装器,以便与其他策略和管道构建器很好地集成。

new ResiliencePipelineBuilder()
    .AddRateLimiter(new RateLimiterStrategyOptions());

new ResiliencePipelineBuilder()
    .AddConcurrencyLimiter(100, 50);

最小化输入参数

另一个设计原则是尽量减少输入参数的数量。例如,在 V7 的情况下,有几个过载。每个过载都提供了对不同参数的访问,有时很难找到合适的过载。onRetry

在 V8 中,生成器方法和用户定义的委托只有一个参数。XYZOptionsXYZArguments


上面的列表并不详尽,但我希望这些背景信息能为您提供一些上下文,为什么 V8 API 看起来是这样的。