public class RetryUtil { private static readonly log4net.ILog _log = log4net.LogManager.GetLogger(typeof(RetryUtil)); /// <summary> /// Executes the specified function. /// </summary> /// <typeparam name="T">Type that the target funtion returns.</typeparam> /// <param name="func">The target function.</param> /// <param name="requiresRetry">Function that validates whether a retry is required based on the target function's output.</param> /// <param name="retryCount">The maximum number of times the target function should be executed.</param> /// <param name="sleepSeconds">The number of seconds to sleep the thread between retries.</param> /// <returns>The result of the target function.</returns> public T Execute<T>(Func<T> func, Func<T, bool> requiresRetry, int retryCount, int sleepSeconds) { var attempt = 0; while (attempt < retryCount) { try { _log.InfoFormat("Attempting call {0} of {1}", attempt + 1, retryCount); var t = func(); if (requiresRetry(t)) { attempt++; if (attempt >= retryCount) return t; _log.WarnFormat("Target method returned {0}... Retrying...", t); if (sleepSeconds > 0) { _log.InfoFormat("Sleeping thread for {0} seconds.", sleepSeconds); Thread.Sleep(TimeSpan.FromSeconds(sleepSeconds)); } continue; } return t; } catch (Exception ex) { attempt++; _log.Error(ex); if (attempt >= retryCount) throw; } } return default(T); } }
To call this utility, simply pass in a delegate (or lambda expression) that wraps your target method, a delegate (or lambda expression) that validates the return, a retry count, and the number of seconds you want to sleep the thread between retries.
public int TargetMethod(int foo) { //Do work.. return -1; } public void CallingMethod() { var retryUtil = new RetryUtil(); //Example call using delegates Func<int> target = delegate { return MyTargetMethod(123); }; Func<int, bool> validate = delegate(int foo) { return foo < 0; }; var result1 = retryUtil.Execute(target, validate, 5, 10); //Example using lambda expressions var result2 = retryUtil.Execute(() => MyTargetMethod(123), (i=> i < 0), 5, 10); }
No comments:
Post a Comment