给出以下F#片段
//User Code
.. code that can throw exceptions
"Success"
P1政策
Policy
.Handle<CosmosException>(fun cx -> cx.StatusCode = HttpStatusCode.TooManyRequests)
.WaitAndRetryForever((fun _ cx _ -> (cx :?> CosmosException).RetryAfter.Value), (fun _ _ _ _ -> ()))
P2政策
Policy<string>
.Handle<Exception>()
.Fallback("Failure")
P3策略
Policy<string>
.Handle<Exception>()
.Fallback(fun ex -> ex.Message)
问题1-如何将P1和P2结合起来?
将P1和P2合并到策略P中,以便:
问题2-如何编写P3?
在构造回退值时,似乎没有允许访问已处理异常来使用该异常的回退重载。
最后一个范围是将P1和P3组合起来,以获得一个策略PFinal,以便:
发布于 2022-07-18 05:33:04
对问题1的答复
为了能够链接策略,需要将它们定义为兼容的策略。您的p2
返回一个string
,而您的p1
则什么也不返回。因此,您需要更改p1
以返回string
。然后可以使用Policy.Wrap
来定义链接,升级。
我不是F#开发人员,所以我将在C#中介绍解决方案。但这两种语言的想法是相同的:
var p1 = Policy<string>
.Handle<CosmosException>(ex => ex.StatusCode == HttpStatusCode.TooManyRequests)
.WaitAndRetryForever(sleepDurationProvider: (_, dr, __) => ((CosmosException)dr.Exception).RetryAfter.Value,
onRetry: (_, __, ___) => { });
var p2 = Policy<string>
.Handle<Exception>()
.Fallback("Failure");
var p = Policy.Wrap(p1, p2);
Policy
更改为Policy<string>
in p1
sleepDurationProvider
将不会将Exception
作为参数接收。DelegateResult
,它具有两个互斥属性:Exception
和Result
对问题2的答复
fallbackAction
委托接收作为参数的DelegateResult<string>
。var p2 = Policy<string>
.Handle<Exception>()
.Fallback(fallbackAction: (dr, _, __) => dr.Exception.Message,
onFallback: (_, __) => { });
更新#1:提供清晰性
将p1
定义从Policy
更改为Policy<string>
还有另一个含义:要修饰的代码应该返回一个字符串(即“成功”)
变更前:
//user code
//to be decorated code which might throw exception
return "Success";
变更后:
//user code
//The decorated code either return "Success" or throws CosmosException
return combinedPolicy.Execute(...
更新#2:修复排序
我建议将p1
和p2
与Policy.Wrap
连接起来。不幸的是,我给你看错了Policy.Wrap(p1, p2)
的订单。正确的是Policy.Wrap(p2, p1)
,因为最右的参数是最内部的参数,最左边的参数是最外层的参数。所以,在你的例子中,重试是内在的,而后退是外部的。
抱歉给您带来不便。
https://stackoverflow.com/questions/73016363
复制相似问题