Search in sources :

Example 21 with Publisher

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

the class AbstractHttpConnectionTest method requestShouldWriteFlatStreamToConnectionAndReadFlatStreamSplicedIntoResponseAndPayload.

@SuppressWarnings("unchecked")
@Test
void requestShouldWriteFlatStreamToConnectionAndReadFlatStreamSplicedIntoResponseAndPayload() throws Exception {
    Buffer chunk1 = allocator.fromAscii("test");
    Buffer chunk2 = allocator.fromAscii("payload");
    Buffer chunk3 = allocator.fromAscii("payload");
    HttpHeaders trailers = headersFactory.newEmptyTrailers();
    HttpHeaders headers = headersFactory.newHeaders();
    headers.add(TRANSFER_ENCODING, CHUNKED);
    StreamingHttpRequest req = newTransportRequest(GET, "/foo", HTTP_1_1, headers, allocator, from(chunk1, chunk2, chunk3, trailers), false, headersFactory);
    HttpResponseMetaData respMeta = newResponseMetaData(HTTP_1_1, OK, INSTANCE.newHeaders().add(CONTENT_TYPE, TEXT_PLAIN));
    Publisher<Object> respFlat = from(respMeta, chunk1, chunk2, chunk3, trailers);
    ArgumentCaptor<Publisher<Object>> reqFlatCaptor = ArgumentCaptor.forClass(Publisher.class);
    when(reqResp.apply(reqFlatCaptor.capture())).thenReturn(respFlat);
    Single<StreamingHttpResponse> responseSingle = http.request(req);
    StreamingHttpResponse resp = awaitIndefinitelyNonNull(responseSingle);
    assertThat(reqFlatCaptor.getValue().toFuture().get(), contains(req, chunk1, chunk2, chunk3, trailers));
    assertThat(resp.status(), equalTo(OK));
    assertThat(resp.version(), equalTo(HTTP_1_1));
    assertThat(resp.headers().get(CONTENT_TYPE), equalTo(TEXT_PLAIN));
    assertThat(resp.payloadBody().toFuture().get(), contains(chunk1, chunk2, chunk3));
}
Also used : Buffer(io.servicetalk.buffer.api.Buffer) HttpHeaders(io.servicetalk.http.api.HttpHeaders) StreamingHttpRequest(io.servicetalk.http.api.StreamingHttpRequest) Publisher(io.servicetalk.concurrent.api.Publisher) HttpResponseMetaData(io.servicetalk.http.api.HttpResponseMetaData) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) Test(org.junit.jupiter.api.Test)

Example 22 with Publisher

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

the class DefaultPartitionedHttpClientBuilder method buildStreaming.

