/// <summary> /// Method for registering a context - should only be used by /// <see cref="IRetryOperations{T}"/> implementations to ensure that /// <see cref="GetContext"/> always returns the correct value. /// </summary> /// <param name="context">The new context to register.</param> /// <returns>The old context if there was one.</returns> public static IRetryContext Register(IRetryContext context) { var oldContext = GetContext(); RetrySynchronizationManager.context.Value = context; return(oldContext); }
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)); } } }
/// <summary>Delegate to the policies that were in operation when the context was /// created. If any of them cannot retry then return false, otherwise return true.<see cref="IRetryPolicy.CanRetry"/></summary> /// <param name="context">The context.</param> /// <returns>The System.Boolean.</returns> public bool CanRetry(IRetryContext context) { var contexts = ((CompositeRetryContext)context).contexts; var policies = ((CompositeRetryContext)context).policies; var retryable = true; if (this.optimistic) { retryable = false; for (var i = 0; i < contexts.Length; i++) { if (policies[i].CanRetry(contexts[i])) { retryable = true; } } } else { for (var i = 0; i < contexts.Length; i++) { if (!policies[i].CanRetry(contexts[i])) { retryable = false; } } } return(retryable); }
private void DoCloseInterceptors <T>(Func <IRetryContext, T> callback, IRetryContext context, Exception lastException) { for (var i = this.listeners.Length; i-- > 0;) { this.listeners[i].Close(context, callback, lastException); } }
private void DoOnErrorInterceptors <T>(Func <IRetryContext, T> callback, IRetryContext context, Exception throwable) { for (var i = this.listeners.Length; i-- > 0;) { this.listeners[i].OnError(context, callback, throwable); } }
/// <summary>Delegate to the policies that were in operation when the context was /// created. If any of them fails to close the exception is propagated (and /// those later in the chain are closed before re-throwing).<see cref="IRetryPolicy.Close"/></summary> /// <param name="context">The context.</param> /// <exception cref="Exception"></exception> public void Close(IRetryContext context) { var contexts = ((CompositeRetryContext)context).contexts; var policies = ((CompositeRetryContext)context).policies; Exception exception = null; for (var i = 0; i < contexts.Length; i++) { try { policies[i].Close(contexts[i]); } catch (Exception e) { if (exception == null) { exception = e; } } } if (exception != null) { throw exception; } }
public static IRetryContext Register(IRetryContext context) { var oldContext = GetContext(); _context.Value = context; return(oldContext); }
public async Task PerformAsync(IRetryContext context, CancellationToken cancellationToken) { ThrowIf.Null(context, "context"); await context.Request.PerformAsync(cancellationToken); context.Request.ProcessResult(context); }
/// <summary>The register exception.</summary> /// <param name="context">The context.</param> /// <param name="exception">The exception.</param> public void RegisterException(IRetryContext context, Exception exception) { this.policy = this.exceptionClassifier.Classify(exception); AssertUtils.ArgumentNotNull(this.policy, "Could not locate policy for exception=[" + exception + "]."); this.context = this.GetContext(this.policy, context.GetParent()); this.policy.RegisterException(this.context, exception); }
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); }
/// <summary>Delegate to the policies that were in operation when the context was /// created. If any of them cannot retry then return false, otherwise return true.<see cref="IRetryPolicy.CanRetry"/></summary> /// <param name="context">The context.</param> /// <returns>The System.Boolean.</returns> public bool CanRetry(IRetryContext context) { var contexts = ((CompositeRetryContext)context).contexts; var policies = ((CompositeRetryContext)context).policies; var retryable = true; if (this.optimistic) { retryable = false; for (var i = 0; i < contexts.Length; i++) { if (policies[i].CanRetry(contexts[i])) { retryable = true; } } } else { for (var i = 0; i < contexts.Length; i++) { if (!policies[i].CanRetry(contexts[i])) { retryable = false; } } } return retryable; }
/// <summary>The register exception.</summary> /// <param name="context">The context.</param> /// <param name="exception">The exception.</param> public void RegisterException(IRetryContext context, Exception exception) { var policy = (IRetryPolicy)context; policy.RegisterException(context, exception); ((RetryContextSupport)context).RegisterException(exception); }
static async Task <T> Attempt <T>(IRetryContext retryContext, Func <Task <T> > retryMethod, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { throw new TaskCanceledException(); } TimeSpan delay; try { return(await retryMethod().ConfigureAwait(false)); } catch (Exception ex) { if (!retryContext.CanRetry(ex, out delay)) { throw; } } await Task.Delay(delay, cancellationToken).ConfigureAwait(false); return(await Attempt(retryContext, retryMethod, cancellationToken).ConfigureAwait(false)); }
public object Recover(IRetryContext context) { replyMessage.Value = SendRetryContextAccessor.GetMessage(context); replyAddress.Value = SendRetryContextAccessor.GetAddress(context); throwable.Value = context.LastException; return(null); }
public static IRetryContext Clear() { var value = GetContext(); IRetryContext parent = value == null ? null : value.Parent; _context.Value = parent; return(value); }
/// <summary>The close.</summary> /// <param name="context">The context.</param> public void Close(IRetryContext context) { // Only close those policies that have been used (opened): foreach (var policy in this.contexts.Keys) { policy.Close(this.GetContext(policy, context.GetParent())); } }
public static async Task Retry(this IRetryPolicy retryPolicy, Func <Task> retryMethod, CancellationToken cancellationToken = default(CancellationToken)) { using (IRetryContext retryContext = retryPolicy.GetRetryContext()) { await Attempt(retryContext, retryMethod, cancellationToken).ConfigureAwait(false); } }
public async Task PerformAsync(IRetryContext context, CancellationToken cancellationToken) { ThrowIf.Null(context, "context"); foreach (IStrategy strategy in this.strategies) { await strategy.PerformAsync(context, cancellationToken); } }
public async Task PerformAsync(IRetryContext context, CancellationToken cancellationToken) { ThrowIf.Null(context, "context"); if (this.condition(context)) { await this.strategy.PerformAsync(context, cancellationToken); } }
public bool Open(IRetryContext context) { if (_adapter.RecoveryCallback != null) { _attributesHolder.Value = context; } return(true); }
public object Recover(IRetryContext context) { if (!ShouldRequeue((MessagingException)context.LastException)) { return(_recoveryCallback.Recover(context)); } throw (MessagingException)context.LastException; }
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); } }
/// <summary>The recover.</summary> /// <param name="context">The context.</param> /// <returns>The System.Object.</returns> public object Recover(IRetryContext context) { if (this.recoverer != null) { return(this.recoverer.Recover <object>(this.args, context.LastException)); } throw new ExhaustedRetryException("Retry was exhausted but there was no recovery path."); }
/// <summary>The can retry.</summary> /// <param name="context">The context.</param> /// <returns>The System.Boolean.</returns> public bool CanRetry(IRetryContext context) { if (this.context == null) { // there was no error yet return(true); } return(this.policy.CanRetry(this.context)); }
/// <summary>Creates a new context that copies the existing policies and keeps a list of the contexts from each one. <see cref="IRetryPolicy.Open"/></summary> /// <param name="parent">The parent.</param> /// <returns>The Spring.Retry.Retry.IRetryContext.</returns> public IRetryContext Open(IRetryContext parent) { var list = new List <IRetryContext>(); for (var i = 0; i < this.policies.Length; i++) { list.Add(this.policies[i].Open(parent)); } return(new CompositeRetryContext(parent, list, this)); }
private bool DoOpenInterceptors <T>(Func <IRetryContext, T> callback, IRetryContext context) { var result = true; for (var i = 0; i < this.listeners.Length; i++) { result = result && this.listeners[i].Open(context, callback); } return(result); }
/// <summary>Extension point for subclasses to decide on behaviour after catching an /// exception in a <see cref="IRetryCallback{T}"/>. Normal stateless behaviour is not /// to rethrow, and if there is state we rethrow.</summary> /// <param name="retryPolicy">The retry policy.</param> /// <param name="context">The context.</param> /// <param name="state">The state.</param> /// <returns>The System.Boolean.</returns> protected bool ShouldRethrow(IRetryPolicy retryPolicy, IRetryContext context, IRetryState state) { if (state == null) { return(false); } else { return(state.RollbackFor(context.LastException)); } }
/// <summary>Delegate to the policies that were in operation when the context was created. <see cref="IRetryPolicy.Close"/></summary> /// <param name="context">The context.</param> /// <param name="exception">The exception.</param> public void RegisterException(IRetryContext context, Exception exception) { var contexts = ((CompositeRetryContext)context).contexts; var policies = ((CompositeRetryContext)context).policies; for (var i = 0; i < contexts.Length; i++) { policies[i].RegisterException(contexts[i], exception); } ((RetryContextSupport)context).RegisterException(exception); }
private IRetryContext GetContext(IRetryPolicy policy, IRetryContext parent) { IRetryContext context; this.contexts.TryGetValue(policy, out context); if (context == null) { context = policy.Open(parent); this.contexts.Add(policy, context); } return(context); }
public async Task PerformAsync(IRetryContext context, CancellationToken cancellationToken) { TestabilityTrace.TraceSource.WriteNoise("DelayStrategy", "{0}: Sleeping '{1}' seconds.", context.ActivityId, this.delayTime.TotalSeconds); await AsyncWaiter.WaitAsync(this.delayTime, cancellationToken); TimeSpan nextSleepTime = this.getNextDelayTime(this.delayTime); if (nextSleepTime != this.delayTime) { TestabilityTrace.TraceSource.WriteNoise("DelayStrategy", "{0}: Increasing current delay time from '{1}' to '{2}' seconds.", context.ActivityId, this.delayTime.TotalSeconds, nextSleepTime.TotalSeconds); this.delayTime = nextSleepTime; } }
/// <summary>Clean up the cache if necessary and close the context provided (if the flag indicates that processing was successful).</summary> /// <param name="retryPolicy">The retry policy.</param> /// <param name="context">The context.</param> /// <param name="state">The state.</param> /// <param name="succeeded">The succeeded.</param> protected void Close(IRetryPolicy retryPolicy, IRetryContext context, IRetryState state, bool succeeded) { if (state != null) { if (succeeded) { this.retryContextCache.Remove(state.GetKey()); retryPolicy.Close(context); } } else { retryPolicy.Close(context); } }
static async Task Attempt(IRetryContext retryContext, Func<Task> retryMethod, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) throw new TaskCanceledException(); TimeSpan delay; try { await retryMethod().ConfigureAwait(false); return; } catch (Exception ex) { if (!retryContext.CanRetry(ex, out delay)) throw; } await Task.Delay(delay, cancellationToken).ConfigureAwait(false); await Attempt(retryContext, retryMethod, cancellationToken).ConfigureAwait(false); }
/// <summary>Initializes a new instance of the <see cref="SimpleRetryContext"/> class.</summary> /// <param name="parent">The parent.</param> public SimpleRetryContext(IRetryContext parent) : base(parent) { }
/// <summary>Get a status object that can be used to track the current operation /// according to this policy. Has to be aware of the latest exception and the /// number of attempts.</summary> /// <param name="parent">The parent.</param> /// <returns>The Spring.Retry.Retry.IRetryContext.</returns> public IRetryContext Open(IRetryContext parent) { return new SimpleRetryContext(parent); }
/// <summary>Update the status with another attempted retry and the latest exception.</summary> /// <param name="context">The context.</param> /// <param name="exception">The throwable.</param> public void RegisterException(IRetryContext context, Exception exception) { var simpleContext = (SimpleRetryContext)context; simpleContext.RegisterException(exception); }
/// <summary>The register exception.</summary> /// <param name="context">The context.</param> /// <param name="exception">The exception.</param> public void RegisterException(IRetryContext context, Exception exception) { ((RetryContextSupport)context).RegisterException(exception); // otherwise no-op - we only time out, otherwise retry everything... }
/// <summary> /// Method for registering a context - should only be used by /// <see cref="IRetryOperations{T}"/> implementations to ensure that /// <see cref="GetContext"/> always returns the correct value. /// </summary> /// <param name="context">The new context to register.</param> /// <returns>The old context if there was one.</returns> public static IRetryContext Register(IRetryContext context) { var oldContext = GetContext(); RetrySynchronizationManager.context.Value = context; return oldContext; }
/// <summary>Returns false after the first exception. So there is always one try, and then the retry is prevented. <see cref="IRetryContext"/></summary> /// <param name="context">The context.</param> /// <returns>The System.Boolean.</returns> public virtual bool CanRetry(IRetryContext context) { return !((NeverRetryContext)context).IsFinished; }
/// <summary>Returns null. Subclasses can add behaviour, e.g. * initial sleep before first attempt.</summary> /// <param name="context">The context.</param> /// <returns>The Spring.Retry.Retry.Backoff.IBackOffContext.</returns> public virtual IBackOffContext Start(IRetryContext context) { return null; }
/// <summary>The put.</summary> /// <param name="key">The key.</param> /// <param name="context">The context.</param> /// <exception cref="NotImplementedException"></exception> public void Put(object key, IRetryContext context) { throw new NotImplementedException(); }
/// <summary>Initializes a new instance of the <see cref="NeverRetryContext"/> class.</summary> /// <param name="parent">The parent.</param> public NeverRetryContext(IRetryContext parent) : base(parent) { }
/// <summary>Creates a new context that copies the existing policies and keeps a list of the contexts from each one. <see cref="IRetryPolicy.Open"/></summary> /// <param name="parent">The parent.</param> /// <returns>The Spring.Retry.Retry.IRetryContext.</returns> public IRetryContext Open(IRetryContext parent) { var list = new List<IRetryContext>(); for (var i = 0; i < this.policies.Length; i++) { list.Add(this.policies[i].Open(parent)); } return new CompositeRetryContext(parent, list, this); }
/// <summary>Make the exception available for downstream use through the context. <see cref="IRetryPolicy.RegisterException"/></summary> /// <param name="context">The context.</param> /// <param name="exception">The exception.</param> public virtual void RegisterException(IRetryContext context, Exception exception) { ((NeverRetryContext)context).SetFinished(); ((RetryContextSupport)context).RegisterException(exception); }
/// <summary>Return a context that can respond to early termination requests, but does nothing else. <see cref="IRetryPolicy.Open"/></summary> /// <param name="parent">The parent.</param> /// <returns>The Spring.Retry.Retry.IRetryContext.</returns> public virtual IRetryContext Open(IRetryContext parent) { return new NeverRetryContext(parent); }
/// <summary>Do nothing. <see cref="IRetryContext"/></summary> /// <param name="context">The context.</param> public virtual void Close(IRetryContext context) { // no-op }
/// <summary>Test for retryable operation based on the status.</summary> /// <param name="context">The context.</param> /// <returns>True if the last exception was retryable and the number of attempts so far is less than the limit.</returns> public bool CanRetry(IRetryContext context) { var t = context.LastException; return (t == null || this.RetryForException(t)) && context.RetryCount < this.maxAttempts; }
public NoRetryPolicy() { _retryContext = new NoRetryContext(); }
/// <summary>The close.</summary> /// <param name="context">The context.</param> public void Close(IRetryContext context) { }
/// <summary>The open.</summary> /// <param name="parent">The parent.</param> /// <returns>The Spring.Retry.Retry.IRetryContext.</returns> public IRetryContext Open(IRetryContext parent) { return new TimeoutRetryContext(parent, this.timeout); }
public CancelRetryContext(IRetryContext retryContext, CancellationToken cancellationToken) { _retryContext = retryContext; _cancellationToken = cancellationToken; }
/// <summary>Initializes a new instance of the <see cref="TimeoutRetryContext"/> class.</summary> /// <param name="parent">The parent.</param> /// <param name="timeout">The timeout.</param> public TimeoutRetryContext(IRetryContext parent, long timeout) : base(parent) { this.start = DateTime.UtcNow; this.timeout = timeout; }
/// <summary>Always return true. <see cref="IRetryPolicy.CanRetry"/></summary> /// <param name="context">The context.</param> /// <returns>The System.Boolean.</returns> public override bool CanRetry(IRetryContext context) { return true; }
/// <summary>Initializes a new instance of the <see cref="RetryContextSupport"/> class.</summary> /// <param name="parent">The parent.</param> public RetryContextSupport(IRetryContext parent) { this.parent = parent; }
/// <summary>Returns a new instance of <see cref="IBackOffContext"/>, seeded with this policy's settings.</summary> /// <param name="context">The context.</param> /// <returns>The Spring.Retry.Retry.Backoff.IBackOffContext.</returns> public override IBackOffContext Start(IRetryContext context) { return new ExponentialRandomBackOffContext(this.InitialInterval, this.Multiplier, this.MaxInterval); }
/// <summary>Initializes a new instance of the <see cref="CompositeRetryContext"/> class.</summary> /// <param name="parent">The parent.</param> /// <param name="contexts">The contexts.</param> /// <param name="outer">The outer.</param> public CompositeRetryContext(IRetryContext parent, List<IRetryContext> contexts, CompositeRetryPolicy outer) : base(parent) { this.contexts = contexts.ToArray(); this.policies = this.outer.policies; this.outer = outer; }
/// <summary>Returns a new instance of <see cref="IBackOffContext"/> configured with the 'expSeed' and 'increment' values.</summary> /// <param name="context">The context.</param> /// <returns>The Spring.Retry.Retry.Backoff.IBackOffContext.</returns> public virtual IBackOffContext Start(IRetryContext context) { return new ExponentialBackOffContext(this.initialInterval, this.multiplier, this.maxInterval); }
/// <summary>The put.</summary> /// <param name="key">The key.</param> /// <param name="context">The context.</param> /// <exception cref="RetryCacheCapacityExceededException"></exception> public void Put(object key, IRetryContext context) { if (this.map.Count >= this.capacity) { throw new RetryCacheCapacityExceededException( "Retry cache capacity limit breached. " + "Do you need to re-consider the implementation of the key generator, " + "or the equals and hashCode of the items that failed?"); } if (this.map.ContainsKey(key)) { this.map[key] = context; } else { this.map.Add(key, context); } }
/// <summary>Only permits a retry if the timeout has not expired. Does not check the exception at all.</summary> /// <param name="context">The context.</param> /// <returns>The System.Boolean.</returns> public bool CanRetry(IRetryContext context) { return ((TimeoutRetryContext)context).IsAlive(); }