Retry Helper

One of the smaller NUGET packages I’ve published in the last few years is CG.Retry. This package contains a single utility class, named RetryHelper, which simplifies the process of retrying blocks of code. Here’s a quick example:

 

So, the RetryHelper constructor accepts a number which represents the maximum number of possible retries allowed. After that, any exceptions are allowed to percolate out into the code, just like they normally would have. The Execute method accepts a single Action, one that contains the business logic to be performed. That logic can do or be anything, the point is that it represents code that might throw an exception if it fails. Those exceptions are caught internally, inside the RetryHelper object, which then retries the operation until it either succeeds or we’ve tried the maximum number of times.

This simple approach works well for simple cases, but, of course, there are also more complicated possibilities out there. For instance, here is the same example again, except now we’ve added a second parameter, a Func, to control whether or not to continue retry process:

 

Of course, there are endless possibilities here, including the ability to execute the code asynchronously, using the Task Asynchronous Pattern (TAP). We could also add additional parameters on the delegates, and on an on …

The point though, is that the RetryHelper class just sits there and retries operations as long as either: (1) the maximum number of retries hasn’t been reached, and/or (2) the (optional) second delegate returns TRUE to indicate that the retries should continue.

 

The Class

The source code for the class is surprising long and repetitive, with both synchronous and asynchronous variations of the Execute method that accept any number of parameters, all the way from none to three. I know, that many! :o)

If you need any more parameters than that, you’re on your own.

As I’ve said, the code listing is repetitive, and long, so I won’t show the entire class here. Instead, I’ll just detail the simpler variation of Execute to demonstrate how the logic works:

 

This is a blocking, synchronous variation of the Execute method. The simplest possible version of Execute. The first thing we do here is validate the parameter using the Guard (Guard is a simple Fluent-style parameter validation API that can be downloaded from my CG.Validation NUGET package). MaxRetries is a parameter that is saved from the RetryHelper constructor. If the number is zero the class simply invokes the delegate with no retry logic. On the other hand, if MaxRetries contains a number greater than zero, then we loop and start our retry logic. Inside the loop, we invoke the delegate. If no exceptions occur, then we simply break out of the loop and return. If there are exceptions, we enter the catch block where we check how many times we’ve gone through the retry loop. If the maximum number has been reached then we rethrow the exception, which effectively ends our involvement. If the maximum number has not been reached then we wait a pseudo random amount of time, bump up the try count, and try everything over again.

You may have noticed the Ranges array, as well as the Random object, and wondered about those. Both of those things are created as part of the RetryHelper constructor. Let’s go look at that now:

 

The constructor accepts a single parameter, maxRetries, which determines how many times this instance of RetryHelper will attempt to retry any given operation before giving up. Inside the constructor, we validate the maxRetries parameter using the Guard instance. Next we store the validated parameter value in the MaxRetries property. Next we create a Random object, which we’ll use, elsewhere, to generate pseudo-random delay periods between retry attempts. Finally, we loop through and generate an array of high-low limits for those delay periods I just spoke of. We’ll use this information later, inside the Execute methods, to generate a slightly longer delay for each retry attempt.

There is also a constructor variant that accepts an array of high-low limits directly, in case the caller wants to control what those delay ranges are. The code for that is pretty straightforward though, so I won’t cover it here.

Let’s see, I think that’s about it for the class itself. As I’ve said before, there are many different overloads so if you need to pass parameters to your delegate I’ve probably got you covered.

 

The package

The code for this article is part of my NUGET package CG.Retry, which can be downloaded for free at

https://github.com/CodeGator/CG.Retry

 

The source code for the CG.Retry project lives on Github and can be obtained for free at

https://www.nuget.org/packages/CG.Retry

 

See ya next time! :o)

 

 

 

Photo by Gabriel Benois on Unsplash