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
p2
returns astring
whereas yourp1
returns nothing. So, you need to changep1
to return withstring
as well. Then you can usePolicy.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:
Policy
toPolicy<string>
inp1
sleepDurationProvider
will not receive theException
as a parameterDelegateResult<string>
which have two mutually exclusive properties:Exception
andResult
Answer to question 2
fallbackAction
delegate receives aDelegateResult<string>
as a parameterUpdate #1: Providing clarity
Changing the
p1
definition fromPolicy
toPolicy<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
p1
andp2
withPolicy.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.