Search in sources :

Example 31 with Server

use of com.linkedin.r2.transport.common.Server in project rest.li by linkedin.

the class TestHttpNettyStreamClient method testSlowReaderTimeout.

/**
 * Tests slow EntityStream {@link Reader} implementation should be subject to streaming timeout even
 * if the entire response entity can be buffered in memory.
 *
 * @throws Exception
 */
@Test(dataProvider = "slowReaderTimeoutClientProvider")
public void testSlowReaderTimeout(AbstractNettyStreamClient client) throws Exception {
    // Sets the response size to be greater than zero but smaller than the in-memory buffer for HTTP/1.1
    // and smaller than the receiving window size for HTTP/2 so the receiver will not block sender
    Server server = new HttpServerBuilder().responseSize(R2Constants.DEFAULT_DATA_CHUNK_SIZE).build();
    StreamRequest request = new StreamRequestBuilder(new URI(URL)).setHeader(HttpHeaderNames.HOST.toString(), HOST_NAME.toString()).build(EntityStreams.emptyStream());
    final CountDownLatch responseLatch = new CountDownLatch(1);
    final CountDownLatch streamLatch = new CountDownLatch(1);
    final AtomicReference<TransportResponse<StreamResponse>> atomicTransportResponse = new AtomicReference<>();
    final AtomicReference<Throwable> atomicThrowable = new AtomicReference<>();
    try {
        server.start();
        client.streamRequest(request, new RequestContext(), new HashMap<>(), response -> {
            atomicTransportResponse.set(response);
            responseLatch.countDown();
            // Sets a reader that does not consume any byte
            response.getResponse().getEntityStream().setReader(new Reader() {

                @Override
                public void onInit(ReadHandle rh) {
                }

                @Override
                public void onDataAvailable(ByteString data) {
                }

                @Override
                public void onDone() {
                }

                @Override
                public void onError(Throwable e) {
                    atomicThrowable.set(e);
                    streamLatch.countDown();
                }
            });
        });
    } finally {
        responseLatch.await(5, TimeUnit.SECONDS);
        streamLatch.await(5, TimeUnit.SECONDS);
        server.stop();
    }
    TransportResponse<StreamResponse> transportResponse = atomicTransportResponse.get();
    Assert.assertNotNull(transportResponse, "Expected to receive a response");
    Assert.assertFalse(transportResponse.hasError(), "Expected to receive a response without error");
    Assert.assertNotNull(transportResponse.getResponse());
    Assert.assertNotNull(transportResponse.getResponse().getEntityStream());
    Throwable throwable = atomicThrowable.get();
    Assert.assertNotNull(throwable, "Expected onError invoked with TimeoutException");
    Assert.assertTrue(throwable instanceof RemoteInvocationException);
    Assert.assertNotNull(throwable.getCause());
    Assert.assertTrue(throwable.getCause() instanceof TimeoutException);
}
Also used : Server(org.eclipse.jetty.server.Server) ByteString(com.linkedin.data.ByteString) StreamResponse(com.linkedin.r2.message.stream.StreamResponse) HttpServerBuilder(com.linkedin.r2.testutils.server.HttpServerBuilder) Reader(com.linkedin.r2.message.stream.entitystream.Reader) AtomicReference(java.util.concurrent.atomic.AtomicReference) CountDownLatch(java.util.concurrent.CountDownLatch) StreamRequestBuilder(com.linkedin.r2.message.stream.StreamRequestBuilder) URI(java.net.URI) TransportResponse(com.linkedin.r2.transport.common.bridge.common.TransportResponse) StreamRequest(com.linkedin.r2.message.stream.StreamRequest) ReadHandle(com.linkedin.r2.message.stream.entitystream.ReadHandle) RequestContext(com.linkedin.r2.message.RequestContext) RemoteInvocationException(com.linkedin.r2.RemoteInvocationException) TimeoutException(java.util.concurrent.TimeoutException) Test(org.testng.annotations.Test)

Example 32 with Server

use of com.linkedin.r2.transport.common.Server in project rest.li by linkedin.

the class TestHttp2NettyStreamClient method testChannelReusedAfterStreamingTimeout.

/**
 * When a request fails due to {@link TimeoutException}, connection should not be destroyed.
 * @throws Exception
 */
