Last active
December 29, 2015 07:09
-
-
Save buu700/7633622 to your computer and use it in GitHub Desktop.
Writing fault-tolerant codes would be a pain without this (licence: public domain)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Linq; | |
/// <summary> | |
/// | |
/// Helper class for retry logic | |
/// | |
/// Example usage: | |
/// | |
/// string[] strings = TryHelper.TryUntilSuccessful | |
/// ( | |
/// () => Cache.GetStrings(), | |
/// e => TryHelper.TryUntilSuccessful<string[], WebException> | |
/// ( | |
/// () => WebService.RequestStrings(), | |
/// maxAttempts: 3, | |
/// catchBlock: exception => | |
/// { | |
/// Log( exception ); | |
/// Thread.Sleep( TimeSpan.FromSeconds(30) ); | |
/// } | |
/// ), | |
/// e => new string[] {} | |
/// ); | |
/// | |
/// </summary> | |
public static class TryHelper | |
{ | |
#region Fields | |
const int DEFAULT_MAX_ATTEMPTS = 20; | |
#endregion | |
#region Public Methods | |
/// <summary> Iterates through a sequence of functions until one succeeds </summary> | |
public static T TryUntilSuccessful<T, E> | |
( | |
Func<T> start, | |
params Func<E, T>[] fallbacks | |
) where E : Exception | |
{ | |
try | |
{ | |
return start(); | |
} | |
catch( E firstException ) | |
{ | |
E exception = firstException; | |
int i = 0; | |
while( true ) | |
{ | |
try | |
{ | |
return fallbacks[i]( exception ); | |
} | |
catch( E e ) | |
{ | |
if( ++i < fallbacks.Length ) | |
{ | |
exception = e; | |
} | |
else | |
{ | |
throw; | |
} | |
} | |
} | |
} | |
} | |
/// <summary> Iterates through a sequence of functions until one succeeds </summary> | |
public static T TryUntilSuccessful<T> | |
( | |
Func<T> start, | |
params Func<Exception, T>[] fallbacks | |
) | |
{ | |
return TryUntilSuccessful<T, Exception>( start, fallbacks ); | |
} | |
/// <summary> Iterates through a sequence of functions until one succeeds </summary> | |
public static void TryUntilSuccessful<E> | |
( | |
Action start, | |
params Action<E>[] fallbacks | |
) where E : Exception | |
{ | |
TryUntilSuccessful<object, E>( ActionToFunc(start), ActionsToFuncs(fallbacks) ); | |
} | |
/// <summary> Iterates through a sequence of functions until one succeeds </summary> | |
public static void TryUntilSuccessful | |
( | |
Action start, | |
params Action<Exception>[] fallbacks | |
) | |
{ | |
TryUntilSuccessful<Exception>( start, fallbacks ); | |
} | |
/// <summary> Retries one function up to a specified number of times with an optional catch block in between </summary> | |
public static T TryUntilSuccessful<T, E> | |
( | |
Func<T> f, | |
int maxAttempts = DEFAULT_MAX_ATTEMPTS, | |
Action<E> catchBlock = null | |
) where E : Exception | |
{ | |
while( maxAttempts-- > 0 ) | |
{ | |
try | |
{ | |
return f(); | |
} | |
catch( E exception ) | |
{ | |
if( catchBlock != null ) | |
{ | |
catchBlock( exception ); | |
} | |
if( maxAttempts <= 0 ) | |
{ | |
throw; | |
} | |
} | |
} | |
return default( T ); | |
} | |
/// <summary> Retries one function up to a specified number of times with an optional catch block in between </summary> | |
public static T TryUntilSuccessful<T> | |
( | |
Func<T> f, | |
int maxAttempts = DEFAULT_MAX_ATTEMPTS, | |
Action<Exception> catchBlock = null | |
) | |
{ | |
return TryUntilSuccessful<T, Exception>( f, maxAttempts, catchBlock ); | |
} | |
/// <summary> Retries one function up to a specified number of times with an optional catch block in between </summary> | |
public static void TryUntilSuccessful<E> | |
( | |
Action f, | |
int maxAttempts = DEFAULT_MAX_ATTEMPTS, | |
Action<E> catchBlock = null | |
) where E : Exception | |
{ | |
TryUntilSuccessful<object, E>( ActionToFunc(f), maxAttempts, catchBlock ); | |
} | |
/// <summary> Retries one function up to a specified number of times with an optional catch block in between </summary> | |
public static void TryUntilSuccessful | |
( | |
Action f, | |
int maxAttempts = DEFAULT_MAX_ATTEMPTS, | |
Action<Exception> catchBlock = null | |
) | |
{ | |
TryUntilSuccessful<Exception>( f, maxAttempts, catchBlock ); | |
} | |
#endregion | |
#region Private Helpers | |
private static Func<T, object> ActionToFunc<T>( Action<T> action ) | |
{ | |
if( action == null ) | |
{ | |
return null; | |
} | |
return o => | |
{ | |
action( o ); | |
return null; | |
}; | |
} | |
private static Func<object> ActionToFunc( Action action ) | |
{ | |
if( action == null ) | |
{ | |
return null; | |
} | |
return () => | |
{ | |
action(); | |
return null; | |
}; | |
} | |
private static Func<T, object>[] ActionsToFuncs<T>( params Action<T>[] actions ) | |
{ | |
return actions.Select( ActionToFunc ).ToArray(); | |
} | |
private static Func<object>[] ActionsToFuncs( params Action[] actions ) | |
{ | |
return actions.Select( ActionToFunc ).ToArray(); | |
} | |
#endregion | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment