Search in sources :

Example 1 with ThreadInterruptingCancellable

use of io.servicetalk.concurrent.internal.ThreadInterruptingCancellable in project servicetalk by apple.

the class CallableSingle method doSubscribe.

@Override
void doSubscribe(final Subscriber<? super T> subscriber) {
    final ThreadInterruptingCancellable cancellable = new ThreadInterruptingCancellable(currentThread());
    try {
        subscriber.onSubscribe(cancellable);
    } catch (Throwable cause) {
        handleExceptionFromOnSubscribe(subscriber, cause);
        return;
    }
    final T value;
    try {
        value = callable.call();
    } catch (Throwable cause) {
        cancellable.setDone(cause);
        safeOnError(subscriber, cause);
        return;
    }
    // It is safe to set this outside the scope of the try/catch above because we don't do any blocking
    // operations which may be interrupted between the completion of the blockingHttpService call and here.
    cancellable.setDone();
    safeOnSuccess(subscriber, value);
}
Also used : ThreadInterruptingCancellable(io.servicetalk.concurrent.internal.ThreadInterruptingCancellable)

Example 2 with ThreadInterruptingCancellable

use of io.servicetalk.concurrent.internal.ThreadInterruptingCancellable in project servicetalk by apple.

the class RunnableCompletable method doSubscribe.

@Override
void doSubscribe(final Subscriber subscriber) {
    final ThreadInterruptingCancellable cancellable = new ThreadInterruptingCancellable(currentThread());
    try {
        subscriber.onSubscribe(cancellable);
    } catch (Throwable cause) {
        handleExceptionFromOnSubscribe(subscriber, cause);
        return;
    }
    try {
        runnable.run();
    } catch (Throwable cause) {
        cancellable.setDone(cause);
        safeOnError(subscriber, cause);
        return;
    }
    // It is safe to set this outside the scope of the try/catch above because we don't do any blocking
    // operations which may be interrupted between the completion of the blockingHttpService call and
    // here.
    cancellable.setDone();
    safeOnComplete(subscriber);
}
Also used : ThreadInterruptingCancellable(io.servicetalk.concurrent.internal.ThreadInterruptingCancellable)

Example 3 with ThreadInterruptingCancellable

use of io.servicetalk.concurrent.internal.ThreadInterruptingCancellable in project servicetalk by apple.

the class BlockingStreamingToStreamingService method handle.