@Override
public StreamingHttpClient buildStreaming() {
    final HttpExecutionContext executionContext = executionContextBuilder.build();
    BiIntFunction<Throwable, ? extends Completable> sdRetryStrategy = serviceDiscovererRetryStrategy;
    if (sdRetryStrategy == null) {
        sdRetryStrategy = retryWithConstantBackoffDeltaJitter(__ -> true, SD_RETRY_STRATEGY_INIT_DURATION, SD_RETRY_STRATEGY_JITTER, executionContext.executor());
    }
    final ServiceDiscoverer<U, R, PartitionedServiceDiscovererEvent<R>> psd = new DefaultSingleAddressHttpClientBuilder.RetryingServiceDiscoverer<>(serviceDiscoverer, sdRetryStrategy);
    final PartitionedClientFactory<U, R, FilterableStreamingHttpClient> clientFactory = (pa, sd) -> {
        // build new context, user may have changed anything on the builder from the filter
        final SingleAddressHttpClientBuilder<U, R> builder = requireNonNull(builderFactory.get());
        builder.serviceDiscoverer(sd);
        setExecutionContext(builder, executionContext);
        if (clientInitializer != null) {
            clientInitializer.initialize(pa, builder);
        }
        return builder.buildStreaming();
    };
    final Publisher<PartitionedServiceDiscovererEvent<R>> psdEvents = psd.discover(address).flatMapConcatIterable(identity());
    final HttpHeadersFactory headersFactory = this.headersFactory;
    final DefaultPartitionedStreamingHttpClientFilter<U, R> partitionedClient = new DefaultPartitionedStreamingHttpClientFilter<>(psdEvents, serviceDiscoveryMaxQueueSize, clientFactory, partitionAttributesBuilderFactory, new DefaultStreamingHttpRequestResponseFactory(executionContext.bufferAllocator(), headersFactory != null ? headersFactory : DefaultHttpHeadersFactory.INSTANCE, HTTP_1_1), executionContext, partitionMapFactory);
    LOGGER.debug("Partitioned client created with base strategy {}", executionContext.executionStrategy());
    return new FilterableClientToClient(partitionedClient, executionContext.executionStrategy());
}
Also used : FilterableStreamingHttpClient(io.servicetalk.http.api.FilterableStreamingHttpClient) HttpRequestMethod(io.servicetalk.http.api.HttpRequestMethod) LoggerFactory(org.slf4j.LoggerFactory) ClientGroup(io.servicetalk.client.api.ClientGroup) StreamingHttpClient(io.servicetalk.http.api.StreamingHttpClient) Executor(io.servicetalk.concurrent.api.Executor) RetryStrategies.retryWithConstantBackoffDeltaJitter(io.servicetalk.concurrent.api.RetryStrategies.retryWithConstantBackoffDeltaJitter) PartitionedClientFactory(io.servicetalk.client.api.internal.DefaultPartitionedClientGroup.PartitionedClientFactory) UnknownPartitionException(io.servicetalk.client.api.partition.UnknownPartitionException) PartitionedHttpClientBuilder(io.servicetalk.http.api.PartitionedHttpClientBuilder) ServiceDiscoverer(io.servicetalk.client.api.ServiceDiscoverer) PartitionedServiceDiscovererEvent(io.servicetalk.client.api.partition.PartitionedServiceDiscovererEvent) DefaultHttpHeadersFactory(io.servicetalk.http.api.DefaultHttpHeadersFactory) HttpRequestMetaData(io.servicetalk.http.api.HttpRequestMetaData) PartitionAttributes(io.servicetalk.client.api.partition.PartitionAttributes) ClosedPartitionException(io.servicetalk.client.api.partition.ClosedPartitionException) DefaultPartitionedClientGroup(io.servicetalk.client.api.internal.DefaultPartitionedClientGroup) PowerSetPartitionMapFactory(io.servicetalk.client.api.internal.partition.PowerSetPartitionMapFactory) Function.identity(java.util.function.Function.identity) ReservedStreamingHttpConnection(io.servicetalk.http.api.ReservedStreamingHttpConnection) BiIntFunction(io.servicetalk.concurrent.api.BiIntFunction) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) Publisher(io.servicetalk.concurrent.api.Publisher) PartitionMapFactory(io.servicetalk.client.api.partition.PartitionMapFactory) Function(java.util.function.Function) Supplier(java.util.function.Supplier) SD_RETRY_STRATEGY_JITTER(io.servicetalk.http.netty.DefaultSingleAddressHttpClientBuilder.SD_RETRY_STRATEGY_JITTER) FilterableReservedStreamingHttpConnection(io.servicetalk.http.api.FilterableReservedStreamingHttpConnection) SD_RETRY_STRATEGY_INIT_DURATION(io.servicetalk.http.netty.DefaultSingleAddressHttpClientBuilder.SD_RETRY_STRATEGY_INIT_DURATION) Objects.requireNonNull(java.util.Objects.requireNonNull) HttpExecutionStrategy(io.servicetalk.http.api.HttpExecutionStrategy) StreamingHttpRequest(io.servicetalk.http.api.StreamingHttpRequest) Nullable(javax.annotation.Nullable) HttpExecutionContext(io.servicetalk.http.api.HttpExecutionContext) Logger(org.slf4j.Logger) PartitionAttributesBuilder(io.servicetalk.client.api.partition.PartitionAttributesBuilder) ListenableAsyncCloseable(io.servicetalk.concurrent.api.ListenableAsyncCloseable) StreamingHttpRequestResponseFactory(io.servicetalk.http.api.StreamingHttpRequestResponseFactory) Single.defer(io.servicetalk.concurrent.api.Single.defer) Single(io.servicetalk.concurrent.api.Single) Completable(io.servicetalk.concurrent.api.Completable) SingleAddressHttpClientBuilder(io.servicetalk.http.api.SingleAddressHttpClientBuilder) IoExecutor(io.servicetalk.transport.api.IoExecutor) BufferAllocator(io.servicetalk.buffer.api.BufferAllocator) StreamingHttpResponseFactory(io.servicetalk.http.api.StreamingHttpResponseFactory) Single.failed(io.servicetalk.concurrent.api.Single.failed) DefaultSingleAddressHttpClientBuilder.setExecutionContext(io.servicetalk.http.netty.DefaultSingleAddressHttpClientBuilder.setExecutionContext) AsyncCloseables.emptyAsyncCloseable(io.servicetalk.concurrent.api.AsyncCloseables.emptyAsyncCloseable) HttpHeadersFactory(io.servicetalk.http.api.HttpHeadersFactory) HTTP_1_1(io.servicetalk.http.api.HttpProtocolVersion.HTTP_1_1) DefaultStreamingHttpRequestResponseFactory(io.servicetalk.http.api.DefaultStreamingHttpRequestResponseFactory) DefaultHttpHeadersFactory(io.servicetalk.http.api.DefaultHttpHeadersFactory) HttpHeadersFactory(io.servicetalk.http.api.HttpHeadersFactory) SingleAddressHttpClientBuilder(io.servicetalk.http.api.SingleAddressHttpClientBuilder) DefaultStreamingHttpRequestResponseFactory(io.servicetalk.http.api.DefaultStreamingHttpRequestResponseFactory) SD_RETRY_STRATEGY_JITTER(io.servicetalk.http.netty.DefaultSingleAddressHttpClientBuilder.SD_RETRY_STRATEGY_JITTER) PartitionedServiceDiscovererEvent(io.servicetalk.client.api.partition.PartitionedServiceDiscovererEvent) HttpExecutionContext(io.servicetalk.http.api.HttpExecutionContext) FilterableStreamingHttpClient(io.servicetalk.http.api.FilterableStreamingHttpClient)

Example 23 with Publisher

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

the class HttpReporter method initReporter.

