public T Do <T>(Func <T> func, string actionName = "") { var sw = Stopwatch.StartNew(); Started?.Invoke(this, new RetryEventArgs(actionName, TimeSpan.Zero)); var attempt = 0; while (true) { attempt++; try { var result = func(); Success?.Invoke(this, new RetryEventArgs(actionName, sw.Elapsed)); return(result); } catch (Exception exc) { var eventArgs = new RetryFailureEventArgs(actionName, attempt, sw.Elapsed, exc); if (attempt < _numAttempts) { TransientFailure?.Invoke(this, eventArgs); _backoff(eventArgs).Wait(); } else { PermanentFailure?.Invoke(this, eventArgs); throw; } } } }
public async Task DoAsync(Func <Task> action, string actionName = "") { var sw = Stopwatch.StartNew(); Started?.Invoke(this, new RetryEventArgs(actionName, TimeSpan.Zero)); var attempt = 0; while (true) { attempt++; try { await action(); Success?.Invoke(this, new RetryEventArgs(actionName, sw.Elapsed)); break; } catch (Exception exc) { var eventArgs = new RetryFailureEventArgs(actionName, attempt, sw.Elapsed, exc); if (attempt < _numAttempts) { TransientFailure?.Invoke(this, eventArgs); await _backoff(eventArgs); } else { PermanentFailure?.Invoke(this, eventArgs); throw; } } } }
private static async Task Backoff(RetryFailureEventArgs retryFailureEventArgs) { await Task.Delay(TimeSpan.FromSeconds(retryFailureEventArgs.FailedAttempts)); }