use of io.servicetalk.concurrent.PublisherSource.Processor in project servicetalk by apple.
the class PublisherFlatMapMergeTest method mappedRecoverMakesProgress.
@Test
void mappedRecoverMakesProgress() throws Exception {
@SuppressWarnings("unchecked") Subscriber<Integer> mockSubscriber = mock(Subscriber.class);
CountDownLatch latchOnSubscribe = new CountDownLatch(1);
CountDownLatch latchOnError = new CountDownLatch(1);
AtomicReference<Throwable> causeRef = new AtomicReference<>();
BlockingQueue<Integer> results = new ArrayBlockingQueue<>(10);
doAnswer(a -> {
Subscription s = a.getArgument(0);
s.request(4);
latchOnSubscribe.countDown();
return null;
}).when(mockSubscriber).onSubscribe(any(Subscription.class));
doAnswer(a -> {
causeRef.set(a.getArgument(0));
latchOnError.countDown();
return null;
}).when(mockSubscriber).onError(any());
doAnswer(a -> {
results.add(a.getArgument(0));
throw DELIBERATE_EXCEPTION;
}).when(mockSubscriber).onNext(any());
Processor<Integer, Integer> processor = newPublisherProcessor();
toSource(fromSource(processor).flatMapMergeDelayError(i -> from(i + 10).onErrorResume(cause -> from(i + 20).concat(failed(cause))))).subscribe(mockSubscriber);
latchOnSubscribe.await();
processor.onNext(1);
assertThat(results.take(), is(11));
assertThat(results.take(), is(21));
assertThat(causeRef.get(), is(nullValue()));
processor.onComplete();
latchOnError.await();
final Throwable t = causeRef.get();
assertThat(t, is(DELIBERATE_EXCEPTION));
}
use of io.servicetalk.concurrent.PublisherSource.Processor in project servicetalk by apple.
the class PublisherConcatMapIterableTest method upstreamRecoverWithMakesProgress.
@Test
void upstreamRecoverWithMakesProgress() throws Exception {
@SuppressWarnings("unchecked") Subscriber<String> mockSubscriber = mock(Subscriber.class);
CountDownLatch latchOnSubscribe = new CountDownLatch(1);
CountDownLatch latchOnError = new CountDownLatch(1);
AtomicReference<Throwable> causeRef = new AtomicReference<>();
AtomicInteger nextCount = new AtomicInteger();
List<String> results = new ArrayList<>();
doAnswer(a -> {
Subscription s = a.getArgument(0);
s.request(Long.MAX_VALUE);
latchOnSubscribe.countDown();
return null;
}).when(mockSubscriber).onSubscribe(any(Subscription.class));
doAnswer(a -> {
causeRef.set(a.getArgument(0));
latchOnError.countDown();
return null;
}).when(mockSubscriber).onError(eq(DELIBERATE_EXCEPTION));
doAnswer(a -> {
results.add(a.getArgument(0));
if (nextCount.getAndIncrement() == 0) {
throw new DeliberateException();
}
// final exception
throw DELIBERATE_EXCEPTION;
}).when(mockSubscriber).onNext(any());
Processor<List<String>, List<String>> processor = newPublisherProcessor();
toSource(fromSource(processor).onErrorResume(cause -> {
if (cause != DELIBERATE_EXCEPTION) {
// recover!
return from(singletonList("two"));
}
return failed(cause);
}).flatMapConcatIterable(identity())).subscribe(mockSubscriber);
latchOnSubscribe.await();
processor.onNext(asList("one", "ignored!"));
latchOnError.await();
assertThat(results, contains("one", "two"));
assertThat(causeRef.get(), is(DELIBERATE_EXCEPTION));
}
use of io.servicetalk.concurrent.PublisherSource.Processor 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();
}
}
Aggregations