@Override
public Single<StreamingHttpResponse> handle(final HttpServiceContext ctx, final StreamingHttpRequest request, final StreamingHttpResponseFactory responseFactory) {
    return new Single<StreamingHttpResponse>() {

        @Override
        protected void handleSubscribe(final Subscriber<? super StreamingHttpResponse> subscriber) {
            final ThreadInterruptingCancellable tiCancellable = new ThreadInterruptingCancellable(currentThread());
            try {
                subscriber.onSubscribe(tiCancellable);
            } catch (Throwable cause) {
                handleExceptionFromOnSubscribe(subscriber, cause);
                return;
            }
            // This exists to help users with error propagation. If the user closes the payloadWriter and they throw
            // (e.g. try-with-resources) this processor is merged with the payloadWriter Publisher so the error will
            // still be propagated.
            final Processor exceptionProcessor = newCompletableProcessor();
            final BufferHttpPayloadWriter payloadWriter = new BufferHttpPayloadWriter(ctx.headersFactory().newTrailers());
            DefaultBlockingStreamingHttpServerResponse response = null;
            try {
                final Consumer<DefaultHttpResponseMetaData> sendMeta = (metaData) -> {
                    final DefaultStreamingHttpResponse result;
                    try {
                        // transfer-encoding takes precedence over content-length.
                        // > When a message does not have a Transfer-Encoding header field, a
                        // Content-Length header field can provide the anticipated size.
                        // https://tools.ietf.org/html/rfc7230#section-3.3.2
                        final HttpHeaders headers = metaData.headers();
                        final HttpProtocolVersion version = metaData.version();
                        boolean addTrailers = version.major() > 1 || isTransferEncodingChunked(headers);
                        if (!addTrailers && h1TrailersSupported(version) && !hasContentLength(headers) && // breaks our HttpResponseDecoder
                        !HEAD.equals(request.method())) {
                            // this is likely not supported in http/1.0 and it is possible that a response has
                            // neither header and the connection close indicates the end of the response.
                            // https://tools.ietf.org/html/rfc7230#section-3.3.3
                            headers.add(TRANSFER_ENCODING, CHUNKED);
                            addTrailers = true;
                        }
                        Publisher<Object> messageBody = fromSource(exceptionProcessor).merge(payloadWriter.connect());
                        if (addTrailers) {
                            messageBody = messageBody.concat(succeeded(payloadWriter.trailers()));
                        }
                        messageBody = messageBody.beforeSubscription(() -> new Subscription() {

                            @Override
                            public void request(final long n) {
                            }

                            @Override
                            public void cancel() {
                                tiCancellable.cancel();
                            }
                        });
                        result = new DefaultStreamingHttpResponse(metaData.status(), version, headers, metaData.context0(), ctx.executionContext().bufferAllocator(), messageBody, forTransportReceive(false, version, headers), ctx.headersFactory());
                    } catch (Throwable t) {
                        subscriber.onError(t);
                        throw t;
                    }
                    subscriber.onSuccess(result);
                };
                response = new DefaultBlockingStreamingHttpServerResponse(OK, request.version(), ctx.headersFactory().newHeaders(), payloadWriter, ctx.executionContext().bufferAllocator(), sendMeta);
                original.handle(ctx, request.toBlockingStreamingRequest(), response);
                // The user code has returned successfully, complete the processor so the response stream can
                // complete. If the user handles the request asynchronously (e.g. on another thread) they are
                // responsible for closing the payloadWriter.
                exceptionProcessor.onComplete();
            } catch (Throwable cause) {
                tiCancellable.setDone(cause);
                if (response == null || response.markMetaSent()) {
                    safeOnError(subscriber, cause);
                } else {
                    try {
                        exceptionProcessor.onError(cause);
                    } finally {
                        safeClose(payloadWriter, cause);
                    }
                }
                return;
            }
            tiCancellable.setDone();
        }
    };
}
Also used : HttpProtocolVersion.h1TrailersSupported(io.servicetalk.http.api.HttpProtocolVersion.h1TrailersSupported) DefaultPayloadInfo.forTransportReceive(io.servicetalk.http.api.DefaultPayloadInfo.forTransportReceive) Publisher(io.servicetalk.concurrent.api.Publisher) Subscriber(io.servicetalk.concurrent.SingleSource.Subscriber) ConnectablePayloadWriter(io.servicetalk.concurrent.api.internal.ConnectablePayloadWriter) PayloadWriterUtils.safeClose(io.servicetalk.oio.api.internal.PayloadWriterUtils.safeClose) Thread.currentThread(java.lang.Thread.currentThread) ThreadInterruptingCancellable(io.servicetalk.concurrent.internal.ThreadInterruptingCancellable) SourceAdapters.fromSource(io.servicetalk.concurrent.api.SourceAdapters.fromSource) HeaderUtils.isTransferEncodingChunked(io.servicetalk.http.api.HeaderUtils.isTransferEncodingChunked) HttpExecutionStrategies.defaultStrategy(io.servicetalk.http.api.HttpExecutionStrategies.defaultStrategy) HEAD(io.servicetalk.http.api.HttpRequestMethod.HEAD) Objects.requireNonNull(java.util.Objects.requireNonNull) SubscriberUtils.safeOnError(io.servicetalk.concurrent.internal.SubscriberUtils.safeOnError) Processors.newCompletableProcessor(io.servicetalk.concurrent.api.Processors.newCompletableProcessor) CHUNKED(io.servicetalk.http.api.HttpHeaderValues.CHUNKED) SubscriberUtils.handleExceptionFromOnSubscribe(io.servicetalk.concurrent.internal.SubscriberUtils.handleExceptionFromOnSubscribe) Single(io.servicetalk.concurrent.api.Single) Completable(io.servicetalk.concurrent.api.Completable) OFFLOAD_RECEIVE_META_STRATEGY(io.servicetalk.http.api.DefaultHttpExecutionStrategy.OFFLOAD_RECEIVE_META_STRATEGY) TRANSFER_ENCODING(io.servicetalk.http.api.HttpHeaderNames.TRANSFER_ENCODING) IOException(java.io.IOException) Subscription(io.servicetalk.concurrent.PublisherSource.Subscription) OK(io.servicetalk.http.api.HttpResponseStatus.OK) Consumer(java.util.function.Consumer) BlockingUtils.blockingToCompletable(io.servicetalk.http.api.BlockingUtils.blockingToCompletable) HeaderUtils.hasContentLength(io.servicetalk.http.api.HeaderUtils.hasContentLength) Buffer(io.servicetalk.buffer.api.Buffer) Processor(io.servicetalk.concurrent.CompletableSource.Processor) Processors.newCompletableProcessor(io.servicetalk.concurrent.api.Processors.newCompletableProcessor) Processor(io.servicetalk.concurrent.CompletableSource.Processor) ThreadInterruptingCancellable(io.servicetalk.concurrent.internal.ThreadInterruptingCancellable) Publisher(io.servicetalk.concurrent.api.Publisher) Single(io.servicetalk.concurrent.api.Single) Subscriber(io.servicetalk.concurrent.SingleSource.Subscriber) Subscription(io.servicetalk.concurrent.PublisherSource.Subscription)

