Given the following F# snippets
//User Code
.. code that can throw exceptions
"Success"
P1 policy
Policy
.Handle<CosmosException>(fun cx -> cx.StatusCode = HttpStatusCode.TooManyRequests)
.WaitAndRetryForever((fun _ cx _ -> (cx :?> CosmosException).RetryAfter.Value), (fun _ _ _ _ -> ()))
P2 policy
Policy<string>
.Handle<Exception>()
.Fallback("Failure")
P3 Policy
Policy<string>
.Handle<Exception>()
.Fallback(fun ex -> ex.Message)
Question #1 - How to combine P1 and P2?
Combine P1 and P2 in a policy P so that:
- if User Code succeeds, "Success" is returned to the caller
- if User Code throws CosmosException, P retries forever using the returned RetryAfter TimeSpan
- if User Code throws any other exception, "Failure" is returned to the caller
Question # 2 - How to write P3?
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:
- if User Code succeeds, "Success" is returned to the caller
- if User Code throws CosmosException, PFinal retries forever using the returned RetryAfter TimeSpan
- if User Code throws any other exception, the handled exception message is returned to the caller
Answer to question 1
In order to be able to chain policies you need to define them as compatible policies. Your
p2returns astringwhereas yourp1returns nothing. So, you need to changep1to return withstringas well. Then you can usePolicy.Wrapto 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:
PolicytoPolicy<string>inp1sleepDurationProviderwill not receive theExceptionas a parameterDelegateResult<string>which have two mutually exclusive properties:ExceptionandResultAnswer to question 2
fallbackActiondelegate receives aDelegateResult<string>as a parameterUpdate #1: Providing clarity
Changing the
p1definition fromPolicytoPolicy<string>has another implication as well: Your to be decorated code should return a string (namely "Success")Before the change:
After the change:
Update #2: Fix ordering
I suggested to chain the
p1andp2withPolicy.Wrap. Unfortunately I have showed you the wrong orderPolicy.Wrap(p1, p2). The correct one isPolicy.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.