Dan Alexandru Hintea/ March 3, 2020/ Code Snippets, Universal/ 0 comments

I wrote this extension as a try-catch-retry sugarcoat.

await
    new Func(
        async () => await asyncUseCase.DoStuff(alpha, beta)
    )
    .TryOrFailWithGrace(
        numberOfTimes: 1,
        onFail: ex => Log(ex)
    );

Here is the implementation, it’s unit-tested, you can safely copy-paste it, but please credit me if you do.

public static class ExecutionUtilities
{
    public static void TryAFewTimesOrFailWithGrace(Action doThis, int numberOfTimes = 5, Action onFail = null, Action onRetry = null, int millisecondsToSleepBetweenRetries = 500)
    {
        if (numberOfTimes <= 0)
            return;

        try
        {
            doThis.Invoke();
        }
        catch (Exception ex)
        {
            numberOfTimes--;
            if (numberOfTimes == 0)
            {
                try { onFail?.Invoke(ex); } catch (Exception) { }
                return;
            }
            else
                try { onRetry?.Invoke(ex); } catch (Exception) { }

            System.Threading.Thread.Sleep(millisecondsToSleepBetweenRetries);

            TryAFewTimesOrFailWithGrace(doThis, numberOfTimes, onFail, onRetry, (int)(millisecondsToSleepBetweenRetries * 1.3));
        }
    }

    public static async Task TryAFewTimesOrFailWithGrace(Func doThis, int numberOfTimes = 5, Action onFail = null, Action onRetry = null, int millisecondsToSleepBetweenRetries = 500)
    {
        if (numberOfTimes <= 0)
            return;

        try
        {
            await doThis.Invoke();
        }
        catch (Exception ex)
        {
            numberOfTimes--;
            if (numberOfTimes == 0)
            {
                try { onFail?.Invoke(ex); } catch (Exception) { }
                return;
            }
            else
                try { onRetry?.Invoke(ex); } catch (Exception) { }

            System.Threading.Thread.Sleep(millisecondsToSleepBetweenRetries);

            await TryAFewTimesOrFailWithGrace(doThis, numberOfTimes, onFail, onRetry, (int)(millisecondsToSleepBetweenRetries * 1.3));
        }

    }

    public static async Task TryAFewTimesOrFailWithGrace(Func doThis, int numberOfTimes = 5, Func onFail = null, Func onRetry = null, int millisecondsToSleepBetweenRetries = 500)
    {
        if (numberOfTimes <= 0)
            return;

        try
        {
            await doThis.Invoke();
        }
        catch (Exception ex)
        {
            numberOfTimes--;
            if (numberOfTimes == 0)
            {
                try { await onFail?.Invoke(ex); } catch (Exception) { }
                return;
            }
            else
                try { await onRetry?.Invoke(ex); } catch (Exception) { }

            System.Threading.Thread.Sleep(millisecondsToSleepBetweenRetries);

            await TryAFewTimesOrFailWithGrace(doThis, numberOfTimes, onFail, onRetry, (int)(millisecondsToSleepBetweenRetries * 1.3));
        }

    }

    public static void TryOrFailWithGrace(this Action doThis, int numberOfTimes = 5, Action onFail = null, Action onRetry = null, int millisecondsToSleepBetweenRetries = 500)
        => TryAFewTimesOrFailWithGrace(doThis, numberOfTimes, onFail, onRetry, millisecondsToSleepBetweenRetries);

    public static Task TryOrFailWithGrace(this Func doThis, int numberOfTimes = 5, Action onFail = null, Action onRetry = null, int millisecondsToSleepBetweenRetries = 500)
        => TryAFewTimesOrFailWithGrace(doThis, numberOfTimes, onFail, onRetry, millisecondsToSleepBetweenRetries);

    public static Task TryOrFailWithGrace(this Func doThis, int numberOfTimes = 5, Func onFail = null, Func onRetry = null, int millisecondsToSleepBetweenRetries = 500)
        => TryAFewTimesOrFailWithGrace(doThis, numberOfTimes, onFail, onRetry, millisecondsToSleepBetweenRetries);
}
Share this Post

Leave a Comment

Your email address will not be published. Required fields are marked *

*
*