How to implement Polly Retry and Fallback
winanjaya
141
Reputation points
Hi,
re to this article:
I'm trying to implement Polly Retry and Fallback using codes below, but I keep getting the following:
You have executed the generic .Execute method on a non-generic FallbackPolicy. A non-generic FallbackPolicy only defines a fallback action which returns void; it can never return a substitute TResult value.
What did I do wrong?
I need advice..
thank you so much in advance.
internal static AsyncRetryPolicy<HttpResponseMessage> GetRetryPolicy(string serviceName)
{
return Policy
.Handle<TimeoutRejectedException>()
.OrResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.TooManyRequests || r.StatusCode == HttpStatusCode.TooManyRequests)
.WaitAndRetryAsync(MAX_RETRIES, retryAttempt => TimeSpan.FromSeconds(Math.Pow(MAX_RETRIES, retryAttempt)),
onRetryAsync: (response, sleepDuration, attemptNumber, context) => Task.Run(async () =>
{
string msg1 = $"{serviceName}:PollyPolicies:GetRetryPolicy in {sleepDuration}. {attemptNumber}/{MAX_RETRIES}";
await Models.Audit.AddAsync((long)0, msg1);
if (attemptNumber == MAX_RETRIES)
{
string msg = $"{serviceName}:PollyPolicies:GetRetryPolicy in {sleepDuration}. {attemptNumber}/{MAX_RETRIES}";
await Models.Audit.AddAsync((long)0, msg); }
}));
internal static AsyncTimeoutPolicy<HttpResponseMessage> GetTimeoutPolicy(string serviceName)
{
return Policy
.TimeoutAsync<HttpResponseMessage>( //Catches TaskCanceledException and throws instead TimeoutRejectedException
timeout: TimeSpan.FromSeconds(MAX_RETRY_ATTEMPT),
timeoutStrategy: TimeoutStrategy.Optimistic,
onTimeoutAsync: (context, sleepDuration, e1, e2) => Task.Run(async () => {
string msg = $"{serviceName}:PollyPolicies: GetTimoutPolicy in {sleepDuration}.";
await Models.Audit.AddAsync((long)0, msg);
})) ;
}
internal static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy(string serviceName)
{
return HttpPolicyExtensions
.HandleTransientHttpError()
.Or<BrokenCircuitException>()
.CircuitBreakerAsync(MAX_RETRIES, TimeSpan.FromSeconds(MAX_RETRY_ATTEMPT),
onBreak: (exception, sleepDuration) => Task.Run(async () =>
{
string msg = $"{serviceName}:PollyPolicies:GetCircuitBreakerPolicy, Circuit cut, request will not flow in {sleepDuration}.";
await Models.Audit.AddAsync((long)0, msg);
}),
onReset: () => Task.Run(async () =>
{
string msg = $"{serviceName}:PollyPolicies:GetCircuitBreakerPolicy, Circuit closed, request flow normally.";
await Models.Audit.AddAsync((long)0, msg);
}),
onHalfOpen: () => Task.Run(async () =>
{
string msg = $"{serviceName}:PollyPolicies:GetCircuitBreakerPolicy, Circuit in test mode, one request will be allowed.";
await Models.Audit.AddAsync((long)0, msg);
}));
}
internal static IAsyncPolicy<HttpResponseMessage> Wrap(string serviceName)
{
return
Policy.WrapAsync(PollyPolicies.GetRetryPolicy(serviceName),
PollyPolicies.GetCircuitBreakerPolicy(serviceName),
PollyPolicies.GetTimeoutPolicy(serviceName));
}
Fallback is here
internal static IAsyncPolicy<HttpResponseMessage> FallbackPolicy(string serviceName)
{
return Policy
.Handle<TimeoutRejectedException>()
.FallbackAsync(async (cancellationToken) => await Models.Audit.AddAsync((long)0, "Network Timeout fallback").ConfigureAwait(false))
.WrapAsync(GetRetryPolicy(serviceName));
}