@Override public boolean isDone() { return delegate.isDone(); }
@Override public boolean cancel(boolean mayInterruptIfRunning) { return delegate.cancel(mayInterruptIfRunning); }
@Override public boolean isCancelled() { return delegate.isCancelled(); }
if (retry != null) { this.retryPolicy = new RetryPolicy() .withMaxRetries(retry.maxRetries()) .withMaxDuration(retry.maxDuration(), TimeUtil.chronoUnitToTimeUnit(retry.durationUnit())) .retryOn(retry.retryOn()); this.retryPolicy.abortOn(retry.abortOn()); factor = ((double) jitter) / delay; this.retryPolicy.withDelay(delay, TimeUnit.NANOSECONDS); this.retryPolicy.withJitter(factor); } else if (retry.delay() > 0) { this.retryPolicy.withDelay(retry.delay(), TimeUtil.chronoUnitToTimeUnit(retry.delayUnit())); this.retryPolicy = new RetryPolicy().withMaxRetries(0); // no retries
if (isAsynchronous) { Scheduler scheduler = CommandScheduler.create(); AsyncFailsafe<Object> failsafe = Failsafe.with(retryPolicy).with(scheduler); FailsafeFuture<?> chainedFuture = (introspector.hasFallback() ? failsafe.withFallback(fallbackFunction).get(this::retryExecute) : failsafe.get(this::retryExecute)); return new FailsafeChainedFuture<>(chainedFuture); } else { SyncFailsafe<Object> failsafe = Failsafe.with(retryPolicy); return introspector.hasFallback() ? failsafe.withFallback(fallbackFunction).get(this::retryExecute) : failsafe.get(this::retryExecute); throw toException(e.getCause());
@Override public RetryPolicy getRetryPolicy() { RetryPolicy retryPolicy = new RetryPolicy().withMaxRetries(configuration.getRetries()); if (configuration.isExponentialBackoffEnabled()) { retryPolicy = retryPolicy.withBackoff(configuration.getExponentialBackoffDelay(), configuration.getExponentialBackoffMaxDelay(), TimeUnit.SECONDS); } return retryPolicy; } }
@Override @SuppressWarnings("unchecked") protected ExecutionResult onFailure(ExecutionResult result) { try { return result.withResult(policy.apply(result.getResult(), result.getFailure(), execution.copy())); } catch (Exception e) { return ExecutionResult.failure(e); } }
@Override protected ExecutionResult preExecute() { if (policy.allowsExecution()) { policy.preExecute(); return null; } return ExecutionResult.failure(new CircuitBreakerOpenException()); }
/** * Returns whether the {@code result} is a success according to the policy. If the {code result} has no result, it is * not a failure. */ protected boolean isFailure(ExecutionResult result) { if (result.isNonResult()) return false; else if (policy instanceof FailurePolicy) return ((FailurePolicy) policy).isFailure(result); else return result.getFailure() != null; }
/** * Records an execution and returns true if a retry can be performed for the {@code result}, else returns false and * marks the execution as complete. * * @throws IllegalStateException if the execution is already complete */ public boolean canRetryFor(Object result) { return !postExecute(new ExecutionResult(result, null)); }
/** * Executes the {@code supplier} until a successful result is returned or the configured policies are exceeded. * * @throws NullPointerException if the {@code supplier} is null * @throws FailsafeException if the {@code supplier} fails with a checked Exception or if interrupted while * waiting to perform a retry. * @throws CircuitBreakerOpenException if a configured circuit is open. */ public <T extends R> T get(ContextualSupplier<T> supplier) { return call(execution -> Functions.supplierOf(supplier, execution)); }
@Override protected ExecutionResult onFailure(ExecutionResult result) { policy.recordFailure(); return result.withComplete(); } }
void inject(Supplier<CompletableFuture<ExecutionResult>> supplier, boolean asyncExecution) { if (!asyncExecution) { outerExecutionSupplier = supplier; } else { outerExecutionSupplier = innerExecutionSupplier = Functions.settableSupplierOf(supplier); } for (PolicyExecutor<Policy<Object>> policyExecutor : policyExecutors) outerExecutionSupplier = policyExecutor.supplyAsync(outerExecutionSupplier, scheduler, this.future); }
@Override @SuppressWarnings("unchecked") public T get() throws InterruptedException, ExecutionException { final T result = delegate.get(); if (result instanceof Future) { return ((Future<T>) result).get(); } return result; }
/** * Records an execution and returns true if a retry can be performed for the {@code result} or {@code failure}, else * returns false and marks the execution as complete. * * @throws IllegalStateException if the execution is already complete */ public boolean canRetryFor(Object result, Throwable failure) { return !postExecute(new ExecutionResult(result, failure)); }
/** * Executes the {@code runnable} until successful or until the configured policies are exceeded. * * @throws NullPointerException if the {@code runnable} is null * @throws FailsafeException if the {@code runnable} fails with a checked Exception or if interrupted while * waiting to perform a retry. * @throws CircuitBreakerOpenException if a configured circuit is open. */ public void run(ContextualRunnable runnable) { call(execution -> Functions.supplierOf(runnable, execution)); }
@Override @SuppressWarnings("unchecked") public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { final T result = delegate.get(); if (result instanceof Future) { return ((Future<T>) result).get(timeout, unit); } return result; } }