Friday, 12 August 2011

Retry class implemented in functional C#

public class Retry
{
  public static ILog _log = LogManager.GetLogger(MethodInfo.GetCurrentMethod().DeclaringType);
  int _retryAttempts = 3;
  int _retryWaitSeconds = 1;
  public Retry() { }
  public Retry(int retryAttempts, int retryWaitSeconds)
  {
    _retryAttempts = retryAttempts;
    _retryWaitSeconds = retryWaitSeconds;
  }
  public void Execute(Action action)
  {
    int attempt = 0;
    while (attempt++ < _retryAttempts)
    {
      try
      {
        if (_log.IsDebugEnabled)
        {
          _log.DebugFormat("Retry attempt {0}/{1}", attempt, _retryAttempts);
        }
        action();
        return;
      }
      catch (Exception e)
      {
        if (attempt >= _retryAttempts)
        {
          _log.ErrorFormat("Retry failed with {0} attempts", _retryAttempts);
          throw e;
        }
        int wait = _retryWaitSeconds * attempt;
        _log.Warn(string.Format("Retry attempt {0}/{1} failed, waiting {2}s", attempt, _retryAttempts, wait), e);
        Thread.Sleep(1000 * wait);
      }
    }
  }
  public TResult Execute<TResult>(Func<TResult> func)
  {
    int attempt = 0;
    while (attempt++ < _retryAttempts)
    {
      try
      {
        if (_log.IsDebugEnabled)
        {
          _log.DebugFormat("Retry attempt {0}/{1}", attempt, _retryAttempts);
        }
        return func();
      }
      catch (Exception e)
      {
        if (attempt >= _retryAttempts)
        {
          _log.ErrorFormat("Retry failed with {0} attempts", _retryAttempts);
          throw e;
        }
        int wait = _retryWaitSeconds * attempt;
        _log.Warn(string.Format("Retry attempt {0}/{1} failed, waiting {2}s", attempt, _retryAttempts, wait), e);
        Thread.Sleep(1000 * wait);
      }
    }
    throw new Exception("Retry failed");
  }
}
[TestFixture]
public class TestRetry
{
  [Test]
  public void Test()
  {
    new Retry(3, 1).Execute(SuccessAction);
    try
    {
      new Retry(3, 1).Execute(FailureAction);
    }catch(Exception ex)
    {
      Console.WriteLine("Failed");
    }
    Console.WriteLine(new Retry(3, 1).Execute(() => ComplexAction("1", "2")));
    Console.WriteLine(new Retry(3, 1).Execute(() => ObjectAction("John")).ToString());
    Func<Person> func = () =>
    {
      return new Person() { Name = "John" };
    };
    Console.WriteLine(new Retry(3, 1).Execute(func));
  }
  private void FailureAction()
  {
    Console.WriteLine("{0}: Failed", DateTime.Now);
    throw new Exception("Failed Exception");
  }
  private void SuccessAction()
  {
    Console.WriteLine("{0}: OK", DateTime.Now);
  }
  private string ComplexAction(string a, string b)
  {
    return String.Format("{0} {1}", a, b);
  }
  private Person ObjectAction(string name)
  {
    return new Person() { Name = name };
  }
}
class Person
{
  public string Name { get; set; }
  public override string ToString()
  {
    return "My name is : " + Name;
  }
}

No comments:

Post a Comment