Search in sources :

Example 16 with Single

use of io.servicetalk.concurrent.api.Single in project servicetalk by apple.

the class RedirectingHttpRequesterFilterTest method newClient.

private StreamingHttpClient newClient(RedirectConfig config, StreamingHttpClientFilterFactory... other) {
    StreamingHttpClientFilterFactory result = new RedirectingHttpRequesterFilter(config);
    for (StreamingHttpClientFilterFactory next : other) {
        result = appendClientFilterFactory(result, next);
    }
    StreamingHttpClientFilterFactory mockResponse = client -> new StreamingHttpClientFilter(client) {

        @Override
        protected Single<StreamingHttpResponse> request(final StreamingHttpRequester delegate, final StreamingHttpRequest request) {
            return httpClient.request(request);
        }
    };
    return from(reqRespFactory, mock(HttpExecutionContext.class), appendClientFilterFactory(result, mockResponse));
}
Also used : StreamingHttpClientFilterFactory(io.servicetalk.http.api.StreamingHttpClientFilterFactory) MULTIPLE_CHOICES(io.servicetalk.http.api.HttpResponseStatus.MULTIPLE_CHOICES) HttpRequestMethod(io.servicetalk.http.api.HttpRequestMethod) LOCATION(io.servicetalk.http.api.HttpHeaderNames.LOCATION) Matchers.not(org.hamcrest.Matchers.not) CONTENT_TYPE(io.servicetalk.http.api.HttpHeaderNames.CONTENT_TYPE) BAD_REQUEST(io.servicetalk.http.api.HttpResponseStatus.BAD_REQUEST) TEMPORARY_REDIRECT(io.servicetalk.http.api.HttpResponseStatus.TEMPORARY_REDIRECT) StreamingHttpClient(io.servicetalk.http.api.StreamingHttpClient) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) HEAD(io.servicetalk.http.api.HttpRequestMethod.HEAD) RedirectConfig(io.servicetalk.http.api.RedirectConfig) Matchers.nullValue(org.hamcrest.Matchers.nullValue) Executor(io.servicetalk.concurrent.api.Executor) FOUND(io.servicetalk.http.api.HttpResponseStatus.FOUND) SEE_OTHER(io.servicetalk.http.api.HttpResponseStatus.SEE_OTHER) StreamingHttpRequestFactory(io.servicetalk.http.api.StreamingHttpRequestFactory) PUT(io.servicetalk.http.api.HttpRequestMethod.PUT) ExecutorExtension(io.servicetalk.concurrent.api.ExecutorExtension) FilterFactoryUtils.appendClientFilterFactory(io.servicetalk.http.api.FilterFactoryUtils.appendClientFilterFactory) Mockito.clearInvocations(org.mockito.Mockito.clearInvocations) Matchers.notNullValue(org.hamcrest.Matchers.notNullValue) TRANSFER_ENCODING(io.servicetalk.http.api.HttpHeaderNames.TRANSFER_ENCODING) CONNECT(io.servicetalk.http.api.HttpRequestMethod.CONNECT) POST(io.servicetalk.http.api.HttpRequestMethod.POST) StatelessTrailersTransformer(io.servicetalk.http.api.StatelessTrailersTransformer) StreamingHttpClientFilter(io.servicetalk.http.api.StreamingHttpClientFilter) CONTENT_LENGTH(io.servicetalk.http.api.HttpHeaderNames.CONTENT_LENGTH) Matchers.startsWith(org.hamcrest.Matchers.startsWith) DefaultHttpHeadersFactory(io.servicetalk.http.api.DefaultHttpHeadersFactory) Test(org.junit.jupiter.api.Test) Matchers.instanceOf(org.hamcrest.Matchers.instanceOf) Buffer(io.servicetalk.buffer.api.Buffer) CONTINUE(io.servicetalk.http.api.HttpResponseStatus.CONTINUE) PATCH(io.servicetalk.http.api.HttpRequestMethod.PATCH) NOT_MODIFIED(io.servicetalk.http.api.HttpResponseStatus.NOT_MODIFIED) Matchers.is(org.hamcrest.Matchers.is) Queue(java.util.Queue) Matchers.endsWith(org.hamcrest.Matchers.endsWith) Mockito.mock(org.mockito.Mockito.mock) Assertions.assertThrows(org.junit.jupiter.api.Assertions.assertThrows) ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) DEFAULT_ALLOCATOR(io.servicetalk.buffer.netty.BufferAllocators.DEFAULT_ALLOCATOR) TestPublisher(io.servicetalk.concurrent.api.TestPublisher) TestStreamingHttpClient.from(io.servicetalk.http.api.TestStreamingHttpClient.from) HttpHeaders(io.servicetalk.http.api.HttpHeaders) StreamingHttpRequester(io.servicetalk.http.api.StreamingHttpRequester) RedirectConfigBuilder(io.servicetalk.http.api.RedirectConfigBuilder) ArgumentCaptor(org.mockito.ArgumentCaptor) RegisterExtension(org.junit.jupiter.api.extension.RegisterExtension) Single.succeeded(io.servicetalk.concurrent.api.Single.succeeded) HOST(io.servicetalk.http.api.HttpHeaderNames.HOST) StreamingHttpRequest(io.servicetalk.http.api.StreamingHttpRequest) Matchers.contentEqualTo(io.servicetalk.buffer.api.Matchers.contentEqualTo) OPTIONS(io.servicetalk.http.api.HttpRequestMethod.OPTIONS) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Publisher.from(io.servicetalk.concurrent.api.Publisher.from) DELIBERATE_EXCEPTION(io.servicetalk.concurrent.internal.DeliberateException.DELIBERATE_EXCEPTION) DELETE(io.servicetalk.http.api.HttpRequestMethod.DELETE) USE_PROXY(io.servicetalk.http.api.HttpResponseStatus.USE_PROXY) Nullable(javax.annotation.Nullable) CHUNKED(io.servicetalk.http.api.HttpHeaderValues.CHUNKED) HttpExecutionContext(io.servicetalk.http.api.HttpExecutionContext) ValueSource(org.junit.jupiter.params.provider.ValueSource) Mockito.ignoreStubs(org.mockito.Mockito.ignoreStubs) INTERNAL_SERVER_ERROR(io.servicetalk.http.api.HttpResponseStatus.INTERNAL_SERVER_ERROR) StreamingHttpRequestResponseFactory(io.servicetalk.http.api.StreamingHttpRequestResponseFactory) Single(io.servicetalk.concurrent.api.Single) Mockito.times(org.mockito.Mockito.times) Mockito.when(org.mockito.Mockito.when) OK(io.servicetalk.http.api.HttpResponseStatus.OK) GET(io.servicetalk.http.api.HttpRequestMethod.GET) Mockito.verify(org.mockito.Mockito.verify) ExecutionException(java.util.concurrent.ExecutionException) ACCEPT_ENCODING(io.servicetalk.http.api.HttpHeaderNames.ACCEPT_ENCODING) US_ASCII(java.nio.charset.StandardCharsets.US_ASCII) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) Matchers.emptyIterable(org.hamcrest.Matchers.emptyIterable) String.valueOf(java.lang.String.valueOf) ArgumentCaptor.forClass(org.mockito.ArgumentCaptor.forClass) Matchers.sameInstance(org.hamcrest.Matchers.sameInstance) PERMANENT_REDIRECT(io.servicetalk.http.api.HttpResponseStatus.PERMANENT_REDIRECT) LinkedBlockingDeque(java.util.concurrent.LinkedBlockingDeque) Single.failed(io.servicetalk.concurrent.api.Single.failed) StreamingHttpClientFilterFactory(io.servicetalk.http.api.StreamingHttpClientFilterFactory) HttpResponseStatus(io.servicetalk.http.api.HttpResponseStatus) HTTP_1_1(io.servicetalk.http.api.HttpProtocolVersion.HTTP_1_1) MOVED_PERMANENTLY(io.servicetalk.http.api.HttpResponseStatus.MOVED_PERMANENTLY) DefaultStreamingHttpRequestResponseFactory(io.servicetalk.http.api.DefaultStreamingHttpRequestResponseFactory) HTTP_1_0(io.servicetalk.http.api.HttpProtocolVersion.HTTP_1_0) TRACE(io.servicetalk.http.api.HttpRequestMethod.TRACE) StreamingHttpClientFilter(io.servicetalk.http.api.StreamingHttpClientFilter) StreamingHttpRequester(io.servicetalk.http.api.StreamingHttpRequester) HttpExecutionContext(io.servicetalk.http.api.HttpExecutionContext) StreamingHttpRequest(io.servicetalk.http.api.StreamingHttpRequest) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse)

Example 17 with Single

use of io.servicetalk.concurrent.api.Single in project servicetalk by apple.

the class RoundRobinLoadBalancer method selectConnection0.

private Single<C> selectConnection0(final Predicate<C> selector, @Nullable final ContextMap context) {
    final List<Host<ResolvedAddress, C>> usedHosts = this.usedHosts;
    if (usedHosts.isEmpty()) {
        return usedHosts == CLOSED_LIST ? failedLBClosed(targetResource) : // This is the case when SD has emitted some items but none of the hosts are available.
        failed(StacklessNoAvailableHostException.newInstance("No hosts are available to connect for " + targetResource + ".", RoundRobinLoadBalancer.class, "selectConnection0(...)"));
    }
    // try one loop over hosts and if all are expired, give up
    final int cursor = (indexUpdater.getAndIncrement(this) & Integer.MAX_VALUE) % usedHosts.size();
    final ThreadLocalRandom rnd = ThreadLocalRandom.current();
    Host<ResolvedAddress, C> pickedHost = null;
    for (int i = 0; i < usedHosts.size(); ++i) {
        // for a particular iteration we maintain a local cursor without contention with other requests
        final int localCursor = (cursor + i) % usedHosts.size();
        final Host<ResolvedAddress, C> host = usedHosts.get(localCursor);
        assert host != null : "Host can't be null.";
        // Try first to see if an existing connection can be used
        final Object[] connections = host.connState.connections;
        // Exhaust the linear search space first:
        final int linearAttempts = min(connections.length, linearSearchSpace);
        for (int j = 0; j < linearAttempts; ++j) {
            @SuppressWarnings("unchecked") final C connection = (C) connections[j];
            if (selector.test(connection)) {
                return succeeded(connection);
            }
        }
        // Try other connections randomly:
        if (connections.length > linearAttempts) {
            final int diff = connections.length - linearAttempts;
            // With small enough search space, attempt number of times equal to number of remaining connections.
            // Back off after exploring most of the search space, it gives diminishing returns.
            final int randomAttempts = diff < MIN_RANDOM_SEARCH_SPACE ? diff : (int) (diff * RANDOM_SEARCH_FACTOR);
            for (int j = 0; j < randomAttempts; ++j) {
                @SuppressWarnings("unchecked") final C connection = (C) connections[rnd.nextInt(linearAttempts, connections.length)];
                if (selector.test(connection)) {
                    return succeeded(connection);
                }
            }
        }
        // Unhealthy hosts have no open connections – that's why we don't fail earlier, the loop will not progress.
        if (host.isActiveAndHealthy()) {
            pickedHost = host;
            break;
        }
    }
    if (pickedHost == null) {
        return failed(StacklessNoAvailableHostException.newInstance("Failed to pick an active host for " + targetResource + ". Either all are busy, expired, or unhealthy: " + usedHosts, RoundRobinLoadBalancer.class, "selectConnection0(...)"));
    }
    // No connection was selected: create a new one.
    final Host<ResolvedAddress, C> host = pickedHost;
    // This LB implementation does not automatically provide TransportObserver. Therefore, we pass "null" here.
    // Users can apply a ConnectionFactoryFilter if they need to override this "null" value with TransportObserver.
    Single<? extends C> establishConnection = connectionFactory.newConnection(host.address, context, null);
    if (host.healthCheckConfig != null) {
        // Schedule health check before returning
        establishConnection = establishConnection.beforeOnError(t -> host.markUnhealthy(t, connectionFactory));
    }
    return establishConnection.flatMap(newCnx -> {
        // used concurrently and hence a new connection can be rejected by the selector.
        if (!selector.test(newCnx)) {
            // with the fact that select failure does not close a connection.
            return newCnx.closeAsync().concat(failed(StacklessConnectionRejectedException.newInstance("Newly created connection " + newCnx + " for " + targetResource + " was rejected by the selection filter.", RoundRobinLoadBalancer.class, "selectConnection0(...)")));
        }
        if (host.addConnection(newCnx)) {
            return succeeded(newCnx);
        }
        return newCnx.closeAsync().concat(this.usedHosts == CLOSED_LIST ? failedLBClosed(targetResource) : failed(StacklessConnectionRejectedException.newInstance("Failed to add newly created connection " + newCnx + " for " + targetResource + " for " + host, RoundRobinLoadBalancer.class, "selectConnection0(...)")));
    });
}
Also used : Arrays(java.util.Arrays) LoggerFactory(org.slf4j.LoggerFactory) LoadBalancer(io.servicetalk.client.api.LoadBalancer) ServiceDiscovererEvent(io.servicetalk.client.api.ServiceDiscovererEvent) Integer.toHexString(java.lang.Integer.toHexString) Collections.singletonList(java.util.Collections.singletonList) SourceAdapters.fromSource(io.servicetalk.concurrent.api.SourceAdapters.fromSource) AsyncContext(io.servicetalk.concurrent.api.AsyncContext) UNAVAILABLE(io.servicetalk.client.api.ServiceDiscovererEvent.Status.UNAVAILABLE) Duration(java.time.Duration) Executor(io.servicetalk.concurrent.api.Executor) AtomicReferenceFieldUpdater.newUpdater(java.util.concurrent.atomic.AtomicReferenceFieldUpdater.newUpdater) LOAD_BALANCER_NOT_READY_EVENT(io.servicetalk.client.api.LoadBalancerReadyEvent.LOAD_BALANCER_NOT_READY_EVENT) EXPIRED(io.servicetalk.client.api.ServiceDiscovererEvent.Status.EXPIRED) AtomicReferenceFieldUpdater(java.util.concurrent.atomic.AtomicReferenceFieldUpdater) Predicate(java.util.function.Predicate) Collections.emptyList(java.util.Collections.emptyList) Collection(java.util.Collection) CompositeCloseable(io.servicetalk.concurrent.api.CompositeCloseable) AsyncCloseables.newCompositeCloseable(io.servicetalk.concurrent.api.AsyncCloseables.newCompositeCloseable) Math.min(java.lang.Math.min) List(java.util.List) Stream(java.util.stream.Stream) ContextMap(io.servicetalk.context.api.ContextMap) ConnectionRejectedException(io.servicetalk.client.api.ConnectionRejectedException) Entry(java.util.Map.Entry) AtomicIntegerFieldUpdater(java.util.concurrent.atomic.AtomicIntegerFieldUpdater) Publisher(io.servicetalk.concurrent.api.Publisher) Processor(io.servicetalk.concurrent.PublisherSource.Processor) SimpleImmutableEntry(java.util.AbstractMap.SimpleImmutableEntry) Function(java.util.function.Function) Subscriber(io.servicetalk.concurrent.PublisherSource.Subscriber) ArrayList(java.util.ArrayList) AVAILABLE(io.servicetalk.client.api.ServiceDiscovererEvent.Status.AVAILABLE) Single.succeeded(io.servicetalk.concurrent.api.Single.succeeded) ThreadLocalRandom(java.util.concurrent.ThreadLocalRandom) Objects.requireNonNull(java.util.Objects.requireNonNull) DelayedCancellable(io.servicetalk.concurrent.internal.DelayedCancellable) AsyncCloseable(io.servicetalk.concurrent.api.AsyncCloseable) Publisher.from(io.servicetalk.concurrent.api.Publisher.from) AtomicIntegerFieldUpdater.newUpdater(java.util.concurrent.atomic.AtomicIntegerFieldUpdater.newUpdater) Nullable(javax.annotation.Nullable) ConnectionFactory(io.servicetalk.client.api.ConnectionFactory) Processors.newPublisherProcessorDropHeadOnOverflow(io.servicetalk.concurrent.api.Processors.newPublisherProcessorDropHeadOnOverflow) Logger(org.slf4j.Logger) RetryStrategies.retryWithConstantBackoffFullJitter(io.servicetalk.concurrent.api.RetryStrategies.retryWithConstantBackoffFullJitter) ListenableAsyncCloseable(io.servicetalk.concurrent.api.ListenableAsyncCloseable) Single.defer(io.servicetalk.concurrent.api.Single.defer) FlowControlUtils.addWithOverflowProtection(io.servicetalk.concurrent.internal.FlowControlUtils.addWithOverflowProtection) LoadBalancedConnection(io.servicetalk.client.api.LoadBalancedConnection) Single(io.servicetalk.concurrent.api.Single) Completable(io.servicetalk.concurrent.api.Completable) LOAD_BALANCER_READY_EVENT(io.servicetalk.client.api.LoadBalancerReadyEvent.LOAD_BALANCER_READY_EVENT) NoAvailableHostException(io.servicetalk.client.api.NoAvailableHostException) AsyncCloseables.toAsyncCloseable(io.servicetalk.concurrent.api.AsyncCloseables.toAsyncCloseable) Subscription(io.servicetalk.concurrent.PublisherSource.Subscription) SourceAdapters.toSource(io.servicetalk.concurrent.api.SourceAdapters.toSource) ThrowableUtils(io.servicetalk.concurrent.internal.ThrowableUtils) Collectors.toList(java.util.stream.Collectors.toList) Completable.completed(io.servicetalk.concurrent.api.Completable.completed) Single.failed(io.servicetalk.concurrent.api.Single.failed) SequentialCancellable(io.servicetalk.concurrent.internal.SequentialCancellable) ThreadLocalRandom(java.util.concurrent.ThreadLocalRandom)

Example 18 with Single

use of io.servicetalk.concurrent.api.Single in project servicetalk by apple.

the class CancellationTest method testCancelResponseSingle.

private void testCancelResponseSingle(final StreamingHttpRequest req, boolean enableOffload) throws Exception {
    final AtomicReference<Throwable> errorRef = new AtomicReference<>();
    final CountDownLatch cancelledLatch = new CountDownLatch(1);
    // different threads because the write operation will block on the Subscriber creating requestN demand.
    if (enableOffload) {
        Single<StreamingHttpResponse> respSingle = execRule.executor().submit(() -> jerseyRouter.handle(ctx, req, HTTP_REQ_RES_FACTORY)).flatMap(identity()).beforeOnError((err) -> {
            // Ignore racy cancellation, it's ordered safely.
            if (!(err instanceof IllegalStateException)) {
                errorRef.compareAndSet(null, err);
            }
        }).afterCancel(cancelledLatch::countDown);
        toSource(respSingle).subscribe(new SingleSource.Subscriber<StreamingHttpResponse>() {

            @Override
            public void onSubscribe(final Cancellable cancellable) {
                cancellable.cancel();
            }

            @Override
            public void onSuccess(@Nullable final StreamingHttpResponse result) {
                if (result == null) {
                    errorRef.compareAndSet(null, new NullPointerException("result == null not expected."));
                    cancelledLatch.countDown();
                } else {
                    result.messageBody().ignoreElements().afterFinally(cancelledLatch::countDown).subscribe();
                }
            }

            @Override
            public void onError(final Throwable t) {
                // Ignore racy cancellation, it's ordered safely.
                if (!(t instanceof IllegalStateException)) {
                    errorRef.compareAndSet(null, t);
                }
                cancelledLatch.countDown();
            }
        });
    } else {
        jerseyRouter.handle(ctx, req, HTTP_REQ_RES_FACTORY).beforeOnError(errorRef::set).afterCancel(cancelledLatch::countDown).ignoreElement().subscribe().cancel();
    }
    cancelledLatch.await();
    final Throwable error = errorRef.get();
    if (error != null) {
        throw new AssertionError(error);
    }
}
Also used : BeforeEach(org.junit.jupiter.api.BeforeEach) ExecutionStrategyTest.asFactory(io.servicetalk.http.router.jersey.ExecutionStrategyTest.asFactory) CancellableResources(io.servicetalk.http.router.jersey.resources.CancellableResources) ArgumentMatchers.eq(org.mockito.ArgumentMatchers.eq) SingleSource(io.servicetalk.concurrent.SingleSource) CONTENT_TYPE(io.servicetalk.http.api.HttpHeaderNames.CONTENT_TYPE) Application(javax.ws.rs.core.Application) Future(java.util.concurrent.Future) ExtendWith(org.junit.jupiter.api.extension.ExtendWith) HttpExecutionStrategies.defaultStrategy(io.servicetalk.http.api.HttpExecutionStrategies.defaultStrategy) Collections.singleton(java.util.Collections.singleton) Mockito.doAnswer(org.mockito.Mockito.doAnswer) Executor(io.servicetalk.concurrent.api.Executor) MockitoExtension(org.mockito.junit.jupiter.MockitoExtension) ExecutorExtension(io.servicetalk.concurrent.api.ExecutorExtension) PATH(io.servicetalk.http.router.jersey.resources.CancellableResources.PATH) Set(java.util.Set) DefaultHttpHeadersFactory(io.servicetalk.http.api.DefaultHttpHeadersFactory) Test(org.junit.jupiter.api.Test) CountDownLatch(java.util.concurrent.CountDownLatch) StreamingHttpService(io.servicetalk.http.api.StreamingHttpService) Function.identity(java.util.function.Function.identity) Matchers.is(org.hamcrest.Matchers.is) Mockito.mock(org.mockito.Mockito.mock) Strictness(org.mockito.quality.Strictness) ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) MockitoSettings(org.mockito.junit.jupiter.MockitoSettings) ArgumentMatchers.anyLong(org.mockito.ArgumentMatchers.anyLong) DEFAULT_ALLOCATOR(io.servicetalk.buffer.netty.BufferAllocators.DEFAULT_ALLOCATOR) Mock(org.mockito.Mock) Cancellable(io.servicetalk.concurrent.Cancellable) AtomicReference(java.util.concurrent.atomic.AtomicReference) HttpServiceContext(io.servicetalk.http.api.HttpServiceContext) RegisterExtension(org.junit.jupiter.api.extension.RegisterExtension) DAYS(java.util.concurrent.TimeUnit.DAYS) StreamingHttpRequest(io.servicetalk.http.api.StreamingHttpRequest) Collections.singletonMap(java.util.Collections.singletonMap) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Publisher.from(io.servicetalk.concurrent.api.Publisher.from) InetSocketAddress.createUnresolved(java.net.InetSocketAddress.createUnresolved) Nullable(javax.annotation.Nullable) HttpExecutionContext(io.servicetalk.http.api.HttpExecutionContext) StreamingHttpRequestResponseFactory(io.servicetalk.http.api.StreamingHttpRequestResponseFactory) Single(io.servicetalk.concurrent.api.Single) Mockito.when(org.mockito.Mockito.when) OK(io.servicetalk.http.api.HttpResponseStatus.OK) SourceAdapters.toSource(io.servicetalk.concurrent.api.SourceAdapters.toSource) TimeUnit(java.util.concurrent.TimeUnit) IoExecutor(io.servicetalk.transport.api.IoExecutor) TestUtils.newLargePayload(io.servicetalk.http.router.jersey.TestUtils.newLargePayload) TEXT_PLAIN(io.servicetalk.http.api.HttpHeaderValues.TEXT_PLAIN) HTTP_1_1(io.servicetalk.http.api.HttpProtocolVersion.HTTP_1_1) DefaultStreamingHttpRequestResponseFactory(io.servicetalk.http.api.DefaultStreamingHttpRequestResponseFactory) SingleSource(io.servicetalk.concurrent.SingleSource) Cancellable(io.servicetalk.concurrent.Cancellable) AtomicReference(java.util.concurrent.atomic.AtomicReference) CountDownLatch(java.util.concurrent.CountDownLatch) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse)

