Introduction
When you develop an application, you may have to execute a set of methods in sequential order to complete the business requirements. If you got an exception from one of the methods, the entire process will fail. The exception may occur when you connect the external services or network connection issue or other external factors. If you retry the failure process with specified interval, you may get a success result and you can execute the rest of the methods.
You can use the retry mechanism in two different situations:
- Getting exception when you execute a method
- A method may not return an expected result
Application Demo
I want to explain one demo application to describe the need of retry mechanism.
There are three methods needed to execute from the main
method, if it fails, the main
method will retry the failed methods.
private static bool SendEmail()
{
Console.WriteLine("Sending Mail ...");
Random rnd = new Random();
var rndNumber = rnd.Next(1, 10);
if (rndNumber != 3)
throw new SmtpFailedRecipientException();
Console.WriteLine("Mail Sent successfully");
return true;
}
private static bool ConnectDatabase()
{
Console.WriteLine("Trying to connect database ...");
throw new Exception("Not able to connect database");
}
private static int GetRandomNumber()
{
Random rnd = new Random();
var result = rnd.Next(1, 10);
Console.WriteLine(result.ToString());
return result;
}
static void Main(string[] args)
{
Console.WriteLine("Send mail, if it fails then try 10 times");
var isSuccess = Retry.Execute(() => SendEmail(), new TimeSpan(0, 0, 1), 10, true);
if (!isSuccess)
Console.WriteLine("Unable to send a mail");
var connectionStatus = Retry.Execute(() => ConnectDatabase(), new TimeSpan(0, 0, 2), 5, true);
if (!connectionStatus)
Console.WriteLine("Unable connect database");
Console.WriteLine("Print Random number till the random number is 4");
Retry.Execute(() => GetRandomNumber(), new TimeSpan(0, 0, 1), 10, 4);
Console.ReadLine();
}
Here are the ways to implement the Retry mechanism in different situations.
Output
Generic Retry Class
public class Retry
{
public static TResult Execute<TResult>(
Func<TResult> action,
TimeSpan retryInterval,
int retryCount,
TResult expectedResult,
bool isExpectedResultEqual = true,
bool isSuppressException = true
)
{
TResult result = default(TResult);
bool succeeded = false;
var exceptions = new List<Exception>();
for (int retry = 0; retry < retryCount; retry++)
{
try
{
if (retry > 0)
Thread.Sleep(retryInterval);
result = action();
if (isExpectedResultEqual)
succeeded = result.Equals(expectedResult);
else
succeeded = !result.Equals(expectedResult);
}
catch (Exception ex)
{
exceptions.Add(ex);
}
if (succeeded)
return result;
}
if (!isSuppressException)
throw new AggregateException(exceptions);
else
return result;
}
}