Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cleanest way to write retry logic?

Tags:

c#

.net

Occasionally I have a need to retry an operation several times before giving up. My code is like:

int retries = 3; while(true) {   try {     DoSomething();     break; // success!   } catch {     if(--retries == 0) throw;     else Thread.Sleep(1000);   } } 

I would like to rewrite this in a general retry function like:

TryThreeTimes(DoSomething); 

Is it possible in C#? What would be the code for the TryThreeTimes() method?

like image 280
noctonura Avatar asked Oct 13 '09 22:10

noctonura


People also ask

How do you write retry logic in Java?

1. Simple for-loop with try-catch. A simple solution to implement retry logic in Java is to write your code inside a for loop that executes the specified number of times (the maximum retry value).

What is a retry logic?

Retry logic is implemented whenever there is a failing operation. Implement retry logic only where the full context of a failing operation. It's important to log all connectivity failures that cause a retry so that underlying problems with the application, services, or resources can be identified.

What is retry strategy?

Manage operations that continually fail: Although a retry strategy will define the maximum number of times that an operation should be retried, it does not prevent the application repeating the operation again, with the same number of retries.


2 Answers

Blanket catch statements that simply retry the same call can be dangerous if used as a general exception handling mechanism. Having said that, here's a lambda-based retry wrapper that you can use with any method. I chose to factor the number of retries and the retry timeout out as parameters for a bit more flexibility:

public static class Retry {     public static void Do(         Action action,         TimeSpan retryInterval,         int maxAttemptCount = 3)     {         Do<object>(() =>         {             action();             return null;         }, retryInterval, maxAttemptCount);     }      public static T Do<T>(         Func<T> action,         TimeSpan retryInterval,         int maxAttemptCount = 3)     {         var exceptions = new List<Exception>();          for (int attempted = 0; attempted < maxAttemptCount; attempted++)         {             try             {                 if (attempted > 0)                 {                     Thread.Sleep(retryInterval);                 }                 return action();             }             catch (Exception ex)             {                 exceptions.Add(ex);             }         }         throw new AggregateException(exceptions);     } } 

You can now use this utility method to perform retry logic:

Retry.Do(() => SomeFunctionThatCanFail(), TimeSpan.FromSeconds(1)); 

or:

Retry.Do(SomeFunctionThatCanFail, TimeSpan.FromSeconds(1)); 

or:

int result = Retry.Do(SomeFunctionWhichReturnsInt, TimeSpan.FromSeconds(1), 4); 

Or you could even make an async overload.

like image 165
LBushkin Avatar answered Nov 17 '22 22:11

LBushkin


You should try Polly. It's a .NET library written by me that allows developers to express transient exception handling policies such as Retry, Retry Forever, Wait and Retry or Circuit Breaker in a fluent manner.

Example

Policy     .Handle<SqlException>(ex => ex.Number == 1205)     .Or<ArgumentException>(ex => ex.ParamName == "example")     .WaitAndRetry(3, retryAttempt => TimeSpan.FromSeconds(3))     .Execute(() => DoSomething()); 
like image 21
Michael Wolfenden Avatar answered Nov 18 '22 00:11

Michael Wolfenden