Example 19 with Single

use of io.servicetalk.concurrent.api.Single in project servicetalk by apple.

the class AbstractTimeoutHttpFilter method withTimeout.

/**
 * Returns the response single for the provided request which will be completed within the specified timeout or
 * generate an error with a timeout exception. The timer begins when the {@link Single} is subscribed. The timeout
 * action, if it occurs, will execute on the filter's chosen timeout executor, or if none is specified, the executor
 * from the request or connection context or, if neither are specified, the global executor.
 *
 * @param request The request requiring a response.
 * @param responseFunction Function which generates the response.
 * @param contextExecutor Executor from the request/connection context to be used for the timeout terminal signal if
 * no specific timeout executor is defined for filter.
 * @return response single
 */
final Single<StreamingHttpResponse> withTimeout(final StreamingHttpRequest request, final Function<StreamingHttpRequest, Single<StreamingHttpResponse>> responseFunction, final Executor contextExecutor) {
    final Executor useForTimeout = null != this.timeoutExecutor ? this.timeoutExecutor : contextExecutor;
    return Single.defer(() -> {
        final Duration timeout = timeoutForRequest.apply(request, useForTimeout);
        Single<StreamingHttpResponse> response = responseFunction.apply(request);
        if (null != timeout) {
            final Single<StreamingHttpResponse> timeoutResponse = response.timeout(timeout, useForTimeout);
            if (fullRequestResponse) {
                final long deadline = useForTimeout.currentTime(NANOSECONDS) + timeout.toNanos();
                response = timeoutResponse.map(resp -> resp.transformMessageBody(body -> defer(() -> {
                    final Duration remaining = ofNanos(deadline - useForTimeout.currentTime(NANOSECONDS));
                    return (body.timeoutTerminal(remaining, useForTimeout)).onErrorMap(TimeoutException.class, t -> new MappedTimeoutException("message body timeout after " + timeout.toMillis() + "ms", t)).shareContextOnSubscribe();
                })));
            } else {
                response = timeoutResponse;
            }
        }
        return response.shareContextOnSubscribe();
    });
}
Also used : StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) NANOSECONDS(java.util.concurrent.TimeUnit.NANOSECONDS) Single(io.servicetalk.concurrent.api.Single) BiFunction(java.util.function.BiFunction) HttpExecutionStrategyInfluencer(io.servicetalk.http.api.HttpExecutionStrategyInfluencer) TimeoutException(java.util.concurrent.TimeoutException) Function(java.util.function.Function) HttpRequestMetaData(io.servicetalk.http.api.HttpRequestMetaData) Duration.ofNanos(java.time.Duration.ofNanos) Executor(io.servicetalk.concurrent.Executor) HttpExecutionStrategies(io.servicetalk.http.api.HttpExecutionStrategies) Duration(java.time.Duration) DurationUtils.ensurePositive(io.servicetalk.utils.internal.DurationUtils.ensurePositive) Objects.requireNonNull(java.util.Objects.requireNonNull) HttpExecutionStrategy(io.servicetalk.http.api.HttpExecutionStrategy) TimeSource(io.servicetalk.concurrent.TimeSource) StreamingHttpRequest(io.servicetalk.http.api.StreamingHttpRequest) Publisher.defer(io.servicetalk.concurrent.api.Publisher.defer) Nullable(javax.annotation.Nullable) Executor(io.servicetalk.concurrent.Executor) Duration(java.time.Duration) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse)

