Monday, November 14, 2011

Generic retry mechanism & catch using generic exception type

Couple of weeks back we faced one situation where a portion of our code breaks due to a IIS not available situation and we were advised to implement a retry mechanism.Hope I can talk about that server down problem in future posts. The retry mechanism needs to implement based on the exception which will occur on that particular scenario. We tried test code by putting the try catch block and could see its working in one place. But there  are a bunch of other areas we need to modify the code.Also in future too developers may need to use this retry mechanism.
The architect resting in me jumped and said that we can use a generic retry mechanism using .net generics. My colleagues were in little confusion about how to achieve a generic mechanism for retry where the size and location of code differs and spread out in 150 projects.With the help of Action delegate I was able to convince them and the subsequent google gave us ready made code to do the same.
public static void ExecuteWithRetry( Action action, UInt16 noOfAttempts )
{
    //Validate args:Throw exception on retryCount=0
    int count = 1;
    for (; ; count++)
    {
        try
        {
            action();
            break;
        }
        catch (ReTryableException ex)
        {
            Log(ex, count);
            if (count == noOfAttempts) throw;
        }
    }
}

Everybody became happy like after the first fight seen in movies. We know that the movie needs to complete its 2 hours with excitement and for that villain  should come back with more power. Here too the villain come back when the perfectionist in me put forward the suggestion of making it real generic so that we can move to the utility project and can be consumed by other fellow developers as well. So we rewrote the logic as follows.


public static void ExecuteWithRetry<TException> ( Action action, UInt16 noOfAttempts ) where TException :Exception   
{
    //Validate args:Throw exception on retryCount=0
    int count=1;
    for(;;count++)
    {
        try
        {
            action();
            break;
        }
        catch (TException ex)
        {
            Log(ex, count);
            if (count == noOfAttempts) throw;
        }
    } 
}

Oh what an idea sir ji…There was one more suggestion came to make retry after specific interval. But before that we tried to integrate modified function in our app.

Catching exception using generic type

Here starts the second part of the story. When we run from Visual studio it didn’t hit the catch block!!! Theoretically there are no issues but practically it failed. At least for some moment surrounding people even I thought that our understanding about either Exception handling or generics is wrong. Even we thought of getting rid of this concept and write redundant retry code everywhere. But when we came back to our original state , we googled it and find that it is a BUG in .Net when running inside Visual Studio debugging mode.We tried running by double clicking the application and it works perfect.We were also able to see this bug in the Microsoft connect and says its fixed.

There is on workaround available for this issue its as follows

catch (Exception ex)
{
    TException tEx = ex as TException;
    if (tEx != null) { /*Process */}
    else throw;
}

This changed my perception

“The bug is there only due to poor dev’s coding mistake never by compilers, development tools or the framework”

to

“Compilers, development tools and frameworks are also coded by developers”.

Later I happen to read a post about fixing a compiler bug which enforced my perception.

No comments: