How to implement Polly Retry and Fallback

winanjaya 141 Reputation points
2023-11-08T11:21:32.4433333+00:00

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));
}
ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
3,764 questions
{count} votes