Example 20 with Single

use of io.servicetalk.concurrent.api.Single in project servicetalk by apple.

the class ProtobufSerializerMessageBodyReaderWriter method writeTo.

@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public void writeTo(final Object o, final Class<?> type, final Type genericType, final Annotation[] annotations, final MediaType mediaType, final MultivaluedMap<String, Object> httpHeaders, final OutputStream entityStream) throws WebApplicationException {
    final BufferAllocator allocator = ctxRefProvider.get().get().executionContext().bufferAllocator();
    final Publisher<Buffer> bufferPublisher;
    if (o instanceof Single) {
        final Class<? extends MessageLite> clazz = genericType instanceof Class ? (Class) genericType : getSourceClass(genericType);
        Serializer serializer = getSerializerFactory(mediaType).serializerDeserializer(clazz);
        bufferPublisher = ((Single) o).map(t -> serializer.serialize(t, allocator)).toPublisher();
    } else if (o instanceof Publisher) {
        final Class<? extends MessageLite> clazz = genericType instanceof Class ? (Class) genericType : getSourceClass(genericType);
        StreamingSerializer serializer = getSerializerFactory(mediaType).streamingSerializerDeserializer(clazz);
        bufferPublisher = serializer.serialize((Publisher) o, allocator);
    } else {
        Serializer serializer = getSerializerFactory(mediaType).serializerDeserializer((Class<? extends MessageLite>) o.getClass());
        bufferPublisher = Publisher.from(serializer.serialize(o, allocator));
    }
    setResponseBufferPublisher(bufferPublisher, requestCtxProvider.get());
}
Also used : Buffer(io.servicetalk.buffer.api.Buffer) Single(io.servicetalk.concurrent.api.Single) Publisher(io.servicetalk.concurrent.api.Publisher) RequestProperties.setResponseBufferPublisher(io.servicetalk.http.router.jersey.internal.RequestProperties.setResponseBufferPublisher) StreamingSerializer(io.servicetalk.serializer.api.StreamingSerializer) MessageLite(com.google.protobuf.MessageLite) BufferAllocator(io.servicetalk.buffer.api.BufferAllocator) Serializer(io.servicetalk.serializer.api.Serializer) StreamingSerializer(io.servicetalk.serializer.api.StreamingSerializer)