private PublisherSource.Processor<Span, Span> initReporter(final Builder builder, final HttpClient client) {
    final PublisherSource.Processor<Span, Span> buffer;
    SpanBytesEncoder spanEncoder = builder.codec.spanBytesEncoder();
    final BufferAllocator allocator = client.executionContext().bufferAllocator();
    final Publisher<Buffer> spans;
    if (!builder.batchingEnabled) {
        buffer = newPublisherProcessorDropHeadOnOverflow(builder.maxConcurrentReports);
        spans = fromSource(buffer).map(span -> allocator.wrap(spanEncoder.encodeList(Collections.singletonList(span))));
    } else {
        // As we send maxConcurrentReports number of parallel requests, each with roughly batchSizeHint number of
        // spans, we hold a maximum of that many Spans in-memory that we can send in parallel to the collector.
        buffer = newPublisherProcessorDropHeadOnOverflow(builder.batchSizeHint * builder.maxConcurrentReports);
        spans = fromSource(buffer).buffer(forCountOrTime(builder.batchSizeHint, builder.maxBatchDuration, () -> new ListAccumulator(builder.batchSizeHint), client.executionContext().executor())).filter(accumulate -> !accumulate.isEmpty()).map(bufferedSpans -> allocator.wrap(spanEncoder.encodeList(bufferedSpans)));
    }
    final CompletableSource.Processor spansTerminated = newCompletableProcessor();
    toSource(spans.flatMapCompletable(encodedSpansReporter(client, builder.codec), builder.maxConcurrentReports)).subscribe(spansTerminated);
    closeable.prepend(toAsyncCloseable(graceful -> {
        closeInitiated = true;
        try {
            buffer.onComplete();
        } catch (Throwable t) {
            LOGGER.error("Failed to dispose request buffer. Ignoring.", t);
        }
        return graceful ? fromSource(spansTerminated) : completed();
    }));
    return buffer;
}
Also used : Buffer(io.servicetalk.buffer.api.Buffer) APPLICATION_JSON(io.servicetalk.http.api.HttpHeaderValues.APPLICATION_JSON) Publisher(io.servicetalk.concurrent.api.Publisher) LoggerFactory(org.slf4j.LoggerFactory) Span(zipkin2.Span) CONTENT_TYPE(io.servicetalk.http.api.HttpHeaderNames.CONTENT_TYPE) CharSequences.newAsciiString(io.servicetalk.buffer.api.CharSequences.newAsciiString) Duration.ofSeconds(java.time.Duration.ofSeconds) Function(java.util.function.Function) ArrayList(java.util.ArrayList) SourceAdapters.fromSource(io.servicetalk.concurrent.api.SourceAdapters.fromSource) Duration(java.time.Duration) Objects.requireNonNull(java.util.Objects.requireNonNull) Component(zipkin2.Component) SpanBytesEncoder(zipkin2.codec.SpanBytesEncoder) HttpClient(io.servicetalk.http.api.HttpClient) AsyncCloseable(io.servicetalk.concurrent.api.AsyncCloseable) Reporter(zipkin2.reporter.Reporter) Nonnull(javax.annotation.Nonnull) Processors.newCompletableProcessor(io.servicetalk.concurrent.api.Processors.newCompletableProcessor) Accumulator(io.servicetalk.concurrent.api.BufferStrategy.Accumulator) Processors.newPublisherProcessorDropHeadOnOverflow(io.servicetalk.concurrent.api.Processors.newPublisherProcessorDropHeadOnOverflow) Logger(org.slf4j.Logger) FutureUtils.awaitTermination(io.servicetalk.concurrent.internal.FutureUtils.awaitTermination) PublisherSource(io.servicetalk.concurrent.PublisherSource) OK(zipkin2.CheckResult.OK) Completable(io.servicetalk.concurrent.api.Completable) CompositeCloseable(io.servicetalk.concurrent.api.CompositeCloseable) CheckResult.failed(zipkin2.CheckResult.failed) BufferStrategies.forCountOrTime(io.servicetalk.concurrent.api.BufferStrategies.forCountOrTime) AsyncCloseables.newCompositeCloseable(io.servicetalk.concurrent.api.AsyncCloseables.newCompositeCloseable) CheckResult(zipkin2.CheckResult) AsyncCloseables.toAsyncCloseable(io.servicetalk.concurrent.api.AsyncCloseables.toAsyncCloseable) SourceAdapters.toSource(io.servicetalk.concurrent.api.SourceAdapters.toSource) CompletableSource(io.servicetalk.concurrent.CompletableSource) SUCCESSFUL_2XX(io.servicetalk.http.api.HttpResponseStatus.StatusClass.SUCCESSFUL_2XX) SingleAddressHttpClientBuilder(io.servicetalk.http.api.SingleAddressHttpClientBuilder) List(java.util.List) Buffer(io.servicetalk.buffer.api.Buffer) BufferAllocator(io.servicetalk.buffer.api.BufferAllocator) Completable.completed(io.servicetalk.concurrent.api.Completable.completed) Collections(java.util.Collections) HttpResponseStatus(io.servicetalk.http.api.HttpResponseStatus) PublisherSource(io.servicetalk.concurrent.PublisherSource) SpanBytesEncoder(zipkin2.codec.SpanBytesEncoder) CompletableSource(io.servicetalk.concurrent.CompletableSource) Span(zipkin2.Span) BufferAllocator(io.servicetalk.buffer.api.BufferAllocator)

Example 24 with Publisher

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

the class H2PriorKnowledgeFeatureParityTest method clientRespectsSettingsFrame.

