Search in sources :

Example 1 with HttpRequestObserver

use of io.servicetalk.http.api.HttpLifecycleObserver.HttpRequestObserver 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();
    });
}
Also used : AtomicIntegerFieldUpdater(java.util.concurrent.atomic.AtomicIntegerFieldUpdater) HttpLifecycleObserver(io.servicetalk.http.api.HttpLifecycleObserver) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) StreamingHttpResponses(io.servicetalk.http.api.StreamingHttpResponses) LoggerFactory(org.slf4j.LoggerFactory) TerminalSignalConsumer(io.servicetalk.concurrent.api.TerminalSignalConsumer) HttpHeaders(io.servicetalk.http.api.HttpHeaders) HttpResponseMetaData(io.servicetalk.http.api.HttpResponseMetaData) Function(java.util.function.Function) Supplier(java.util.function.Supplier) Key.newKey(io.servicetalk.context.api.ContextMap.Key.newKey) HttpResponseObserver(io.servicetalk.http.api.HttpLifecycleObserver.HttpResponseObserver) ConnectionInfo(io.servicetalk.transport.api.ConnectionInfo) AsyncContext(io.servicetalk.concurrent.api.AsyncContext) HttpExecutionStrategies(io.servicetalk.http.api.HttpExecutionStrategies) Objects.requireNonNull(java.util.Objects.requireNonNull) HttpExecutionStrategy(io.servicetalk.http.api.HttpExecutionStrategy) HttpRequestObserver(io.servicetalk.http.api.HttpLifecycleObserver.HttpRequestObserver) StreamingHttpRequest(io.servicetalk.http.api.StreamingHttpRequest) Nullable(javax.annotation.Nullable) Logger(org.slf4j.Logger) NoopHttpExchangeObserver(io.servicetalk.http.netty.NoopHttpLifecycleObserver.NoopHttpExchangeObserver) Single.defer(io.servicetalk.concurrent.api.Single.defer) PublisherSource(io.servicetalk.concurrent.PublisherSource) Single(io.servicetalk.concurrent.api.Single) HttpExecutionStrategyInfluencer(io.servicetalk.http.api.HttpExecutionStrategyInfluencer) HttpExchangeObserver(io.servicetalk.http.api.HttpLifecycleObserver.HttpExchangeObserver) Consumer(java.util.function.Consumer) Buffer(io.servicetalk.buffer.api.Buffer) ContextMap(io.servicetalk.context.api.ContextMap) NoopHttpRequestObserver(io.servicetalk.http.netty.NoopHttpLifecycleObserver.NoopHttpRequestObserver) BeforeFinallyHttpOperator(io.servicetalk.http.utils.BeforeFinallyHttpOperator) Buffer(io.servicetalk.buffer.api.Buffer) TerminalSignalConsumer(io.servicetalk.concurrent.api.TerminalSignalConsumer) HttpHeaders(io.servicetalk.http.api.HttpHeaders) HttpRequestObserver(io.servicetalk.http.api.HttpLifecycleObserver.HttpRequestObserver) NoopHttpRequestObserver(io.servicetalk.http.netty.NoopHttpLifecycleObserver.NoopHttpRequestObserver) BeforeFinallyHttpOperator(io.servicetalk.http.utils.BeforeFinallyHttpOperator) NoopHttpExchangeObserver(io.servicetalk.http.netty.NoopHttpLifecycleObserver.NoopHttpExchangeObserver) HttpExchangeObserver(io.servicetalk.http.api.HttpLifecycleObserver.HttpExchangeObserver) StreamingHttpRequest(io.servicetalk.http.api.StreamingHttpRequest) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse)

Aggregations

Buffer (io.servicetalk.buffer.api.Buffer)1 PublisherSource (io.servicetalk.concurrent.PublisherSource)1 AsyncContext (io.servicetalk.concurrent.api.AsyncContext)1 Single (io.servicetalk.concurrent.api.Single)1 Single.defer (io.servicetalk.concurrent.api.Single.defer)1 TerminalSignalConsumer (io.servicetalk.concurrent.api.TerminalSignalConsumer)1 ContextMap (io.servicetalk.context.api.ContextMap)1 Key.newKey (io.servicetalk.context.api.ContextMap.Key.newKey)1 HttpExecutionStrategies (io.servicetalk.http.api.HttpExecutionStrategies)1 HttpExecutionStrategy (io.servicetalk.http.api.HttpExecutionStrategy)1 HttpExecutionStrategyInfluencer (io.servicetalk.http.api.HttpExecutionStrategyInfluencer)1 HttpHeaders (io.servicetalk.http.api.HttpHeaders)1 HttpLifecycleObserver (io.servicetalk.http.api.HttpLifecycleObserver)1 HttpExchangeObserver (io.servicetalk.http.api.HttpLifecycleObserver.HttpExchangeObserver)1 HttpRequestObserver (io.servicetalk.http.api.HttpLifecycleObserver.HttpRequestObserver)1 HttpResponseObserver (io.servicetalk.http.api.HttpLifecycleObserver.HttpResponseObserver)1 HttpResponseMetaData (io.servicetalk.http.api.HttpResponseMetaData)1 StreamingHttpRequest (io.servicetalk.http.api.StreamingHttpRequest)1 StreamingHttpResponse (io.servicetalk.http.api.StreamingHttpResponse)1 StreamingHttpResponses (io.servicetalk.http.api.StreamingHttpResponses)1