Aggregations

ThreadInterruptingCancellable (io.servicetalk.concurrent.internal.ThreadInterruptingCancellable)3 Buffer (io.servicetalk.buffer.api.Buffer)1 Processor (io.servicetalk.concurrent.CompletableSource.Processor)1 Subscription (io.servicetalk.concurrent.PublisherSource.Subscription)1 Subscriber (io.servicetalk.concurrent.SingleSource.Subscriber)1 Completable (io.servicetalk.concurrent.api.Completable)1 Processors.newCompletableProcessor (io.servicetalk.concurrent.api.Processors.newCompletableProcessor)1 Publisher (io.servicetalk.concurrent.api.Publisher)1 Single (io.servicetalk.concurrent.api.Single)1 SourceAdapters.fromSource (io.servicetalk.concurrent.api.SourceAdapters.fromSource)1 ConnectablePayloadWriter (io.servicetalk.concurrent.api.internal.ConnectablePayloadWriter)1 SubscriberUtils.handleExceptionFromOnSubscribe (io.servicetalk.concurrent.internal.SubscriberUtils.handleExceptionFromOnSubscribe)1 SubscriberUtils.safeOnError (io.servicetalk.concurrent.internal.SubscriberUtils.safeOnError)1 BlockingUtils.blockingToCompletable (io.servicetalk.http.api.BlockingUtils.blockingToCompletable)1 OFFLOAD_RECEIVE_META_STRATEGY (io.servicetalk.http.api.DefaultHttpExecutionStrategy.OFFLOAD_RECEIVE_META_STRATEGY)1 DefaultPayloadInfo.forTransportReceive (io.servicetalk.http.api.DefaultPayloadInfo.forTransportReceive)1 HeaderUtils.hasContentLength (io.servicetalk.http.api.HeaderUtils.hasContentLength)1 HeaderUtils.isTransferEncodingChunked (io.servicetalk.http.api.HeaderUtils.isTransferEncodingChunked)1 HttpExecutionStrategies.defaultStrategy (io.servicetalk.http.api.HttpExecutionStrategies.defaultStrategy)1 TRANSFER_ENCODING (io.servicetalk.http.api.HttpHeaderNames.TRANSFER_ENCODING)1