How to execute multiple policies (or combine them into a single one)?
For example I have:
var policy1 = Policy.Handle<DivideByZeroException>().WaitAndRetry(5));
var policy2 = Policy.Handle<StackOverflowException>().RetryForever();
How to apply them to one method at the same time?
As of Polly v5.0, there's a new PolicyWrap class, which let you combine multiple policies.
var policy1 = Policy.Handle<DivideByZeroException>().WaitAndRetry(3, i => TimeSpan.FromSeconds(1));
var policy2 = Policy.Handle<StackOverflowException>().RetryForever();
PolicyWrap policyWrap = Policy.Wrap(policy1, policy2);
policyWrap.Execute(someGreatAction);
There are several ways to combine two policies. Let me list all the different options for the sake of completeness. I will add recommendations for each: when to use it and when to avoid it
ExceptionDispatchInfo edi = null;
int retryCounter = 0;
var combinedPolicy = Policy
.Handle<DivideByZeroException>()
.Or<StackOverflowException>()
.WaitAndRetry(CalculateSleep());
combinedPolicy.Execute(() => {
try
{
//User code...
throw new DivideByZeroException();
}
catch (Exception ex)
{
edi = ExceptionDispatchInfo.Capture(ex);
edi.Throw();
}
});
IEnumerable<TimeSpan> CalculateSleep()
{
while (true)
{
var wasItADivideByZero = edi.SourceException is DivideByZeroException;
var attempt = retryCounter++;
if (wasItADivideByZero)
{
if (attempt > 3) break;
yield return TimeSpan.FromSeconds(1);
}
yield return TimeSpan.FromSeconds(0);
}
}
WaitAndRetry
does not have an overload where you don't have to specify the retryCount
but you can access the thrown exception inside the sleepDurations
retryCount
+ sleepDurationProvider
(from where you can access the exception) or use sleepDurations
ExceptionDispatchInfo
to capture the thrown exception and access it inside our custom CalculateSleep
methodvar combinedPolicy = Policy
.Handle<DivideByZeroException>()
.Or<StackOverflowException>()
.WaitAndRetry(3,
(_, ex, __) => TimeSpan.FromSeconds(ex is DivideByZeroException ? 1 : 2),
(_, __, ___, ____) => { });
policy1.Execute(() =>
{
policy2.Execute(() =>
{
//User code
});
});
OR
policy2.Execute(() =>
{
policy1.Execute(() =>
{
//User code
});
});
policy1.Execute(policy2.Execute(UserCode()));
Wrap
instance methodvar combinedPolicy = policy1.Wrap(policy2);
combinedPolicy.Execute(UserCode());
OR
var combinedPolicy = policy2.Wrap(policy1);
combinedPolicy.Execute(UserCode());
combinedPolicy
's type is PolicyWrap
, which implements the ISyncPolicy
interface as wellvar combinedPolicy = globalTimeout.Wrap(retry).Wrap(circuitBreaker).Wrap(localTimeout);
void
and another policy for TResult
then the system tries to act smart
combinedPolicy
is now PolicyWrap<string>
var policy1 = Policy.Handle<DivideByZeroException>().WaitAndRetry(3, i => TimeSpan.FromSeconds(1));
var policy2 = Policy<string>.Handle<StackOverflowException>().RetryForever();
var combinedPolicy = policy1.Wrap(policy2);
string? result = combinedPolicy.Execute(() => "dummy response");
Wrap
static methodvar combinedPolicy = Policy.Wrap(policy2, policy1);
OR
var combinedPolicy = Policy.Wrap(policy2, policy1);
ISyncPolicy
or ISyncPolicy<TResult>
policiesISyncPolicy
and a ISyncPolicy<string>
policies because all policies should have the same typevar combinedPolicy = Policy.Wrap<HttpResponseMessage>(globalTimeout,retry,circuitBreaker,localTimeout);
TResult
and one or more void
TResult
and one or more void
TResult1
and TResult2
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With