use of io.servicetalk.transport.api.TransportObserver in project servicetalk by apple.
the class HttpTransportObserverTest method setUp.
private void setUp(HttpProtocol protocol) {
this.protocol = protocol;
protocol(protocol.config);
connectionAcceptor(ctx -> {
ctx.onClose().whenFinally(serverConnectionClosed::countDown).subscribe();
return completed();
});
serviceFilterFactory(service -> new StreamingHttpServiceFilter(service) {
@Override
public Single<StreamingHttpResponse> handle(HttpServiceContext ctx, StreamingHttpRequest request, StreamingHttpResponseFactory responseFactory) {
requestReceived.countDown();
try {
processRequest.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throwException(e);
}
return delegate().handle(ctx, request, responseFactory);
}
});
clientTransportObserver = mock(TransportObserver.class, "clientTransportObserver");
clientConnectionObserver = mock(ConnectionObserver.class, "clientConnectionObserver");
clientDataObserver = mock(DataObserver.class, "clientDataObserver");
clientMultiplexedObserver = mock(MultiplexedObserver.class, "clientMultiplexedObserver");
clientStreamObserver = mock(StreamObserver.class, "clientStreamObserver");
clientReadObserver = mock(ReadObserver.class, "clientReadObserver");
clientWriteObserver = mock(WriteObserver.class, "clientWriteObserver");
when(clientTransportObserver.onNewConnection(any(), any())).thenReturn(clientConnectionObserver);
lenient().when(clientConnectionObserver.connectionEstablished(any(ConnectionInfo.class))).thenReturn(clientDataObserver);
lenient().when(clientConnectionObserver.multiplexedConnectionEstablished(any(ConnectionInfo.class))).thenReturn(clientMultiplexedObserver);
lenient().when(clientMultiplexedObserver.onNewStream()).thenReturn(clientStreamObserver);
lenient().when(clientStreamObserver.streamEstablished()).thenReturn(clientDataObserver);
lenient().when(clientDataObserver.onNewRead()).thenReturn(clientReadObserver);
lenient().when(clientDataObserver.onNewWrite()).thenReturn(clientWriteObserver);
serverTransportObserver = mock(TransportObserver.class, "serverTransportObserver");
serverConnectionObserver = mock(ConnectionObserver.class, "serverConnectionObserver");
serverDataObserver = mock(DataObserver.class, "serverDataObserver");
serverMultiplexedObserver = mock(MultiplexedObserver.class, "serverMultiplexedObserver");
serverStreamObserver = mock(StreamObserver.class, "serverStreamObserver");
serverReadObserver = mock(ReadObserver.class, "serverReadObserver");
serverWriteObserver = mock(WriteObserver.class, "serverWriteObserver");
when(serverTransportObserver.onNewConnection(any(), any())).thenReturn(serverConnectionObserver);
lenient().when(serverConnectionObserver.connectionEstablished(any(ConnectionInfo.class))).thenReturn(serverDataObserver);
lenient().when(serverConnectionObserver.multiplexedConnectionEstablished(any(ConnectionInfo.class))).thenReturn(serverMultiplexedObserver);
lenient().when(serverMultiplexedObserver.onNewStream()).thenReturn(serverStreamObserver);
lenient().when(serverStreamObserver.streamEstablished()).thenReturn(serverDataObserver);
lenient().when(serverDataObserver.onNewRead()).thenReturn(serverReadObserver);
lenient().when(serverDataObserver.onNewWrite()).thenReturn(serverWriteObserver);
transportObserver(clientTransportObserver, serverTransportObserver);
setUp(CACHED, CACHED_SERVER);
}
use of io.servicetalk.transport.api.TransportObserver in project servicetalk by apple.
the class ConnectionFactoryFilterTest method testAppend.
@Test
void testAppend() throws Exception {
Deque<Integer> createOrder = new ArrayDeque<>();
Deque<Integer> connectOrder = new ArrayDeque<>();
class FactoryOrder implements ConnectionFactory<InetSocketAddress, ListenableAsyncCloseable> {
final int order;
ConnectionFactory<InetSocketAddress, ListenableAsyncCloseable> original;
FactoryOrder(int order, ConnectionFactory<InetSocketAddress, ListenableAsyncCloseable> original) {
this.order = order;
this.original = original;
}
@Override
public Single<ListenableAsyncCloseable> newConnection(final InetSocketAddress unused, @Nullable final TransportObserver observer) {
connectOrder.add(order);
return original.newConnection(unused, observer);
}
@Override
public Completable closeAsync() {
return Completable.completed();
}
@Override
public Completable onClose() {
return Completable.completed();
}
}
class FilterOrder implements ConnectionFactoryFilter<InetSocketAddress, ListenableAsyncCloseable> {
final int order;
FilterOrder(int order) {
this.order = order;
}
@Override
public ConnectionFactory<InetSocketAddress, ListenableAsyncCloseable> create(final ConnectionFactory<InetSocketAddress, ListenableAsyncCloseable> original) {
createOrder.add(order);
return new FactoryOrder(order, original);
}
}
FilterOrder first = new FilterOrder(1);
FilterOrder second = new FilterOrder(2);
ConnectionFactoryFilter<InetSocketAddress, ListenableAsyncCloseable> combined = first.append(second);
ConnectionFactory<InetSocketAddress, ListenableAsyncCloseable> root = new FactoryOrder(999, new ConnectionFactory<InetSocketAddress, ListenableAsyncCloseable>() {
@Override
public Single<ListenableAsyncCloseable> newConnection(final InetSocketAddress unused, @Nullable final TransportObserver observer) {
return Single.succeeded(DUMMY_CLOSABLE);
}
@Override
public Completable onClose() {
return Completable.completed();
}
@Override
public Completable closeAsync() {
return Completable.completed();
}
});
ConnectionFactory<InetSocketAddress, ListenableAsyncCloseable> factory = combined.create(root);
ListenableAsyncCloseable connection = factory.newConnection(mock(InetSocketAddress.class), null).toFuture().get();
assertThat(connection, is(sameInstance(DUMMY_CLOSABLE)));
assertThat(createOrder, is(hasSize(2)));
assertThat(createOrder, is(containsInRelativeOrder(2, 1)));
assertThat(connectOrder, is(hasSize(3)));
assertThat(connectOrder, is(containsInRelativeOrder(1, 2, 999)));
}
use of io.servicetalk.transport.api.TransportObserver in project servicetalk by apple.
the class RetryRequestWithNonRepeatablePayloadTest method setUp.
private void setUp(HttpProtocol protocol, TestPublisher<Buffer> payloadBody, Queue<Throwable> errors, boolean offloading) {
protocol(protocol.config);
ChannelOutboundHandler firstWriteHandler = new FailingFirstWriteHandler();
connectionFactoryFilter(ConnectionFactoryFilter.withStrategy(factory -> new DelegatingConnectionFactory<InetSocketAddress, FilterableStreamingHttpConnection>(factory) {
@Override
public Single<FilterableStreamingHttpConnection> newConnection(InetSocketAddress address, @Nullable TransportObserver observer) {
return delegate().newConnection(address, observer).map(c -> {
final Channel channel = ((NettyConnectionContext) c.connectionContext()).nettyChannel();
if (protocol == HTTP_1) {
// Insert right before HttpResponseDecoder to avoid seeing failed frames on wire logs
channel.pipeline().addBefore(HttpRequestEncoder.class.getSimpleName() + "#0", null, firstWriteHandler);
} else if (protocol == HTTP_2) {
// Insert right before Http2MultiplexHandler to avoid failing connection-level frames and
// seeing failed stream frames on frame/wire logs
channel.pipeline().addBefore(Http2MultiplexHandler.class.getSimpleName() + "#0", null, firstWriteHandler);
}
return new StreamingHttpConnectionFilter(c) {
@Override
public Single<StreamingHttpResponse> request(StreamingHttpRequest request) {
return delegate().request(request).whenOnError(t -> {
try {
assertThat("Unexpected exception type", t, instanceOf(RetryableException.class));
assertThat("Unexpected exception type", t.getCause(), instanceOf(DeliberateException.class));
assertThat("Unexpected subscribe to payload body", payloadBody.isSubscribed(), is(false));
} catch (Throwable error) {
errors.add(error);
}
});
}
};
});
}
}, ExecutionStrategy.offloadNone()));
setUp(offloading ? CACHED : IMMEDIATE, offloading ? CACHED_SERVER : IMMEDIATE);
}
use of io.servicetalk.transport.api.TransportObserver in project servicetalk by apple.
the class AbstractNettyHttpServerTest method startServer.
private void startServer() throws Exception {
final InetSocketAddress bindAddress = localAddress(0);
service(new TestServiceStreaming(publisherSupplier));
// A small SNDBUF is needed to test that the server defers closing the connection until writes are complete.
// However, if it is too small, tests that expect certain chunks of data will see those chunks broken up
// differently.
final HttpServerBuilder serverBuilder = HttpServers.forAddress(bindAddress).executor(serverExecutor).socketOption(StandardSocketOptions.SO_SNDBUF, 100).protocols(protocol).transportObserver(serverTransportObserver).enableWireLogging("servicetalk-tests-wire-logger", TRACE, () -> true);
configureServerBuilder(serverBuilder);
if (sslEnabled) {
serverBuilder.sslConfig(new ServerSslConfigBuilder(DefaultTestCerts::loadServerPem, DefaultTestCerts::loadServerKey).build());
}
if (nonOffloadingServiceFilterFactory != null) {
serverBuilder.appendNonOffloadingServiceFilter(nonOffloadingServiceFilterFactory);
}
if (serviceFilterFactory != null) {
serverBuilder.appendServiceFilter(serviceFilterFactory);
}
if (serverLifecycleObserver != NoopHttpLifecycleObserver.INSTANCE) {
serverBuilder.lifecycleObserver(serverLifecycleObserver);
}
serverContext = awaitIndefinitelyNonNull(listen(serverBuilder.ioExecutor(serverIoExecutor).appendConnectionAcceptorFilter(original -> new DelegatingConnectionAcceptor(connectionAcceptor))).beforeOnSuccess(ctx -> LOGGER.debug("Server started on {}.", ctx.listenAddress())).beforeOnError(throwable -> LOGGER.debug("Failed starting server on {}.", bindAddress)));
final SingleAddressHttpClientBuilder<HostAndPort, InetSocketAddress> clientBuilder = newClientBuilder();
if (sslEnabled) {
clientBuilder.sslConfig(new ClientSslConfigBuilder(DefaultTestCerts::loadServerCAPem).peerHost(serverPemHostname()).build());
}
if (connectionFactoryFilter != null) {
clientBuilder.appendConnectionFactoryFilter(connectionFactoryFilter);
}
if (connectionFilterFactory != null) {
clientBuilder.appendConnectionFilter(connectionFilterFactory);
}
if (clientTransportObserver != NoopTransportObserver.INSTANCE) {
clientBuilder.appendConnectionFactoryFilter(new TransportObserverConnectionFactoryFilter<>(clientTransportObserver));
}
if (clientLifecycleObserver != NoopHttpLifecycleObserver.INSTANCE) {
clientBuilder.appendClientFilter(new HttpLifecycleObserverRequesterFilter(clientLifecycleObserver));
}
if (clientFilterFactory != null) {
clientBuilder.appendClientFilter(clientFilterFactory);
}
httpClient = clientBuilder.ioExecutor(clientIoExecutor).executor(clientExecutor).executionStrategy(defaultStrategy()).protocols(protocol).enableWireLogging("servicetalk-tests-wire-logger", TRACE, Boolean.TRUE::booleanValue).buildStreaming();
httpConnection = httpClient.reserveConnection(httpClient.get("/")).toFuture().get();
}
use of io.servicetalk.transport.api.TransportObserver in project servicetalk by apple.
the class ConnectionFactoryOffloadingTest method testFactoryOffloading.
@ParameterizedTest(name = "offload={0} httpStrategy={1}")
@MethodSource("testCases")
void testFactoryOffloading(boolean offload, HttpExecutionStrategy httpStrategy) throws Exception {
AtomicReference<Thread> factoryThread = new AtomicReference<>();
Thread appThread = Thread.currentThread();
try (ServerContext server = HttpServers.forPort(0).listenAndAwait(this::helloWorld)) {
SocketAddress serverAddress = server.listenAddress();
ConnectionFactoryFilter<SocketAddress, FilterableStreamingHttpConnection> factory = ConnectionFactoryFilter.withStrategy(original -> new ConnectionFactory<SocketAddress, FilterableStreamingHttpConnection>() {
private final ListenableAsyncCloseable close = emptyAsyncCloseable();
@Override
public Single<FilterableStreamingHttpConnection> newConnection(final SocketAddress socketAddress, @Nullable final TransportObserver observer) {
factoryThread.set(Thread.currentThread());
return original.newConnection(socketAddress, observer);
}
@Override
public Completable onClose() {
return close.onClose();
}
@Override
public Completable closeAsync() {
return close.closeAsync();
}
@Override
public Completable closeAsyncGracefully() {
return close.closeAsyncGracefully();
}
}, new ConnectAndHttpExecutionStrategy(offload ? ConnectExecutionStrategy.offloadAll() : ConnectExecutionStrategy.offloadNone(), httpStrategy));
try (HttpClient client = HttpClients.forResolvedAddress(serverAddress).appendConnectionFactoryFilter(factory).build()) {
assertThat(client.executionContext().executionStrategy().missing(httpStrategy), is(HttpExecutionStrategies.offloadNone()));
Single<HttpResponse> single = client.request(client.get("/sayHello"));
HttpResponse response = single.toFuture().get();
assertThat("unexpected status", response.status(), is(HttpResponseStatus.OK));
}
}
assertTrue((offload && !IoThreadFactory.IoThread.isIoThread(factoryThread.get())) || (!offload && factoryThread.get() == appThread), "incorrect offloading, offload=" + offload + " thread=" + factoryThread.get());
}
Aggregations