@Test(timeOut = TEST_TIMEOUT, retryAnalyzer = SingleRetry.class)
public void testChannelReusedAfterStreamingTimeout() throws Exception {
    final HttpServerBuilder.HttpServerStatsProvider statsProvider = new HttpServerBuilder.HttpServerStatsProvider();
    final HttpServerBuilder serverBuilder = new HttpServerBuilder();
    final Server server = serverBuilder.serverStatsProvider(statsProvider).stopTimeout(0).build();
    final HttpClientBuilder clientBuilder = new HttpClientBuilder(_eventLoop, _scheduler);
    final Http2NettyStreamClient client = clientBuilder.setRequestTimeout(1000).buildHttp2StreamClient();
    final TransportResponse<StreamResponse> response1;
    final TransportResponse<StreamResponse> response2;
    try {
        server.start();
        final StreamRequestBuilder builder1 = new StreamRequestBuilder(new URI(URL));
        final StreamRequest request1 = builder1.setMethod(METHOD).setHeader(HttpHeaderNames.HOST.toString(), HOST_NAME.toString()).build(EntityStreams.newEntityStream(new ByteStringWriter(ByteString.copy(new byte[REQUEST_SIZE]))));
        final FutureTransportCallback<StreamResponse> callback1 = new FutureTransportCallback<>();
        client.streamRequest(request1, new RequestContext(), new HashMap<>(), callback1);
        response1 = callback1.get();
        Assert.assertNotNull(response1);
        Assert.assertFalse(response1.hasError());
        response1.getResponse().getEntityStream().setReader(new TimeoutReader());
        final StreamRequestBuilder builder2 = new StreamRequestBuilder(new URI(URL));
        final StreamRequest request2 = builder2.setMethod(METHOD).setHeader(HttpHeaderNames.HOST.toString(), HOST_NAME.toString()).build(EntityStreams.newEntityStream(new ByteStringWriter(ByteString.copy(new byte[REQUEST_SIZE]))));
        final FutureTransportCallback<StreamResponse> callback2 = new FutureTransportCallback<>();
        client.streamRequest(request2, new RequestContext(), new HashMap<>(), callback2);
        response2 = callback2.get();
    } finally {
        server.stop();
    }
    // The 2nd request should succeed
    Assert.assertNotNull(response2);
    Assert.assertFalse(response2.hasError());
    response2.getResponse().getEntityStream().setReader(new DrainReader());
    // The server should have seen 3 requests but establishes only 1 connection with the client
    Assert.assertEquals(statsProvider.requestCount(), 3);
    Assert.assertEquals(statsProvider.clientConnections().size(), 1);
}
Also used : Server(org.eclipse.jetty.server.Server) FutureTransportCallback(com.linkedin.r2.transport.common.bridge.common.FutureTransportCallback) StreamResponse(com.linkedin.r2.message.stream.StreamResponse) HttpServerBuilder(com.linkedin.r2.testutils.server.HttpServerBuilder) HttpClientBuilder(com.linkedin.r2.transport.http.client.HttpClientBuilder) StreamRequestBuilder(com.linkedin.r2.message.stream.StreamRequestBuilder) URI(java.net.URI) DrainReader(com.linkedin.r2.message.stream.entitystream.DrainReader) StreamRequest(com.linkedin.r2.message.stream.StreamRequest) RequestContext(com.linkedin.r2.message.RequestContext) ByteStringWriter(com.linkedin.r2.message.stream.entitystream.ByteStringWriter) Test(org.testng.annotations.Test)

Example 33 with Server

use of com.linkedin.r2.transport.common.Server in project rest.li by linkedin.

the class TestHttp2NettyStreamClient method testMaxConcurrentStreamExhaustion.

/**
 * When the maximum number of concurrent streams is exhausted, the client is expected to throw
 * an {@link StreamException} immediately.
 */
