/** * Delegate to the {@link RetryPolicy} having checked in the cache for an existing value if the * state is not null. * * @param state a {@link RetryState} * @param retryPolicy a {@link RetryPolicy} to delegate the context creation * @return a retry context, either a new one or the one used last time the same state was * encountered */ protected RetryContext open(RetryPolicy retryPolicy, RetryState state) { if (state == null) { return doOpenInternal(retryPolicy); } Object key = state.getKey(); if (state.isForceRefresh()) { return doOpenInternal(retryPolicy, state); } // 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 doOpenInternal(retryPolicy, state); } RetryContext 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 doOpenInternal(retryPolicy, state); } // Start with a clean slate for state that others may be inspecting context.removeAttribute(RetryContext.CLOSED); context.removeAttribute(RetryContext.EXHAUSTED); context.removeAttribute(RetryContext.RECOVERED); return context; }