public virtual bool CanRetry(RetryContext context) { Exception ex = context.LastException; // N.B. the contract is defined to include the initial attempt in the count. return((ex == null || RetryForException(ex)) && (context.RetryCount < _maxAttempts)); }
/// <summary> /// Keep executing the callback until it eiether succeeds or the policy dictates that we stop, /// in which case the most recent exception thrown by the callback will be rethrown. /// </summary> /// <param name="callback">Callback interface for an operation that can be retried</param> /// <returns>Return value of the callback</returns> /// <typeparam name="T">Return type</typeparam> public T Execute <T>(Func <RetryContext, T> callback) { Exception lastException = null; RetryContext context = new RetryContext(_retryPolicy.MaxAttempts, _retryPolicy.BackOffPeriod); while (_retryPolicy.CanRetry(context) && !context.IsExhausted) { try { lastException = null; return(callback(context)); } catch (Exception ex) { lastException = ex; _retryPolicy.RegisterThrowable(context, ex); if (!_retryPolicy.CanRetry(context)) { // Rethrow last exception throw; } } var onRetryHandler = OnRetry; if (onRetryHandler != null) { onRetryHandler(context); } _retryPolicy.BackOff(context); } return(_retryPolicy.HandleRetryExhausted <T>(context)); }
/// <summary> /// Keep executing the callback until it eiether succeeds or the policy dictates that we stop, /// in which case the most recent exception thrown by the callback will be rethrown. /// </summary> /// <param name="callback">Callback interface for an operation that can be retried</param> /// <returns>Return value of the callback</returns> /// <typeparam name="T">Return type</typeparam> public async Task <T> ExecuteAsync <T>(Func <RetryContext, Task <T> > callback) { Exception lastException = null; RetryContext context = new RetryContext(_retryPolicy.MaxAttempts, _retryPolicy.BackOffPeriod); while (_retryPolicy.CanRetry(context) && !context.IsExhausted) { try { lastException = null; return(await callback(context).ConfigureAwait(false)); } catch (Exception ex) { lastException = ex; _retryPolicy.RegisterThrowable(context, ex); if (!_retryPolicy.CanRetry(context)) { // Rethrow last exception throw; } } var onRetryHandler = OnRetry; if (onRetryHandler != null) { onRetryHandler(context); } await _retryPolicy.BackOffAsync(context).ConfigureAwait(false); } return(_retryPolicy.HandleRetryExhausted <T>(context)); }
public virtual T HandleRetryExhausted <T>(RetryContext context) { throw new ExhaustedRetryException("Retry exhausted after last attempt with no recovery path.", context.LastException); }
public virtual Task BackOffAsync(RetryContext context) { return(Task.Delay(BackOffPeriod)); }
public virtual void BackOff(RetryContext context) { Thread.Sleep(BackOffPeriod); }
public virtual void RegisterThrowable(RetryContext context, Exception exception) { context.RegisterException(exception); }