use of fish.payara.microprofile.faulttolerance.FaultToleranceMethodContext.AsyncFuture in project Payara by payara.
the class FaultTolerancePolicy method processRetryAsync.
private AsyncFuture processRetryAsync(FaultToleranceInvocation invocation) throws Exception {
AsyncFuture asyncAttempt = new AsyncFuture();
invocation.context.runAsynchronous(asyncAttempt, () -> invocation.runStageWithWorker(() -> processCircuitBreakerStage(invocation, asyncAttempt)));
try {
// wait and only proceed on success
asyncAttempt.get();
invocation.timeoutIfConcludedConcurrently();
return asyncAttempt;
} catch (ExecutionException ex) {
// this ExecutionException is from calling get() above in case completed exceptionally
if (!asyncAttempt.isExceptionThrown() && asynchronous.isSuccessWhenCompletedExceptionally()) {
invocation.timeoutIfConcludedConcurrently();
return asyncAttempt;
}
rethrow(ex.getCause());
// not reachable
return null;
}
}
use of fish.payara.microprofile.faulttolerance.FaultToleranceMethodContext.AsyncFuture in project Payara by payara.
the class FaultTolerancePolicy method processAsynchronousStage.
/**
* Stage that takes care of the {@link AsynchronousPolicy} handling.
*/
private Object processAsynchronousStage(FaultToleranceMethodContext context, FaultToleranceMetrics metrics) throws Exception {
if (!isAsynchronous()) {
return processFallbackStage(new FaultToleranceInvocation(context, metrics, null, null));
}
logger.log(Level.FINER, "Proceeding invocation with asynchronous semantics");
Set<Thread> workers = ConcurrentHashMap.newKeySet();
AsyncFuture asyncResult = new AsyncFuture() {
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
boolean res = super.cancel(mayInterruptIfRunning);
if (mayInterruptIfRunning) {
logger.log(Level.FINE, "Asynchronous computation was cancelled by caller.");
if (mayInterruptIfRunning) {
workers.forEach(worker -> worker.interrupt());
}
}
return res;
}
};
FaultToleranceInvocation invocation = new FaultToleranceInvocation(context, metrics, asyncResult, workers);
context.runAsynchronous(asyncResult, () -> invocation.runStageWithWorker(() -> processFallbackStage(invocation)));
return asyncResult;
}
use of fish.payara.microprofile.faulttolerance.FaultToleranceMethodContext.AsyncFuture in project Payara by payara.
the class FaultTolerancePolicy method proceed.
/**
* Wraps {@link InvocationContext#proceed()} with fault tolerance behaviour.
*
* Processing has 6 stages:
* <pre>
* 1) Asynchronous
* 2) Fallback
* 3) Retry
* 4) Circuit Breaker
* 5) Timeout
* 6) Bulkhead
* </pre>
* The call chain goes from 1) down to 6) skipping stages that are not requested by this policy.
*
* Asynchronous execution branches to new threads in stage 1) and 3) each executed by the
* {@link FaultToleranceService#runAsynchronous(CompletableFuture, Callable)}.
*
* @param context intercepted call context
* @param ftmContextSupplier the environment used to execute the FT behaviour
* @return the result of {@link InvocationContext#proceed()} after applying FT behaviour
* @throws Exception as thrown by the wrapped invocation or a {@link FaultToleranceException}
*/
public Object proceed(InvocationContext context, Supplier<FaultToleranceMethodContext> ftmContextSupplier) throws Exception {
if (!isPresent) {
logger.log(Level.FINER, "Fault Tolerance not enabled, proceeding normally.");
return context.proceed();
}
FaultToleranceMethodContext ftmContext = ftmContextSupplier.get();
FaultToleranceMetrics metrics = ftmContext.getMetrics().boundTo(ftmContext, this);
try {
Object res = processAsynchronousStage(ftmContext, metrics);
if (res instanceof AsyncFuture) {
AsyncFuture async = (AsyncFuture) res;
async.whenComplete((value, ex) -> {
// first evaluate async when the results are in...
if (isExceptionThrown(async)) {
metrics.incrementInvocationsExceptionThrown();
} else {
metrics.incrementInvocationsValueReturned();
}
});
} else {
metrics.incrementInvocationsValueReturned();
}
return res;
} catch (Exception | Error ex) {
metrics.incrementInvocationsExceptionThrown();
throw ex;
}
}
Aggregations