/** * Returns whether an execution result can be retried given the configured failure conditions. * * @see #handle(Class...) * @see #handle(List) * @see #handleIf(BiPredicate) * @see #handleIf(Predicate) * @see #handleResult(R) * @see #handleResultIf(Predicate) */ boolean isFailure(ExecutionResult result) { return failureConditions.isEmpty() ? result.getFailure() != null : isFailure((R) result.getResult(), result.getFailure()); }
/** * Calls the {@code supplier} synchronously, handling results according to the configured policies. * * @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 breaker is open */ @SuppressWarnings("unchecked") private <T> T call(Function<Execution, CheckedSupplier<?>> supplierFn) { Execution execution = new Execution(this); Supplier<ExecutionResult> supplier = Functions.resultSupplierOf(supplierFn.apply(execution), execution); ExecutionResult result = execution.executeSync(supplier); if (result.getFailure() != null) throw result.getFailure() instanceof RuntimeException ? (RuntimeException) result.getFailure() : new FailsafeException(result.getFailure()); return (T) result.getResult(); }
/** * 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 attempt. * * @throws IllegalStateException if the execution is already complete */ void record(ExecutionResult result) { Assert.state(!completed, "Execution has already been completed"); attempts++; lastResult = result.getResult(); lastFailure = result.getFailure(); }
default void handle(ExecutionResult result, ExecutionContext context) { handle(result.getResult(), result.getFailure(), context); } }
@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); } }
private void complete(ExecutionResult result, Throwable error) { if (result == null && error == null) return; completed = true; if (!future.isDone() && !future.isCancelled()) { if (result != null) { future.complete(result.getResult(), result.getFailure()); executor.handleComplete(result, this); } else future.complete(null, error); } } }
if (delayFunction != null && policy.canApplyDelayFn(result.getResult(), result.getFailure())) { Duration computedDelay = delayFunction.computeDelay(result.getResult(), result.getFailure(), execution); if (computedDelay != null && computedDelay.toNanos() >= 0) computedDelayNanos = computedDelay.toNanos(); boolean maxDurationExceeded = policy.getMaxDuration() != null && elapsedNanos > policy.getMaxDuration().toNanos(); retriesExceeded = maxRetriesExceeded || maxDurationExceeded; boolean isAbortable = policy.isAbortable(result.getResult(), result.getFailure()); boolean shouldRetry = !result.isSuccess() && !isAbortable && !retriesExceeded && policy.allowsRetries(); boolean completed = isAbortable || !shouldRetry;