use of io.servicetalk.http.utils.BeforeFinallyHttpOperator in project servicetalk by apple.
the class LoadBalancedStreamingHttpClient method request.
@Override
public Single<StreamingHttpResponse> request(final StreamingHttpRequest request) {
// correct.
return loadBalancer.selectConnection(SELECTOR_FOR_REQUEST).flatMap(c -> {
final Consumer<ConnectionInfo> onConnectionSelected = AsyncContext.get(ON_CONNECTION_SELECTED_CONSUMER);
if (onConnectionSelected != null) {
onConnectionSelected.accept(c.connectionContext());
}
final OwnedRunnable ownedRunnable = c.connectionContext().protocol().major() <= 1 ? null : new OwnedRunnable(c::requestFinished);
return c.request(ownedRunnable == null ? request : new StreamingHttpRequestWithContext(request, ownedRunnable)).liftSync(new BeforeFinallyHttpOperator(new TerminalSignalConsumer() {
@Override
public void onComplete() {
if (ownedRunnable == null || ownedRunnable.own()) {
c.requestFinished();
}
}
@Override
public void onError(final Throwable throwable) {
if (ownedRunnable == null || ownedRunnable.own()) {
c.requestFinished();
}
}
@Override
public void cancel() {
// the transport, we mark request as finished immediately.
if (ownedRunnable == null) {
c.closeAsync().subscribe();
} else if (ownedRunnable.own()) {
c.requestFinished();
}
}
})).shareContextOnSubscribe();
});
}
use of io.servicetalk.http.utils.BeforeFinallyHttpOperator in project servicetalk by apple.
the class AbstractLifecycleObserverHttpFilter method trackLifecycle.
/**
* Returns a {@link Single} tracking the request/response, capturing lifecycle events as they are observed.
*
* @param connInfo {@link ConnectionInfo} connection information.
* @param request the {@link StreamingHttpRequest}.
* @param responseFunction produces {@link Single}<{@link StreamingHttpResponses}>.
* @return a {@link Single} tracking the request/response, capturing lifecycle events as they are observed.
*/
final Single<StreamingHttpResponse> trackLifecycle(@Nullable final ConnectionInfo connInfo, final StreamingHttpRequest request, final Function<StreamingHttpRequest, Single<StreamingHttpResponse>> responseFunction) {
return defer(() -> {
final HttpExchangeObserver onExchange = safeReport(observer::onNewExchange, observer, "onNewExchange", NoopHttpExchangeObserver.INSTANCE);
final boolean clearAsyncContext;
if (connInfo != null) {
safeReport(onExchange::onConnectionSelected, connInfo, onExchange, "onConnectionSelected");
clearAsyncContext = false;
} else {
// Pass it down to LoadBalancedStreamingHttpClient
// FIXME: switch to RequestContext when it's available
AsyncContext.put(ON_CONNECTION_SELECTED_CONSUMER, selectedConnection -> safeReport(onExchange::onConnectionSelected, selectedConnection, onExchange, "onConnectionSelected"));
clearAsyncContext = true;
}
final ExchangeContext exchangeContext = new ExchangeContext(onExchange, client, clearAsyncContext);
final HttpRequestObserver onRequest = safeReport(onExchange::onRequest, request, onExchange, "onRequest", NoopHttpRequestObserver.INSTANCE);
final StreamingHttpRequest transformed = request.transformMessageBody(p -> {
if (client) {
p = p.beforeSubscriber(() -> {
exchangeContext.requestMessageBodyStarts();
return NoopSubscriber.INSTANCE;
});
}
return p.beforeOnNext(item -> {
if (item instanceof Buffer) {
safeReport(onRequest::onRequestData, (Buffer) item, onRequest, "onRequestData");
} else if (item instanceof HttpHeaders) {
safeReport(onRequest::onRequestTrailers, (HttpHeaders) item, onRequest, "onRequestTrailers");
} else {
LOGGER.warn("Programming mistake: unexpected message body item is received on the request: {}", item.getClass().getName());
}
}).beforeFinally(new TerminalSignalConsumer() {
@Override
public void onComplete() {
safeReport(onRequest::onRequestComplete, onRequest, "onRequestComplete");
exchangeContext.decrementRemaining();
}
@Override
public void onError(final Throwable cause) {
safeReport(onRequest::onRequestError, cause, onRequest, "onRequestError");
exchangeContext.decrementRemaining();
}
@Override
public void cancel() {
safeReport(onRequest::onRequestCancel, onRequest, "onRequestCancel");
exchangeContext.decrementRemaining();
}
});
});
final Single<StreamingHttpResponse> responseSingle;
try {
responseSingle = responseFunction.apply(transformed);
} catch (Throwable t) {
onExchange.onResponseError(t);
return Single.<StreamingHttpResponse>failed(t).shareContextOnSubscribe();
}
return responseSingle.liftSync(new BeforeFinallyHttpOperator(exchangeContext, /* discardEventsAfterCancel */
true)).map(resp -> {
exchangeContext.onResponse(resp);
return resp.transformMessageBody(p -> p.beforeOnNext(exchangeContext::onResponseBody));
}).shareContextOnSubscribe();
});
}
Aggregations