use of com.palantir.conjure.java.undertow.lib.ReturnValueWriter in project conjure-java by palantir.
the class ConjureAsyncRequestProcessing method registerCallback.
private <T> void registerCallback(ListenableFuture<T> future, ReturnValueWriter<T> returnValueWriter, Duration requestAsyncTimeout, HttpServerExchange exchange) {
// Attach data to the exchange in order to reuse a stateless listener
exchange.putAttachment(FUTURE, future);
// If the exchange is complete we still follow this path to provide standard logging.
if (exchange.isComplete()) {
// If the exchange has already completed (http/2 rst_stream while processing).
// Calling addExchangeCompleteListener will result in an IllegalStateException in this case.
future.cancel(INTERRUPT_ON_CANCEL);
} else {
// Cancel the future if the exchange is completed before the future is done
exchange.addExchangeCompleteListener(COMPLETION_LISTENER);
}
XnioExecutor.Key timeoutKey = exchange.getIoThread().executeAfter(() -> {
// TIMED_OUT must be set prior to future.cancel, otherwise the FutureCallback
// may be invoked before TIMED_OUT is set/visible.
exchange.putAttachment(TIMED_OUT, Boolean.TRUE);
future.cancel(INTERRUPT_ON_CANCEL);
}, requestAsyncTimeout.toMillis(), TimeUnit.MILLISECONDS);
future.addListener(timeoutKey::remove, DIRECT_EXECUTOR);
// Dispatch the registration task, this accomplishes two things:
// 1. Puts the exchange into a 'dispatched' state, otherwise the request will be terminated when
// the endpoint HttpHandler returns. See Connectors.executeRootHandler for more information.
// 2. Avoids racing completion with the current handler chain. The dispatched task will be executed
// after this Endpoints HttpHandler returns. Otherwise an unlucky future could race
// HttpServerExchange.isInCall transitioning from true -> false, causing hte dispatch task not
// to execute.
DeferredTracer tracer = new DeferredTracer("Undertow: Async Result");
exchange.dispatch(() -> Futures.addCallback(future, new FutureCallback<T>() {
@Override
public void onSuccess(@Nullable T result) {
exchange.dispatch(wrapCallback(_serverExchange -> returnValueWriter.write(result, exchange), tracer));
}
@Override
public void onFailure(Throwable throwable) {
exchange.dispatch(wrapCallback(serverExchange -> exceptionHandler.handle(serverExchange, getThrowable(serverExchange, throwable, requestAsyncTimeout)), tracer));
}
}, DIRECT_EXECUTOR));
}
Aggregations