@ParameterizedTest(name = "{displayName} [{index}] client={0}, h2PriorKnowledge={1}")
@MethodSource("clientExecutors")
void clientRespectsSettingsFrame(HttpTestExecutionStrategy strategy, boolean h2PriorKnowledge) throws Exception {
    setUp(strategy, h2PriorKnowledge);
    assumeTrue(h2PriorKnowledge, "Only HTTP/2 supports SETTINGS frames");
    int expectedMaxConcurrent = 1;
    BlockingQueue<FilterableStreamingHttpConnection> connectionQueue = new LinkedBlockingQueue<>();
    BlockingQueue<Publisher<? extends ConsumableEvent<Integer>>> maxConcurrentPubQueue = new LinkedBlockingQueue<>();
    AtomicReference<Channel> serverParentChannelRef = new AtomicReference<>();
    CountDownLatch serverChannelLatch = new CountDownLatch(1);
    CountDownLatch serverSettingsAckLatch = new CountDownLatch(2);
    serverAcceptorChannel = bindH2Server(serverEventLoopGroup, new ChannelInitializer<Channel>() {

        @Override
        protected void initChannel(final Channel ch) {
            ch.pipeline().addLast(new EchoHttp2Handler());
        }
    }, parentPipeline -> parentPipeline.addLast(new ChannelInboundHandlerAdapter() {

        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            if (serverParentChannelRef.compareAndSet(null, ctx.channel())) {
                serverChannelLatch.countDown();
            }
            super.channelActive(ctx);
        }

        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            if (msg instanceof Http2SettingsAckFrame) {
                serverSettingsAckLatch.countDown();
            }
            super.channelRead(ctx, msg);
        }
    }), identity());
    InetSocketAddress serverAddress = (InetSocketAddress) serverAcceptorChannel.localAddress();
    try (StreamingHttpClient client = forSingleAddress(HostAndPort.of(serverAddress)).protocols(h2PriorKnowledge ? h2Default() : h1Default()).executionStrategy(clientExecutionStrategy).appendConnectionFilter(conn -> new TestConnectionFilter(conn, connectionQueue, maxConcurrentPubQueue)).buildStreaming()) {
        Processor<Buffer, Buffer> requestPayload = newProcessor();
        client.request(client.post("/0").payloadBody(fromSource(requestPayload))).toFuture().get();
        serverChannelLatch.await();
        Channel serverParentChannel = serverParentChannelRef.get();
        serverParentChannel.writeAndFlush(new DefaultHttp2SettingsFrame(new Http2Settings().maxConcurrentStreams(expectedMaxConcurrent))).sync();
        Iterator<? extends ConsumableEvent<Integer>> maxItr = maxConcurrentPubQueue.take().toIterable().iterator();
        // Verify that the initial maxConcurrency value is the default number
        assertThat("No initial maxConcurrency value", maxItr.hasNext(), is(true));
        ConsumableEvent<Integer> next = maxItr.next();
        assertThat(next, is(notNullValue()));
        assertThat("First event is not the default", next.event(), is(SMALLEST_MAX_CONCURRENT_STREAMS));
        // We previously made a request, and intentionally didn't complete the request body. We want to verify
        // that we have received the SETTINGS frame reducing the total number of streams to 1.
        assertThat("No maxConcurrency value received", maxItr.hasNext(), is(true));
        next = maxItr.next();
        assertThat(next, is(notNullValue()));
        assertThat("maxConcurrency did not change to the expected value", next.event(), is(expectedMaxConcurrent));
        // Wait for a server to receive a settings ack
        serverSettingsAckLatch.await();
        // After this point we want to issue a new request and verify that client selects a new connection.
        Processor<Buffer, Buffer> requestPayload2 = newProcessor();
        client.request(client.post("/1").payloadBody(fromSource(requestPayload2))).toFuture().get();
        // We expect 2 connections to be created.
        assertNotSame(connectionQueue.take(), connectionQueue.take());
        requestPayload.onComplete();
        requestPayload2.onComplete();
    }
}
Also used : TestUtils.assertNoAsyncErrors(io.servicetalk.test.resources.TestUtils.assertNoAsyncErrors) UnaryOperator.identity(java.util.function.UnaryOperator.identity) ChannelInboundHandlerAdapter(io.netty.channel.ChannelInboundHandlerAdapter) SingleSource(io.servicetalk.concurrent.SingleSource) StreamingHttpServiceFilterFactory(io.servicetalk.http.api.StreamingHttpServiceFilterFactory) UnaryOperator(java.util.function.UnaryOperator) LogLevel(io.servicetalk.logging.api.LogLevel) DefaultHttp2DataFrame(io.netty.handler.codec.http2.DefaultHttp2DataFrame) Disabled(org.junit.jupiter.api.Disabled) Matchers.hasItems(org.hamcrest.Matchers.hasItems) SourceAdapters.fromSource(io.servicetalk.concurrent.api.SourceAdapters.fromSource) H2StreamResetException(io.servicetalk.http.netty.NettyHttp2ExceptionUtils.H2StreamResetException) AsyncContext(io.servicetalk.concurrent.api.AsyncContext) HttpRequest(io.servicetalk.http.api.HttpRequest) Assumptions.assumeFalse(org.junit.jupiter.api.Assumptions.assumeFalse) Matchers.nullValue(org.hamcrest.Matchers.nullValue) PROTOCOL_ERROR(io.netty.handler.codec.http2.Http2Error.PROTOCOL_ERROR) HttpCookiePair(io.servicetalk.http.api.HttpCookiePair) DefaultHttp2ResetFrame(io.netty.handler.codec.http2.DefaultHttp2ResetFrame) EXPECT(io.servicetalk.http.api.HttpHeaderNames.EXPECT) BlockingHttpClient(io.servicetalk.http.api.BlockingHttpClient) PrintWriter(java.io.PrintWriter) Matchers.notNullValue(org.hamcrest.Matchers.notNullValue) DefaultHttp2SettingsFrame(io.netty.handler.codec.http2.DefaultHttp2SettingsFrame) HttpClients.forSingleAddress(io.servicetalk.http.netty.HttpClients.forSingleAddress) HttpResponse(io.servicetalk.http.api.HttpResponse) Http2SettingsAckFrame(io.netty.handler.codec.http2.Http2SettingsAckFrame) TRANSFER_ENCODING(io.servicetalk.http.api.HttpHeaderNames.TRANSFER_ENCODING) POST(io.servicetalk.http.api.HttpRequestMethod.POST) BlockingQueue(java.util.concurrent.BlockingQueue) ChannelPipeline(io.netty.channel.ChannelPipeline) MILLISECONDS(java.util.concurrent.TimeUnit.MILLISECONDS) StatelessTrailersTransformer(io.servicetalk.http.api.StatelessTrailersTransformer) StreamingHttpClientFilter(io.servicetalk.http.api.StreamingHttpClientFilter) StreamingHttpConnectionFilter(io.servicetalk.http.api.StreamingHttpConnectionFilter) Arguments(org.junit.jupiter.params.provider.Arguments) Assertions.assertNotSame(org.junit.jupiter.api.Assertions.assertNotSame) Http2HeadersFrame(io.netty.handler.codec.http2.Http2HeadersFrame) UPGRADE(io.servicetalk.http.api.HttpHeaderNames.UPGRADE) CountDownLatch(java.util.concurrent.CountDownLatch) HttpSetCookie(io.servicetalk.http.api.HttpSetCookie) Buffer(io.servicetalk.buffer.api.Buffer) Stream(java.util.stream.Stream) Http2Headers(io.netty.handler.codec.http2.Http2Headers) Assertions.assertTrue(org.junit.jupiter.api.Assertions.assertTrue) COOKIE(io.servicetalk.http.api.HttpHeaderNames.COOKIE) Matchers.is(org.hamcrest.Matchers.is) CONTENT_TYPE(io.netty.handler.codec.http.HttpHeaderNames.CONTENT_TYPE) Assertions.assertThrows(org.junit.jupiter.api.Assertions.assertThrows) Assertions.assertNotNull(org.junit.jupiter.api.Assertions.assertNotNull) Processor(io.servicetalk.concurrent.PublisherSource.Processor) BuilderUtils.serverChannel(io.servicetalk.transport.netty.internal.BuilderUtils.serverChannel) TRAILER(io.netty.handler.codec.http.HttpHeaderNames.TRAILER) Assertions.assertNull(org.junit.jupiter.api.Assertions.assertNull) HttpHeaders(io.servicetalk.http.api.HttpHeaders) ConsumableEvent(io.servicetalk.client.api.ConsumableEvent) StreamingHttpRequester(io.servicetalk.http.api.StreamingHttpRequester) FilterableStreamingHttpConnection(io.servicetalk.http.api.FilterableStreamingHttpConnection) ArrayList(java.util.ArrayList) EMPTY_BUFFER(io.servicetalk.buffer.api.EmptyBuffer.EMPTY_BUFFER) MAX_CONCURRENCY(io.servicetalk.http.api.HttpEventKey.MAX_CONCURRENCY) HeaderUtils.isTransferEncodingChunked(io.servicetalk.http.api.HeaderUtils.isTransferEncodingChunked) HttpServiceContext(io.servicetalk.http.api.HttpServiceContext) Single.succeeded(io.servicetalk.concurrent.api.Single.succeeded) Processors(io.servicetalk.concurrent.api.Processors) BiConsumer(java.util.function.BiConsumer) Assumptions.assumeTrue(org.junit.jupiter.api.Assumptions.assumeTrue) StreamingHttpRequest(io.servicetalk.http.api.StreamingHttpRequest) AddressUtils.serverHostAndPort(io.servicetalk.transport.netty.internal.AddressUtils.serverHostAndPort) Matchers.contentEqualTo(io.servicetalk.buffer.api.Matchers.contentEqualTo) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) Nullable(javax.annotation.Nullable) CHUNKED(io.servicetalk.http.api.HttpHeaderValues.CHUNKED) SMALLEST_MAX_CONCURRENT_STREAMS(io.netty.handler.codec.http2.Http2CodecUtil.SMALLEST_MAX_CONCURRENT_STREAMS) DEFAULT(io.servicetalk.http.netty.HttpTestExecutionStrategy.DEFAULT) Single(io.servicetalk.concurrent.api.Single) StringWriter(java.io.StringWriter) Completable(io.servicetalk.concurrent.api.Completable) DefaultHttp2HeadersFrame(io.netty.handler.codec.http2.DefaultHttp2HeadersFrame) IOException(java.io.IOException) ReservedBlockingHttpConnection(io.servicetalk.http.api.ReservedBlockingHttpConnection) OK(io.servicetalk.http.api.HttpResponseStatus.OK) GET(io.servicetalk.http.api.HttpRequestMethod.GET) Channel(io.netty.channel.Channel) Http2Settings(io.netty.handler.codec.http2.Http2Settings) AfterEach(org.junit.jupiter.api.AfterEach) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) String.valueOf(java.lang.String.valueOf) Completable.completed(io.servicetalk.concurrent.api.Completable.completed) Http2MultiplexHandler(io.netty.handler.codec.http2.Http2MultiplexHandler) HttpHeaderNames(io.netty.handler.codec.http.HttpHeaderNames) HttpResponseStatus(io.servicetalk.http.api.HttpResponseStatus) HostAndPort(io.servicetalk.transport.api.HostAndPort) HttpRequestMethod(io.servicetalk.http.api.HttpRequestMethod) Matchers.emptyString(org.hamcrest.Matchers.emptyString) Http2FrameCodecBuilder(io.netty.handler.codec.http2.Http2FrameCodecBuilder) Key.newKey(io.servicetalk.context.api.ContextMap.Key.newKey) Assertions.assertFalse(org.junit.jupiter.api.Assertions.assertFalse) StreamingHttpClient(io.servicetalk.http.api.StreamingHttpClient) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Http2DataFrame(io.netty.handler.codec.http2.Http2DataFrame) CONNECTION(io.servicetalk.http.api.HttpHeaderNames.CONNECTION) MethodSource(org.junit.jupiter.params.provider.MethodSource) ChannelDuplexHandler(io.netty.channel.ChannelDuplexHandler) ChannelInitializer(io.netty.channel.ChannelInitializer) PublisherSource(io.servicetalk.concurrent.PublisherSource) CONTENT_LENGTH(io.servicetalk.http.api.HttpHeaderNames.CONTENT_LENGTH) InetSocketAddress(java.net.InetSocketAddress) LinkedBlockingQueue(java.util.concurrent.LinkedBlockingQueue) HttpEventKey(io.servicetalk.http.api.HttpEventKey) Test(org.junit.jupiter.api.Test) List(java.util.List) ContextMap(io.servicetalk.context.api.ContextMap) DelegatingConnectionAcceptor(io.servicetalk.transport.api.DelegatingConnectionAcceptor) Matchers.equalTo(org.hamcrest.Matchers.equalTo) Writer(java.io.Writer) Queue(java.util.Queue) CONTINUE(io.servicetalk.http.api.HttpHeaderValues.CONTINUE) ConcurrentLinkedQueue(java.util.concurrent.ConcurrentLinkedQueue) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) Publisher(io.servicetalk.concurrent.api.Publisher) Http2Exception(io.servicetalk.http.api.Http2Exception) AtomicReference(java.util.concurrent.atomic.AtomicReference) StreamingHttpServiceFilter(io.servicetalk.http.api.StreamingHttpServiceFilter) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) HttpMetaData(io.servicetalk.http.api.HttpMetaData) HttpProtocolConfigs.h1Default(io.servicetalk.http.netty.HttpProtocolConfigs.h1Default) HttpProtocolConfigs.h2Default(io.servicetalk.http.netty.HttpProtocolConfigs.h2Default) HttpSerializers.textSerializerUtf8(io.servicetalk.http.api.HttpSerializers.textSerializerUtf8) HttpExecutionStrategy(io.servicetalk.http.api.HttpExecutionStrategy) NettyConnectionContext(io.servicetalk.transport.netty.internal.NettyConnectionContext) DELIBERATE_EXCEPTION(io.servicetalk.concurrent.internal.DeliberateException.DELIBERATE_EXCEPTION) HttpServerBuilder(io.servicetalk.http.api.HttpServerBuilder) ConnectionContext(io.servicetalk.transport.api.ConnectionContext) KEEP_ALIVE(io.servicetalk.http.api.HttpHeaderValues.KEEP_ALIVE) INTERNAL_SERVER_ERROR(io.servicetalk.http.api.HttpResponseStatus.INTERNAL_SERVER_ERROR) AddressUtils.localAddress(io.servicetalk.transport.netty.internal.AddressUtils.localAddress) EventLoopGroup(io.netty.channel.EventLoopGroup) ServerContext(io.servicetalk.transport.api.ServerContext) Iterator(java.util.Iterator) EXPECTATION_FAILED(io.servicetalk.http.api.HttpResponseStatus.EXPECTATION_FAILED) NettyIoExecutors.createIoExecutor(io.servicetalk.transport.netty.internal.NettyIoExecutors.createIoExecutor) UTF_8(java.nio.charset.StandardCharsets.UTF_8) Processors.newPublisherProcessor(io.servicetalk.concurrent.api.Processors.newPublisherProcessor) Consumer(java.util.function.Consumer) Matchers.emptyIterable(org.hamcrest.Matchers.emptyIterable) PROXY_CONNECTION(io.servicetalk.http.netty.H2ToStH1Utils.PROXY_CONNECTION) StreamingHttpResponseFactory(io.servicetalk.http.api.StreamingHttpResponseFactory) NO_OFFLOAD(io.servicetalk.http.netty.HttpTestExecutionStrategy.NO_OFFLOAD) ServerBootstrap(io.netty.bootstrap.ServerBootstrap) ChannelHandler(io.netty.channel.ChannelHandler) SET_COOKIE(io.servicetalk.http.api.HttpHeaderNames.SET_COOKIE) DefaultHttpCookiePair(io.servicetalk.http.api.DefaultHttpCookiePair) DefaultHttp2Headers(io.netty.handler.codec.http2.DefaultHttp2Headers) Http2SettingsAckFrame(io.netty.handler.codec.http2.Http2SettingsAckFrame) StreamingHttpClient(io.servicetalk.http.api.StreamingHttpClient) InetSocketAddress(java.net.InetSocketAddress) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) LinkedBlockingQueue(java.util.concurrent.LinkedBlockingQueue) ConsumableEvent(io.servicetalk.client.api.ConsumableEvent) ChannelInitializer(io.netty.channel.ChannelInitializer) Http2Settings(io.netty.handler.codec.http2.Http2Settings) Buffer(io.servicetalk.buffer.api.Buffer) FilterableStreamingHttpConnection(io.servicetalk.http.api.FilterableStreamingHttpConnection) DefaultHttp2SettingsFrame(io.netty.handler.codec.http2.DefaultHttp2SettingsFrame) BuilderUtils.serverChannel(io.servicetalk.transport.netty.internal.BuilderUtils.serverChannel) Channel(io.netty.channel.Channel) AtomicReference(java.util.concurrent.atomic.AtomicReference) Publisher(io.servicetalk.concurrent.api.Publisher) CountDownLatch(java.util.concurrent.CountDownLatch) H2StreamResetException(io.servicetalk.http.netty.NettyHttp2ExceptionUtils.H2StreamResetException) IOException(java.io.IOException) Http2Exception(io.servicetalk.http.api.Http2Exception) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ChannelInboundHandlerAdapter(io.netty.channel.ChannelInboundHandlerAdapter) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) MethodSource(org.junit.jupiter.params.provider.MethodSource)