Aggregations

Single (io.servicetalk.concurrent.api.Single)57 StreamingHttpRequest (io.servicetalk.http.api.StreamingHttpRequest)34 StreamingHttpResponse (io.servicetalk.http.api.StreamingHttpResponse)34 Nullable (javax.annotation.Nullable)29 MatcherAssert.assertThat (org.hamcrest.MatcherAssert.assertThat)25 HttpServiceContext (io.servicetalk.http.api.HttpServiceContext)23 StreamingHttpResponseFactory (io.servicetalk.http.api.StreamingHttpResponseFactory)23 Buffer (io.servicetalk.buffer.api.Buffer)22 Single.succeeded (io.servicetalk.concurrent.api.Single.succeeded)21 Test (org.junit.jupiter.api.Test)21 Publisher (io.servicetalk.concurrent.api.Publisher)20 OK (io.servicetalk.http.api.HttpResponseStatus.OK)20 ServerContext (io.servicetalk.transport.api.ServerContext)19 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)19 StreamingHttpServiceFilter (io.servicetalk.http.api.StreamingHttpServiceFilter)18 Matchers.is (org.hamcrest.Matchers.is)18 Completable (io.servicetalk.concurrent.api.Completable)17 InetSocketAddress (java.net.InetSocketAddress)17 AddressUtils.localAddress (io.servicetalk.transport.netty.internal.AddressUtils.localAddress)16 ContextMap (io.servicetalk.context.api.ContextMap)13