use of fish.payara.microprofile.faulttolerance.FaultToleranceMethodContext in project Payara by payara.
the class BulkheadLifecycleTckTest method createService.
@Override
protected FaultToleranceServiceStub createService() {
// this test needs to use more advanced state per method as multiple methods are involved
// therefore the below special setup where we have state per method as in the actual implementation
final Map<Object, AtomicReference<BlockingQueue<Thread>>> concurrentExecutionByMethodId = new ConcurrentHashMap<>();
final Map<Object, AtomicInteger> waitingQueuePopulationByMethodId = new ConcurrentHashMap<>();
registry = new MetricRegistryImpl(Type.BASE);
return new FaultToleranceServiceStub() {
@Override
protected FaultToleranceMethodContext stubMethodContext(StubContext ctx) {
FaultToleranceMetrics metrics = new MethodFaultToleranceMetrics(registry, FaultToleranceUtils.getCanonicalMethodName(ctx.context));
return new FaultToleranceMethodContextStub(ctx, state, concurrentExecutionByMethodId.computeIfAbsent(ctx.key, key -> new AtomicReference<>()), waitingQueuePopulationByMethodId.computeIfAbsent(ctx.key, key -> new AtomicInteger())) {
@Override
public FaultToleranceMetrics getMetrics() {
return metrics;
}
@Override
public Future<?> runDelayed(long delayMillis, Runnable task) throws Exception {
return CompletableFuture.completedFuture(null);
}
};
}
};
}
use of fish.payara.microprofile.faulttolerance.FaultToleranceMethodContext 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