/** * Performs an asynchronous execution. * * @param asyncExecution whether this is a detached, async execution that must be manually completed */ @SuppressWarnings("unchecked") void executeAsync(boolean asyncExecution) { if (!asyncExecution) Functions.makeAsync(outerExecutionSupplier, scheduler, future).get().whenComplete(this::complete); else future.inject((Future) scheduler.schedule(innerExecutionSupplier::get, 0, TimeUnit.NANOSECONDS)); }
/** * Returns a Supplier that supplies a promise that is completed with the result of calling the {@code supplier} on the * {@code scheduler}. */ @SuppressWarnings("unchecked") static Supplier<CompletableFuture<ExecutionResult>> makeAsync(Supplier<CompletableFuture<ExecutionResult>> supplier, Scheduler scheduler, FailsafeFuture<Object> future) { return () -> { CompletableFuture<ExecutionResult> promise = new CompletableFuture<>(); Callable<Object> callable = () -> supplier.get().handle((result, error) -> { // Propagate result if (result != null) promise.complete(result); else promise.completeExceptionally(error); return result; }); try { future.inject((Future) scheduler.schedule(callable, 0, TimeUnit.NANOSECONDS)); } catch (Exception e) { promise.completeExceptionally(e); } return promise; }; }
@SuppressWarnings("unchecked") protected CompletableFuture<ExecutionResult> onFailureAsync(ExecutionResult result, Scheduler scheduler, FailsafeFuture<Object> future) { if (!policy.isAsync()) return CompletableFuture.completedFuture(onFailure(result)); CompletableFuture<ExecutionResult> promise = new CompletableFuture<>(); Callable<Object> callable = () -> promise.complete(onFailure(result)); try { future.inject((Future) scheduler.schedule(callable, result.getWaitNanos(), TimeUnit.NANOSECONDS)); } catch (Exception e) { promise.completeExceptionally(e); } return promise; } }
/** * Calls the asynchronous {@code supplier} via the configured Scheduler, handling results according to the configured * policies. * <p> * If a configured circuit breaker is open, the resulting future is completed with {@link * CircuitBreakerOpenException}. * * @param asyncExecution whether this is a detached, async execution that must be manually completed * @throws NullPointerException if the {@code supplierFn} is null * @throws RejectedExecutionException if the {@code supplierFn} cannot be scheduled for execution */ @SuppressWarnings("unchecked") private <T> CompletableFuture<T> callAsync( Function<AsyncExecution, Supplier<CompletableFuture<ExecutionResult>>> supplierFn, boolean asyncExecution) { FailsafeFuture<T> future = new FailsafeFuture(this); AsyncExecution execution = new AsyncExecution(scheduler, future, this); future.inject(execution); execution.inject(supplierFn.apply(execution), asyncExecution); execution.executeAsync(asyncExecution); return future; } }