Skip to content

Instantly share code, notes, and snippets.

@buu700
Last active December 29, 2015 07:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save buu700/7633622 to your computer and use it in GitHub Desktop.
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)
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