提问人:sharpener 提问时间:9/16/2023 最后编辑:sharpener 更新时间:9/18/2023 访问量:152
将自定义上下文传递到 OnRetry
Pass custom context into OnRetry
问:
- 我想使用 Polly v8,它引入了新的 API。
ResiliencePipeline
- 我想使用该策略处理提供的异步操作的执行。
ResiliencePipeline.ExecuteAsync()
Retry
- 我需要在回调中提供自定义上下文,该上下文是在构建阶段(通过 )定义的。
OnRetry
ResiliencePipeline
ResiliencePipelineBuilder
- 回调中似乎只有一个可用。
OnRetryArguments
OnRetry
- 如果我没有遗漏任何内容,则只有属性(类型)可用于自定义数据传递,即(类型)。
Context
ResilienceContext
Properties
ResilienceProperties
我还没有找到任何方法,如何“配置”给定调用中使用的特定实例,除了自己创建它并将其直接传递给适当的重载。这似乎有点复杂,因为它需要从池中获取实例,然后在执行完成后将其返回(看起来可以服务于它)。ResilienceContext
ExecuteAsync
ResilienceContextPool.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);
}
}
}
看起来这按预期工作......
答:
在撰写本文时,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
)。ResilienceContextPool
ArrayPool
重用现有组件
另一个例子是 .NET 7 引入了 RateLimiter,Polly
V8 使用该组件而不是两个单独的实现。当然,必须引入一些包装器,以便与其他策略和管道构建器很好地集成。
new ResiliencePipelineBuilder()
.AddRateLimiter(new RateLimiterStrategyOptions());
new ResiliencePipelineBuilder()
.AddConcurrencyLimiter(100, 50);
最小化输入参数
另一个设计原则是尽量减少输入参数的数量。例如,在 V7 的情况下,有几个过载。每个过载都提供了对不同参数的访问,有时很难找到合适的过载。onRetry
在 V8 中,生成器方法和用户定义的委托只有一个参数。XYZOptions
XYZArguments
上面的列表并不详尽,但我希望这些背景信息能为您提供一些上下文,为什么 V8 API 看起来是这样的。
评论