@Test(timeOut = TEST_TIMEOUT)
public void testMaxConcurrentStreamExhaustion() throws Exception {
    final HttpServerBuilder serverBuilder = new HttpServerBuilder();
    final Server server = serverBuilder.maxConcurrentStreams(0).build();
    final HttpClientBuilder clientBuilder = new HttpClientBuilder(_eventLoop, _scheduler);
    final Http2NettyStreamClient client = clientBuilder.buildHttp2StreamClient();
    final FutureTransportCallback<StreamResponse> callback = new FutureTransportCallback<>();
    final TransportResponse<StreamResponse> response;
    try {
        server.start();
        // Sends the stream request
        final StreamRequestBuilder builder = new StreamRequestBuilder(new URI(URL));
        final StreamRequest request = builder.setMethod(METHOD).setHeader(HttpHeaderNames.HOST.toString(), HOST_NAME.toString()).build(EntityStreams.newEntityStream(new ByteStringWriter(ByteString.copy(new byte[REQUEST_SIZE]))));
        client.streamRequest(request, new RequestContext(), new HashMap<>(), callback);
        response = callback.get();
    } finally {
        server.stop();
    }
    Assert.assertNotNull(response);
    Assert.assertTrue(response.hasError());
    Assert.assertNotNull(response.getError());
    ExceptionTestUtil.verifyCauseChain(response.getError(), Http2Exception.StreamException.class);
}
Also used : Http2Exception(io.netty.handler.codec.http2.Http2Exception) Server(org.eclipse.jetty.server.Server) FutureTransportCallback(com.linkedin.r2.transport.common.bridge.common.FutureTransportCallback) StreamResponse(com.linkedin.r2.message.stream.StreamResponse) HttpServerBuilder(com.linkedin.r2.testutils.server.HttpServerBuilder) HttpClientBuilder(com.linkedin.r2.transport.http.client.HttpClientBuilder) StreamRequestBuilder(com.linkedin.r2.message.stream.StreamRequestBuilder) URI(java.net.URI) StreamRequest(com.linkedin.r2.message.stream.StreamRequest) RequestContext(com.linkedin.r2.message.RequestContext) ByteStringWriter(com.linkedin.r2.message.stream.entitystream.ByteStringWriter) Test(org.testng.annotations.Test)

Example 34 with Server

use of com.linkedin.r2.transport.common.Server in project rest.li by linkedin.

the class TestHttp2NettyStreamClient method testChannelReusedAfterRequestTimeout.

/**
 * When a request fails due to {@link TimeoutException}, connection should not be destroyed.
 * @throws Exception
 */
@Test(timeOut = TEST_TIMEOUT)
public void testChannelReusedAfterRequestTimeout() throws Exception {
    final HttpServerBuilder.HttpServerStatsProvider statsProvider = new HttpServerBuilder.HttpServerStatsProvider();
    final HttpServerBuilder serverBuilder = new HttpServerBuilder();
    final Server server = serverBuilder.serverStatsProvider(statsProvider).stopTimeout(0).build();
    final HttpClientBuilder clientBuilder = new HttpClientBuilder(_eventLoop, _scheduler);
    final Http2NettyStreamClient client = clientBuilder.setRequestTimeout(1000).buildHttp2StreamClient();
    final TransportResponse<StreamResponse> response1;
    final TransportResponse<StreamResponse> response2;
    try {
        server.start();
        final StreamRequestBuilder builder1 = new StreamRequestBuilder(new URI(URL));
        final StreamRequest request1 = builder1.setMethod(METHOD).setHeader(HttpHeaderNames.HOST.toString(), HOST_NAME.toString()).build(EntityStreams.newEntityStream(new TimeoutWriter()));
        final FutureTransportCallback<StreamResponse> callback1 = new FutureTransportCallback<>();
        client.streamRequest(request1, new RequestContext(), new HashMap<>(), callback1);
        response1 = callback1.get();
        final StreamRequestBuilder builder2 = new StreamRequestBuilder(new URI(URL));
        final StreamRequest request2 = builder2.setMethod(METHOD).setHeader(HttpHeaderNames.HOST.toString(), HOST_NAME.toString()).build(EntityStreams.newEntityStream(new ByteStringWriter(ByteString.copy(new byte[REQUEST_SIZE]))));
        final FutureTransportCallback<StreamResponse> callback2 = new FutureTransportCallback<>();
        client.streamRequest(request2, new RequestContext(), new HashMap<>(), callback2);
        response2 = callback2.get();
    } finally {
        server.stop();
    }
    // The 1st request should be failed with timeout
    Assert.assertNotNull(response1);
    Assert.assertTrue(response1.hasError());
    Assert.assertNotNull(response1.getError());
    ExceptionTestUtil.verifyCauseChain(response1.getError(), TimeoutException.class);
    // The 2nd request should succeed
    Assert.assertNotNull(response2);
    Assert.assertFalse(response2.hasError());
    response2.getResponse().getEntityStream().setReader(new DrainReader());
    // The server should have seen 2 requests but establishes only 1 connection with the client
    Assert.assertEquals(statsProvider.requestCount(), 3);
    Assert.assertEquals(statsProvider.clientConnections().size(), 1);
}
Also used : Server(org.eclipse.jetty.server.Server) FutureTransportCallback(com.linkedin.r2.transport.common.bridge.common.FutureTransportCallback) StreamResponse(com.linkedin.r2.message.stream.StreamResponse) HttpServerBuilder(com.linkedin.r2.testutils.server.HttpServerBuilder) HttpClientBuilder(com.linkedin.r2.transport.http.client.HttpClientBuilder) StreamRequestBuilder(com.linkedin.r2.message.stream.StreamRequestBuilder) URI(java.net.URI) DrainReader(com.linkedin.r2.message.stream.entitystream.DrainReader) StreamRequest(com.linkedin.r2.message.stream.StreamRequest) RequestContext(com.linkedin.r2.message.RequestContext) ByteStringWriter(com.linkedin.r2.message.stream.entitystream.ByteStringWriter) Test(org.testng.annotations.Test)

