/// <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); } }
/// <summary>The register exception.</summary> /// <param name="retryPolicy">The retry policy.</param> /// <param name="state">The state.</param> /// <param name="context">The context.</param> /// <param name="e">The e.</param> /// <exception cref="RetryException"></exception> protected void RegisterThrowable(IRetryPolicy retryPolicy, IRetryState state, IRetryContext context, Exception e) { if (state != null) { var key = state.GetKey(); if (context.RetryCount > 0 && !this.retryContextCache.ContainsKey(key)) { throw new RetryException( "Inconsistent state for failed item key: cache key has changed. " + "Consider whether equals() or hashCode() for the key might be inconsistent, " + "or if you need to supply a better key"); } this.retryContextCache.Put(key, context); } retryPolicy.RegisterException(context, e); }
/// <summary>Actions to take after final attempt has failed. If there is state clean /// up the cache. If there is a recovery callback, execute that and return /// its result. Otherwise throw an exception.</summary> /// <param name="recoveryCallback">The callback for recovery (might be null).</param> /// <param name="context">The current retry context.</param> /// <param name="state">The state.</param> /// <returns>The T.</returns> /// <typeparam name="T">Type T.</typeparam> protected T HandleRetryExhausted <T>(Func <IRetryContext, T> recoveryCallback, IRetryContext context, IRetryState state) { if (state != null) { this.retryContextCache.Remove(state.GetKey()); } if (recoveryCallback != null) { return(recoveryCallback.Invoke(context)); } if (state != null) { Logger.Debug(m => m("Retry exhausted after last attempt with no recovery path.")); throw new ExhaustedRetryException("Retry exhausted after last attempt with no recovery path", context.LastException); } throw WrapIfNecessary(context.LastException); }
/// <summary>Delegate to the <see cref="IRetryPolicy"/> having checked in the cache for an existing value if the state is not null.</summary> /// <param name="retryPolicy">The retry policy.</param> /// <param name="state">The state.</param> /// <returns>The Spring.Retry.Retry.IRetryContext, either a new one or the one used last time the same state was encountered.</returns> protected IRetryContext Open(IRetryPolicy retryPolicy, IRetryState state) { if (state == null) { return(this.DoOpenInternal(retryPolicy)); } var key = state.GetKey(); if (state.IsForceRefresh()) { return(this.DoOpenInternal(retryPolicy)); } // If there is no cache hit we can avoid the possible expense of the // cache re-hydration. if (!this.retryContextCache.ContainsKey(key)) { // The cache is only used if there is a failure. return(this.DoOpenInternal(retryPolicy)); } var context = this.retryContextCache.Get(key); if (context == null) { if (this.retryContextCache.ContainsKey(key)) { throw new RetryException( "Inconsistent state for failed item: no history found. " + "Consider whether equals() or hashCode() for the item might be inconsistent, " + "or if you need to supply a better ItemKeyGenerator"); } // The cache could have been expired in between calls to // containsKey(), so we have to live with this: return(this.DoOpenInternal(retryPolicy)); } return(context); }