RetryPolicy Using Microsoft Practices Enterprise Library

In today’s software development world, almost all applications are connected. In some or many ways they’re connected to network-based services. Te Ihnternet is one such network, which sometimes is not reliable due to slow connections, timeouts, and other connection un-availability issues. It is most important for any application to handle such situations in a graceful manner. That means, these things happens and are meant to happen, so how should an application respond to these scenarios without reducing  the “Reliability” factor?

An example scenario

Let’s take an example of an application which displays some information from an RSS/Atom feed. Now once in a while, the RSS/Atom host server become unreachable for a short span of time (say 10-20 sec.) due to the above-mentioned reasons. We have a couple of options to deal with such situations. Try reading from the feed, and when there’s an error, show the user that feed is not available and try again. The user tries again and the application successfully reads the feed and displays the information to user. Or the application can retry the fetch operation a couple of times, and when it’s available display the information to the user without any user interaction. This depends on the business scenario but it increases the Reliability.



A high level view of Retry mechanism

When to apply the Retry mechanism

In most scenarios at least, important read operations can be marked to engage the server with Retry operation for specific errors like network timeout, connection unreachable, etc. Another example that I assume everybody has seen while downloading something from Internet andthe  connection goes down, is the browser waits and retries for some time before actually aborting the download.

Implementation

To introduce this behavior I prefer TrasientFaultHandling from Microsoft Practice Enterprise library. It’s available as an individual NuGet package so you won’t need to install the whole Enterprise Library monster project. Although you can use any other utility which provides Retry mechanism or implement your own, IMO if something is already there, well-tested, and optimized then why wasting time re-inventing the wheel.

Installing Nuget package

Add the NuGet package TransientFaultHandling.Core in your project to have the required library classes and method available for usage.

Implementing Transient Fault detection policy/strategy

Transient fault/exceptions are identified as temporary errors and probably can be fixed by retrying the operation. To introduce such types of fault/exceptions we need to implement the policy/strategy by implementing the interface ITransientErrorDetectionStrategy.

  1. /// <summary>  
  2. /// Provides the transient error detection logic that can recognize transient faults when dealing with reading online feed.   
  3. /// </summary>  
  4. internal class DownloadFeedTrasientErrorDetectionStrategy: ITransientErrorDetectionStrategy   
  5. {  
  6.     /// <summary>  
  7.     /// Determines whether the specified exception represents a transient failure that can be compensated by a retry.  
  8.     /// </summary>  
  9.     /// <param name="ex">The exception object to be verified.</param>  
  10.     /// <returns>True if the specified exception is considered as transient, otherwise false.</returns>  
  11.     public bool IsTransient(Exception ex)  
  12.     {  
  13.         return CheckIsTransientInternal(ex);  
  14.     }  
  15.   
  16.     /// <summary>  
  17.     /// Allows you to override the call to change or extend the behavior by extending this class.  
  18.     /// </summary>  
  19.     /// <param name="ex">The error to check.</param>  
  20.     /// <returns></returns>  
  21.     protected virtual bool CheckIsTransientInternal(Exception ex)  
  22.     {  
  23.         return CheckIsTransient(ex);  
  24.     }  
  25.   
  26.     private static bool CheckIsTransient(Exception ex)  
  27.     {  
  28.         if (ex is TimeoutException)   
  29.         {  
  30.             return true;  
  31.         } else if (ex is WebException)   
  32.         {  
  33.             return true;  
  34.         } else if (ex is UnauthorizedAccessException)  
  35.         {  
  36.             return false;  
  37.         }  
  38.   
  39.         return false;  
  40.     }  
  41. }  
view rawDownloadFeedTrasientErrorDetectionStrategy.cs hosted with ❤ by GitHub

 

A straight forward usage of Retry utility:

  1. public class FeedDao {  
  2.     private readonly RetryPolicy retryPolicy;  
  3.   
  4.     public FeedDao()  
  5.   {  
  6.         // setup retry policy that will try 3 times, with fast retry for first time and then   
  7.         // with incremental interval by 1.5 seconds.  
  8.         this.retryPolicy =  
  9.             new RetryPolicy < DownloadFeedTrasientErrorDetectionStrategy >  
  10.           (  
  11.                 new Incremental(3, TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(1.5))   
  12.           {  
  13.                     FastFirstRetry = true  
  14.                 });  
  15.   
  16.         // Set tracing if retry happened.  
  17.         this.retryPolicy.Retrying += (s, e) =>  
  18.             Trace.TraceWarning("An error occurred in attempt number {1} to download feed: {0}", e.LastException.Message, e.CurrentRetryCount);  
  19.     }  
  20.   
  21.     public void GetFeed()  
  22.   {  
  23.         this.retryPolicy.ExecuteAction(() => this.DownloadFeed(feed_source));  
  24.     }  
  25.   
  26.     private string DownloadFeed(string source)   
  27.   {  
  28.         // logic to retrieve feeds  
  29.         return result;  
  30.     }  
  31. }  
view rawFeedDao.cs hosted with ❤ by GitHub.

 

Code Explanation:

The RetryPolicy is a class from TransientFaultHandling namespace.
  1. this.retryPolicy = new RetryPolicy < DownloadFeedTrasientErrorDetectionStrategy > (new Incremental(3, TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(1.5))   
  2. {  
  3.     FastFirstRetry = true  
  4. });  

The above snippet is an interesting one. Here we’ve used the Generic constructor of RetryPolicy. The class Incremental is RetryStrategy which takes similar arguments as defined in RetryPolicy class constructor.

  1. this.retryPolicy.ExecuteAction(() => this.DownloadFeed(feed_source));   

The above line shows how the actual network based method call is wrapped with Retry logic. It takes simple void Action delegate which is represented as LambdaExpression.

This is a simplest usage of RetryPolicy. Really easy, isn’t it? But this is all you need to do to introduce Retry stuff in your application. Who else is using – Entity Framework, Windows Azure service and many other important products are using this library.