Given the following F# snippets
//User Code
.. code that can throw exceptions
"Success"
Policy
.Handle<CosmosException>(fun cx -> cx.StatusCode = HttpStatusCode.TooManyRequests)
.WaitAndRetryForever((fun _ cx _ -> (cx :?> CosmosException).RetryAfter.Value), (fun _ _ _ _ -> ()))
Policy<string>
.Handle<Exception>()
.Fallback("Failure")
Policy<string>
.Handle<Exception>()
.Fallback(fun ex -> ex.Message)
Combine P1 and P2 in a policy P so that:
There doesn't seem to be a Fallback overload that allows to access the handled exception to use it when constructing the fallback return value
Final scope is to combine P1 and P3 to obtain a policy PFinal such that:
In order to be able to chain policies you need to define them as compatible policies. Your p2
returns a string
whereas your p1
returns nothing. So, you need to change p1
to return with string
as well. Then you can use Policy.Wrap
to define chaining, escalation.
I'm not an F# developer so I will present the solution in C#. But the idea is the same in both languages:
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
to Policy<string>
in p1
sleepDurationProvider
will not receive the Exception
as a parameter
DelegateResult<string>
which have two mutually exclusive properties: Exception
and Result
fallbackAction
delegate receives a DelegateResult<string>
as a parametervar p2 = Policy<string>
.Handle<Exception>()
.Fallback(fallbackAction: (dr, _, __) => dr.Exception.Message,
onFallback: (_, __) => { });
Update #1: Providing clarity
Changing the p1
definition from Policy
to Policy<string>
has another implication as well: Your to be decorated code should return a string (namely "Success")
Before the change:
//user code
//to be decorated code which might throw exception
return "Success";
After the change:
//user code
//The decorated code either return "Success" or throws CosmosException
return combinedPolicy.Execute(...
Update #2: Fix ordering
I suggested to chain the p1
and p2
with Policy.Wrap
. Unfortunately I have showed you the wrong order Policy.Wrap(p1, p2)
. The correct one is Policy.Wrap(p2, p1)
since the right most parameter is the most inner and the left most is the most outer. So, in your case the retry is the inner and the fallback is the outer.
Apologise for the inconvenience.