Example 35 with Server

use of com.linkedin.r2.transport.common.Server in project rest.li by linkedin.

the class AbstractPerfServerFactory method createPureStreamServer.

public Server createPureStreamServer(int port, URI echoUri, final int msg_size, int numHeaders, int headerSize) {
    String headerContent = new StringGenerator(headerSize).nextMessage();
    StreamRequestHandler handler = new StreamRequestHandler() {

        @Override
        public void handleRequest(StreamRequest request, RequestContext requestContext, final Callback<StreamResponse> callback) {
            request.getEntityStream().setReader(new PerfStreamReader<>(new Callback<None>() {

                @Override
                public void onError(Throwable e) {
                    callback.onError(e);
                }

                @Override
                public void onSuccess(None result) {
                    StreamResponseBuilder builder = new StreamResponseBuilder();
                    for (int i = 0; i < numHeaders; i++) {
                        builder.setHeader(STATIC_HEADER_PREFIX + i, headerContent);
                    }
                    callback.onSuccess(builder.build(EntityStreams.newEntityStream(new PerfStreamWriter(msg_size))));
                }
            }, None.none()));
        }
    };
    final TransportDispatcher dispatcher = new TransportDispatcherBuilder().addStreamHandler(echoUri, handler).build();
    return createServer(port, dispatcher, true);
}
Also used : StreamResponseBuilder(com.linkedin.r2.message.stream.StreamResponseBuilder) TransportDispatcher(com.linkedin.r2.transport.common.bridge.server.TransportDispatcher) StreamRequest(com.linkedin.r2.message.stream.StreamRequest) PerfStreamWriter(test.r2.perf.PerfStreamWriter) StreamRequestHandler(com.linkedin.r2.transport.common.StreamRequestHandler) Callback(com.linkedin.common.callback.Callback) StringGenerator(test.r2.perf.StringGenerator) RequestContext(com.linkedin.r2.message.RequestContext) None(com.linkedin.common.util.None) TransportDispatcherBuilder(com.linkedin.r2.transport.common.bridge.server.TransportDispatcherBuilder)

Aggregations

Test (org.testng.annotations.Test)82 RestRequest (com.linkedin.r2.message.rest.RestRequest)52 RestRequestBuilder (com.linkedin.r2.message.rest.RestRequestBuilder)50 RequestContext (com.linkedin.r2.message.RequestContext)49 URI (java.net.URI)43 RestResponse (com.linkedin.r2.message.rest.RestResponse)41 StreamRequest (com.linkedin.r2.message.stream.StreamRequest)32 FutureCallback (com.linkedin.common.callback.FutureCallback)30 StreamResponse (com.linkedin.r2.message.stream.StreamResponse)30 CountDownLatch (java.util.concurrent.CountDownLatch)24 StreamRequestBuilder (com.linkedin.r2.message.stream.StreamRequestBuilder)23 RestException (com.linkedin.r2.message.rest.RestException)21 ExecutionException (java.util.concurrent.ExecutionException)21 None (com.linkedin.common.util.None)20 Server (org.eclipse.jetty.server.Server)20 ByteString (com.linkedin.data.ByteString)19 HttpServerBuilder (com.linkedin.r2.testutils.server.HttpServerBuilder)19 HashMap (java.util.HashMap)15 RemoteInvocationException (com.linkedin.r2.RemoteInvocationException)13 ArrayList (java.util.ArrayList)13