Example 25 with Publisher

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

the class HttpLifecycleObserverTest method testClientCancelsRequestBeforeResponse.

@ParameterizedTest(name = "{displayName} [{index}] protocol={0}")
@EnumSource(HttpProtocol.class)
void testClientCancelsRequestBeforeResponse(HttpProtocol protocol) throws Exception {
    CountDownLatch requestReceived = new CountDownLatch(1);
    serviceFilterFactory(service -> new StreamingHttpServiceFilter(service) {

        @Override
        public Single<StreamingHttpResponse> handle(HttpServiceContext ctx, StreamingHttpRequest request, StreamingHttpResponseFactory responseFactory) {
            return delegate().handle(ctx, request.transformMessageBody(mb -> mb.afterOnNext(__ -> requestReceived.countDown())), responseFactory);
        }
    });
    setUp(protocol);
    StreamingHttpClient client = streamingHttpClient();
    Future<StreamingHttpResponse> responseFuture = client.request(client.post(SVC_NEVER).payloadBody(Publisher.from(CONTENT.duplicate()).concat(Publisher.never()))).toFuture();
    requestReceived.await();
    responseFuture.cancel(true);
    bothTerminate.await();
    verify(serverExchangeObserver, await()).onExchangeFinally();
    clientInOrder.verify(clientLifecycleObserver).onNewExchange();
    clientInOrder.verify(clientExchangeObserver).onRequest(any(StreamingHttpRequest.class));
    clientInOrder.verify(clientExchangeObserver).onConnectionSelected(any(ConnectionInfo.class));
    clientInOrder.verify(clientExchangeObserver).onResponseCancel();
    clientRequestInOrder.verify(clientRequestObserver).onRequestDataRequested(anyLong());
    clientRequestInOrder.verify(clientRequestObserver).onRequestData(any(Buffer.class));
    clientRequestInOrder.verify(clientRequestObserver).onRequestCancel();
    clientInOrder.verify(clientExchangeObserver).onExchangeFinally();
    verifyNoMoreInteractions(clientLifecycleObserver, clientExchangeObserver, clientRequestObserver);
    verifyNoInteractions(clientResponseObserver);
    serverInOrder.verify(serverLifecycleObserver).onNewExchange();
    serverInOrder.verify(serverExchangeObserver).onConnectionSelected(any(ConnectionInfo.class));
    serverInOrder.verify(serverExchangeObserver).onRequest(any(StreamingHttpRequest.class));
    serverRequestInOrder.verify(serverRequestObserver, atLeastOnce()).onRequestDataRequested(anyLong());
    serverRequestInOrder.verify(serverRequestObserver).onRequestData(any(Buffer.class));
    serverRequestInOrder.verify(serverRequestObserver).onRequestError(any(IOException.class));
    // because of offloading, cancel from the IO-thread may race with an error propagated through request publisher:
    verify(serverExchangeObserver, atMostOnce()).onResponseCancel();
    verify(serverExchangeObserver, atMostOnce()).onResponse(any(StreamingHttpResponse.class));
    verify(serverResponseObserver, atMostOnce()).onResponseDataRequested(anyLong());
    verify(serverResponseObserver, atMostOnce()).onResponseComplete();
    serverInOrder.verify(serverExchangeObserver).onExchangeFinally();
    verifyNoMoreInteractions(serverLifecycleObserver, serverExchangeObserver, serverRequestObserver, serverResponseObserver);
}
Also used : HttpLifecycleObserver(io.servicetalk.http.api.HttpLifecycleObserver) HttpLifecycleObservers.logging(io.servicetalk.http.utils.HttpLifecycleObservers.logging) ConnectionInfo(io.servicetalk.transport.api.ConnectionInfo) Mockito.verifyNoInteractions(org.mockito.Mockito.verifyNoInteractions) Future(java.util.concurrent.Future) StreamingHttpClient(io.servicetalk.http.api.StreamingHttpClient) Mockito.verifyNoMoreInteractions(org.mockito.Mockito.verifyNoMoreInteractions) Mockito.doAnswer(org.mockito.Mockito.doAnswer) HttpRequestObserver(io.servicetalk.http.api.HttpLifecycleObserver.HttpRequestObserver) HttpTransportObserverTest.await(io.servicetalk.http.netty.HttpTransportObserverTest.await) Collection(java.util.Collection) Mockito.atLeastOnce(org.mockito.Mockito.atLeastOnce) SVC_ECHO(io.servicetalk.http.netty.TestServiceStreaming.SVC_ECHO) HttpExchangeObserver(io.servicetalk.http.api.HttpLifecycleObserver.HttpExchangeObserver) StatelessTrailersTransformer(io.servicetalk.http.api.StatelessTrailersTransformer) StreamingHttpConnectionFilter(io.servicetalk.http.api.StreamingHttpConnectionFilter) Mockito.atMostOnce(org.mockito.Mockito.atMostOnce) Matchers.instanceOf(org.hamcrest.Matchers.instanceOf) CountDownLatch(java.util.concurrent.CountDownLatch) SVC_THROW_ERROR(io.servicetalk.http.netty.TestServiceStreaming.SVC_THROW_ERROR) Buffer(io.servicetalk.buffer.api.Buffer) SVC_NEVER(io.servicetalk.http.netty.TestServiceStreaming.SVC_NEVER) Mockito.inOrder(org.mockito.Mockito.inOrder) DEFAULT_RO_ALLOCATOR(io.servicetalk.buffer.api.ReadOnlyBufferAllocators.DEFAULT_RO_ALLOCATOR) Assertions.assertThrows(org.junit.jupiter.api.Assertions.assertThrows) ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) ArgumentMatchers.anyLong(org.mockito.ArgumentMatchers.anyLong) TestPublisher(io.servicetalk.concurrent.api.TestPublisher) SVC_ERROR_DURING_READ(io.servicetalk.http.netty.TestServiceStreaming.SVC_ERROR_DURING_READ) Publisher(io.servicetalk.concurrent.api.Publisher) Mock(org.mockito.Mock) TRACE(io.servicetalk.logging.api.LogLevel.TRACE) Http2Exception(io.servicetalk.http.api.Http2Exception) HttpHeaders(io.servicetalk.http.api.HttpHeaders) EnumSource(org.junit.jupiter.params.provider.EnumSource) HttpResponseObserver(io.servicetalk.http.api.HttpLifecycleObserver.HttpResponseObserver) StreamingHttpServiceFilter(io.servicetalk.http.api.StreamingHttpServiceFilter) HttpServiceContext(io.servicetalk.http.api.HttpServiceContext) SVC_NO_CONTENT(io.servicetalk.http.netty.TestServiceStreaming.SVC_NO_CONTENT) Single.succeeded(io.servicetalk.concurrent.api.Single.succeeded) StreamingHttpRequest(io.servicetalk.http.api.StreamingHttpRequest) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) DELIBERATE_EXCEPTION(io.servicetalk.concurrent.internal.DeliberateException.DELIBERATE_EXCEPTION) CACHED_SERVER(io.servicetalk.http.netty.AbstractNettyHttpServerTest.ExecutorSupplier.CACHED_SERVER) INTERNAL_SERVER_ERROR(io.servicetalk.http.api.HttpResponseStatus.INTERNAL_SERVER_ERROR) InOrder(org.mockito.InOrder) StreamingHttpConnection(io.servicetalk.http.api.StreamingHttpConnection) ClosedChannelException(java.nio.channels.ClosedChannelException) Single(io.servicetalk.concurrent.api.Single) NO_CONTENT(io.servicetalk.http.api.HttpResponseStatus.NO_CONTENT) HttpLifecycleObservers.combine(io.servicetalk.http.utils.HttpLifecycleObservers.combine) IOException(java.io.IOException) Mockito.times(org.mockito.Mockito.times) Mockito.when(org.mockito.Mockito.when) OK(io.servicetalk.http.api.HttpResponseStatus.OK) SVC_SINGLE_ERROR(io.servicetalk.http.netty.TestServiceStreaming.SVC_SINGLE_ERROR) Mockito.verify(org.mockito.Mockito.verify) ExecutionException(java.util.concurrent.ExecutionException) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) Mockito.never(org.mockito.Mockito.never) CACHED(io.servicetalk.http.netty.AbstractNettyHttpServerTest.ExecutorSupplier.CACHED) Matchers.sameInstance(org.hamcrest.Matchers.sameInstance) StreamingHttpResponseFactory(io.servicetalk.http.api.StreamingHttpResponseFactory) Single.failed(io.servicetalk.concurrent.api.Single.failed) HttpResponseStatus(io.servicetalk.http.api.HttpResponseStatus) Buffer(io.servicetalk.buffer.api.Buffer) StreamingHttpClient(io.servicetalk.http.api.StreamingHttpClient) StreamingHttpResponseFactory(io.servicetalk.http.api.StreamingHttpResponseFactory) IOException(java.io.IOException) CountDownLatch(java.util.concurrent.CountDownLatch) StreamingHttpServiceFilter(io.servicetalk.http.api.StreamingHttpServiceFilter) Single(io.servicetalk.concurrent.api.Single) HttpServiceContext(io.servicetalk.http.api.HttpServiceContext) StreamingHttpRequest(io.servicetalk.http.api.StreamingHttpRequest) ConnectionInfo(io.servicetalk.transport.api.ConnectionInfo) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) EnumSource(org.junit.jupiter.params.provider.EnumSource) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Aggregations

