Search in sources :

Example 1 with BeforeFinallyHttpOperator

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();
    });
}
Also used : TerminalSignalConsumer(io.servicetalk.concurrent.api.TerminalSignalConsumer) BeforeFinallyHttpOperator(io.servicetalk.http.utils.BeforeFinallyHttpOperator) ConnectionInfo(io.servicetalk.transport.api.ConnectionInfo)

Example 2 with BeforeFinallyHttpOperator

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}&lt;{@link StreamingHttpResponses}&gt;.
 * @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

TerminalSignalConsumer (io.servicetalk.concurrent.api.TerminalSignalConsumer)2 BeforeFinallyHttpOperator (io.servicetalk.http.utils.BeforeFinallyHttpOperator)2 ConnectionInfo (io.servicetalk.transport.api.ConnectionInfo)2 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 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