use of io.servicetalk.concurrent.api.Single in project servicetalk by apple.
the class ServiceTalkThreadContextMapTest method testAsyncExecution.
@Test
void testAsyncExecution() throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
try {
MDC.clear();
MDC.put("a", "1");
MDC.put("b", "2");
// human inspection as sanity check
logger.info("expected a=1 b=2");
Thread original = Thread.currentThread();
Single<String> single = new Single<String>() {
@Override
protected void handleSubscribe(Subscriber<? super String> singleSubscriber) {
executor.execute(() -> {
singleSubscriber.onSubscribe(IGNORE_CANCEL);
singleSubscriber.onSuccess("1");
});
}
}.map(v -> {
assertNotEquals(Thread.currentThread(), original);
assertEquals("1", MDC.get("a"));
assertEquals("2", MDC.get("b"));
MDC.put("b", "22");
return v;
}).beforeFinally(() -> {
// human inspection as sanity check
logger.info("expected a=1 b=22");
assertEquals("1", MDC.get("a"));
assertEquals("22", MDC.get("b"));
});
single.toFuture().get();
} finally {
executor.shutdown();
}
}
use of io.servicetalk.concurrent.api.Single in project servicetalk by apple.
the class H2PriorKnowledgeFeatureParityTest method serverThrowsFromHandler.
@ParameterizedTest(name = "{displayName} [{index}] client={0}, h2PriorKnowledge={1}")
@MethodSource("clientExecutors")
void serverThrowsFromHandler(HttpTestExecutionStrategy strategy, boolean h2PriorKnowledge) throws Exception {
setUp(strategy, h2PriorKnowledge);
InetSocketAddress serverAddress = bindHttpEchoServer(service -> new StreamingHttpServiceFilter(service) {
@Override
public Single<StreamingHttpResponse> handle(final HttpServiceContext ctx, final StreamingHttpRequest request, final StreamingHttpResponseFactory responseFactory) {
throw DELIBERATE_EXCEPTION;
}
}, null);
try (BlockingHttpClient client = forSingleAddress(HostAndPort.of(serverAddress)).protocols(h2PriorKnowledge ? h2Default() : h1Default()).executionStrategy(clientExecutionStrategy).buildBlocking()) {
HttpResponse response = client.request(client.get("/"));
assertThat(response.status(), is(INTERNAL_SERVER_ERROR));
assertThat(response.payloadBody(), equalTo(EMPTY_BUFFER));
}
}
use of io.servicetalk.concurrent.api.Single in project servicetalk by apple.
the class NettyPipelinedConnectionTest method multiThreadedWritesAllComplete.
@Test
void multiThreadedWritesAllComplete() throws Exception {
// Avoid using EmbeddedChannel because it is not thread safe. This test writes/reads from multiple threads.
@SuppressWarnings("unchecked") NettyConnection<Integer, Integer> connection = mock(NettyConnection.class);
Executor connectionExecutor = Executors.newCachedThreadExecutor();
try {
doAnswer((Answer<Completable>) invocation -> {
Publisher<Integer> writeStream = invocation.getArgument(0);
return writeStream.ignoreElements().concat(connectionExecutor.submit(() -> {
}));
}).when(connection).write(any(), any(), any());
doAnswer((Answer<Publisher<Integer>>) invocation -> connectionExecutor.submit(() -> {
}).concat(Publisher.from(1))).when(connection).read();
final int concurrentRequestCount = 300;
NettyPipelinedConnection<Integer, Integer> pipelinedConnection = new NettyPipelinedConnection<>(connection, concurrentRequestCount);
CyclicBarrier requestStartBarrier = new CyclicBarrier(concurrentRequestCount);
List<Future<Collection<Integer>>> futures = new ArrayList<>(concurrentRequestCount);
ExecutorService executor = new ThreadPoolExecutor(0, concurrentRequestCount, 1, SECONDS, new SynchronousQueue<>());
try {
for (int i = 0; i < concurrentRequestCount; ++i) {
final int finalI = i;
futures.add(executor.submit(() -> {
try {
requestStartBarrier.await();
} catch (Exception e) {
return Single.<Collection<Integer>>failed(new AssertionError("failure during request " + finalI, e)).toFuture().get();
}
return pipelinedConnection.write(Publisher.from(finalI)).toFuture().get();
}));
}
for (Future<Collection<Integer>> future : futures) {
assertThat(future.get(), hasSize(1));
}
} finally {
executor.shutdown();
}
} finally {
connectionExecutor.closeAsync().subscribe();
}
}
use of io.servicetalk.concurrent.api.Single in project servicetalk by apple.
the class ResponseTimeoutTest method setUp.
private void setUp(Duration clientTimeout, Duration serverTimeout) throws Exception {
ctx = forAddress(localAddress(0)).appendServiceFilter(new TimeoutHttpServiceFilter((req, ts) -> serverTimeout, true)).listenAndAwait((__, ___, factory) -> {
Single<HttpResponse> resp = Single.never();
serverResponses.add(resp);
return resp;
});
client = forSingleAddress(serverHostAndPort(ctx)).appendClientFilter(client -> new StreamingHttpClientFilter(client) {
@Override
protected Single<StreamingHttpResponse> request(final StreamingHttpRequester delegate, final StreamingHttpRequest request) {
return Single.succeeded(null).afterOnSubscribe(delayedClientCancels::add).concat(delegate().request(request).liftSync(target -> new Subscriber<StreamingHttpResponse>() {
@Override
public void onSubscribe(final Cancellable cancellable) {
target.onSubscribe(() -> {
delayedClientCancels.add(cancellable);
cancellable.cancel();
});
}
@Override
public void onSuccess(final StreamingHttpResponse result) {
ClientTerminationSignal signal = OK.equals(result.status()) ? new ClientTerminationSignal(target, result) : new ClientTerminationSignal(target, new HttpResponseStatusException(result.status()));
delayedClientTermination.add(signal);
target.onSuccess(result);
}
@Override
public void onError(final Throwable t) {
delayedClientTermination.add(new ClientTerminationSignal(target, t));
target.onError(t);
}
})).filter(Objects::nonNull).firstOrError().map(thing -> (StreamingHttpResponse) thing);
}
}).appendConnectionFactoryFilter(original -> new CountingConnectionFactory(original, connectionCount)).appendClientFilter(new TimeoutHttpRequesterFilter((req, ts) -> clientTimeout, true)).build();
}
use of io.servicetalk.concurrent.api.Single 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);
}
Aggregations