Publisher (io.servicetalk.concurrent.api.Publisher)30 Buffer (io.servicetalk.buffer.api.Buffer)16 Single (io.servicetalk.concurrent.api.Single)15 Test (org.junit.jupiter.api.Test)15 MatcherAssert.assertThat (org.hamcrest.MatcherAssert.assertThat)13 Completable (io.servicetalk.concurrent.api.Completable)12 PublisherSource (io.servicetalk.concurrent.PublisherSource)11 Collection (java.util.Collection)11 SourceAdapters.toSource (io.servicetalk.concurrent.api.SourceAdapters.toSource)10 StreamingHttpResponse (io.servicetalk.http.api.StreamingHttpResponse)10 ArrayList (java.util.ArrayList)10 List (java.util.List)10 Matchers.instanceOf (org.hamcrest.Matchers.instanceOf)10 Matchers.is (org.hamcrest.Matchers.is)10 Subscription (io.servicetalk.concurrent.PublisherSource.Subscription)9 StreamingHttpRequest (io.servicetalk.http.api.StreamingHttpRequest)9 DEFAULT_ALLOCATOR (io.servicetalk.buffer.netty.BufferAllocators.DEFAULT_ALLOCATOR)8 Completable.completed (io.servicetalk.concurrent.api.Completable.completed)8 Executor (io.servicetalk.concurrent.api.Executor)8 HttpHeaders (io.servicetalk.http.api.HttpHeaders)8