public static async Task Retry(this IRetryPolicy retryPolicy, Func <Task> retryMethod, CancellationToken cancellationToken = default(CancellationToken)) { using (var retryContext = retryPolicy.GetRetryContext()) { await Attempt(retryContext, retryMethod, cancellationToken).ConfigureAwait(false); } }
async Task Attempt(RetryConsumeContext context, IPipe <ConsumeContext> next) { context.ClearPendingFaults(); TimeSpan delay; try { await next.Send(context).ConfigureAwait(false); return; } catch (Exception ex) { if (!_retryPolicy.CanRetry(ex)) { context.NotifyPendingFaults(); throw; } // by not adding the retry payload until the exception occurs, the deepest retry filter // is the one to set the actual retry context with the deepest configured policy IRetryContext retryContext = context.GetOrAddPayload(() => _retryPolicy.GetRetryContext()); if (!retryContext.CanRetry(ex, out delay)) { context.NotifyPendingFaults(); throw; } } await Task.Delay(delay).ConfigureAwait(false); await Attempt(context, next).ConfigureAwait(false); }
public async Task Send(ConsumeContext <T> context, IPipe <ConsumeContext <T> > next) { try { await next.Send(context); } catch (Exception ex) { if (!_retryPolicy.CanRetry(ex)) { throw; } try { MessageRedeliveryContext redeliveryContext; if (!context.TryGetPayload(out redeliveryContext)) { throw new ContextException("The message redelivery context was not available to delay the message", ex); } TimeSpan delay; using (IRetryContext retryContext = _retryPolicy.GetRetryContext()) { retryContext.CanRetry(ex, out delay); } await redeliveryContext.ScheduleRedelivery(delay); } catch (Exception redeliveryException) { throw new ContextException("The message delivery could not be rescheduled", new AggregateException(redeliveryException, ex)); } } }
public static async Task Retry <T>(this IRetryPolicy retryPolicy, ConsumeContext <T> context, Func <ConsumeContext <T>, Task> retryMethod) where T : class { using (IRetryContext retryContext = retryPolicy.GetRetryContext()) { await Attempt(retryContext, context, retryMethod).ConfigureAwait(false); } }
public static async Task RetryUntilCancelled(this IRetryPolicy retryPolicy, Func <Task> retryMethod, CancellationToken cancellationToken = default(CancellationToken)) { await Task.Yield(); while (!cancellationToken.IsCancellationRequested) { using (var retryContext = retryPolicy.GetRetryContext()) { await Attempt(retryContext, retryMethod, cancellationToken).ConfigureAwait(false); } } }
/// <summary> /// Retry a task composition using the specified retry policy /// </summary> /// <typeparam name="T">The composer payload type</typeparam> /// <param name="composer">The task composer</param> /// <param name="retryPolicy">The retry policy</param> /// <param name="callback">The task composition callback</param> /// <returns>The original task composer</returns> public static Composer <T> Retry <T>(this Composer <T> composer, IRetryPolicy retryPolicy, Action <Composer <T> > callback) { IRetryContext retryContext = null; composer.ComposeTask(taskComposer => { retryContext = retryPolicy.GetRetryContext(); Attempt(taskComposer, retryContext, callback); }); composer.Finally((_, status) => { if (retryContext != null) { retryContext.Complete(status); } }); return(composer); }
public IRetryContext GetRetryContext() { return(new CancelRetryContext(_retryPolicy.GetRetryContext(), _cancellationToken)); }