@Override public ListenableFuture<Void> connect(final TcpConnectionHandler<P> handler) { Assert.notNull(handler, "TcpConnectionHandler is required"); if (this.stopping) { return handleShuttingDownConnectFailure(handler); } Mono<Void> connectMono = this.tcpClient .handle(new ReactorNettyHandler(handler)) .connect() .doOnError(handler::afterConnectFailure) .then(); return new MonoToListenableFutureAdapter<>(connectMono); }
@Override public ListenableFuture<Void> connect(TcpConnectionHandler<P> handler, ReconnectStrategy strategy) { Assert.notNull(handler, "TcpConnectionHandler is required"); Assert.notNull(strategy, "ReconnectStrategy is required"); if (this.stopping) { return handleShuttingDownConnectFailure(handler); } // Report first connect to the ListenableFuture MonoProcessor<Void> connectMono = MonoProcessor.create(); this.tcpClient .handle(new ReactorNettyHandler(handler)) .connect() .doOnNext(updateConnectMono(connectMono)) .doOnError(updateConnectMono(connectMono)) .doOnError(handler::afterConnectFailure) // report all connect failures to the handler .flatMap(Connection::onDispose) // post-connect issues .retryWhen(reconnectFunction(strategy)) .repeatWhen(reconnectFunction(strategy)) .subscribe(); return new MonoToListenableFutureAdapter<>(connectMono); }
@Override public ListenableFuture<Void> connect(final TcpConnectionHandler<P> handler) { Assert.notNull(handler, "TcpConnectionHandler is required"); if (this.stopping) { return handleShuttingDownConnectFailure(handler); } Mono<Void> connectMono = this.tcpClient .handle(new ReactorNettyHandler(handler)) .connect() .doOnError(handler::afterConnectFailure) .then(); return new MonoToListenableFutureAdapter<>(connectMono); }
@Override public ListenableFuture<Void> connect(TcpConnectionHandler<P> handler, ReconnectStrategy strategy) { Assert.notNull(handler, "TcpConnectionHandler is required"); Assert.notNull(strategy, "ReconnectStrategy is required"); if (this.stopping) { return handleShuttingDownConnectFailure(handler); } // Report first connect to the ListenableFuture MonoProcessor<Void> connectMono = MonoProcessor.create(); this.tcpClient .handle(new ReactorNettyHandler(handler)) .connect() .doOnNext(updateConnectMono(connectMono)) .doOnError(updateConnectMono(connectMono)) .doOnError(handler::afterConnectFailure) // report all connect failures to the handler .flatMap(Connection::onDispose) // post-connect issues .retryWhen(reconnectFunction(strategy)) .repeatWhen(reconnectFunction(strategy)) .subscribe(); return new MonoToListenableFutureAdapter<>(connectMono); }
@Override public ListenableFuture<Void> connect(final TcpConnectionHandler<P> handler) { Assert.notNull(handler, "TcpConnectionHandler is required"); if (this.stopping) { return handleShuttingDownConnectFailure(handler); } Mono<Void> connectMono = this.tcpClient .handle(new ReactorNettyHandler(handler)) .connect() .doOnError(handler::afterConnectFailure) .then(); return new MonoToListenableFutureAdapter<>(connectMono); }
@Override public ListenableFuture<Void> connect(final TcpConnectionHandler<P> handler) { Assert.notNull(handler, "TcpConnectionHandler is required"); if (this.stopping) { return handleShuttingDownConnectFailure(handler); } Mono<Void> connectMono = this.tcpClient .handle(new ReactorNettyHandler(handler)) .connect() .doOnError(handler::afterConnectFailure) .then(); return new MonoToListenableFutureAdapter<>(connectMono); }
@Test public void testTcpClientWithInetSocketAddress() throws InterruptedException { final CountDownLatch latch = new CountDownLatch(1); TcpClient client = TcpClient.create().port(echoServerPort); Connection s = client.handle((in, out) -> { in.receive() .subscribe(d -> latch.countDown()); return out.sendString(Flux.just("Hello")) .neverComplete(); }) .wiretap(true) .connectNow(Duration.ofSeconds(5)); latch.await(5, TimeUnit.SECONDS); s.disposeNow(); assertThat("latch was counted down", latch.getCount(), is(0L)); }
final AtomicLong totalDelay = new AtomicLong(); client.handle((in, out) -> Mono.never()) .wiretap(true) .connect()
@Override public ListenableFuture<Void> connect(TcpConnectionHandler<P> handler, ReconnectStrategy strategy) { Assert.notNull(handler, "TcpConnectionHandler is required"); Assert.notNull(strategy, "ReconnectStrategy is required"); if (this.stopping) { return handleShuttingDownConnectFailure(handler); } // Report first connect to the ListenableFuture MonoProcessor<Void> connectMono = MonoProcessor.create(); this.tcpClient .handle(new ReactorNettyHandler(handler)) .connect() .doOnNext(updateConnectMono(connectMono)) .doOnError(updateConnectMono(connectMono)) .doOnError(handler::afterConnectFailure) // report all connect failures to the handler .flatMap(Connection::onDispose) // post-connect issues .retryWhen(reconnectFunction(strategy)) .repeatWhen(reconnectFunction(strategy)) .subscribe(); return new MonoToListenableFutureAdapter<>(connectMono); }
@Override public ListenableFuture<Void> connect(TcpConnectionHandler<P> handler, ReconnectStrategy strategy) { Assert.notNull(handler, "TcpConnectionHandler is required"); Assert.notNull(strategy, "ReconnectStrategy is required"); if (this.stopping) { return handleShuttingDownConnectFailure(handler); } // Report first connect to the ListenableFuture MonoProcessor<Void> connectMono = MonoProcessor.create(); this.tcpClient .handle(new ReactorNettyHandler(handler)) .connect() .doOnNext(updateConnectMono(connectMono)) .doOnError(updateConnectMono(connectMono)) .doOnError(handler::afterConnectFailure) // report all connect failures to the handler .flatMap(Connection::onDispose) // post-connect issues .retryWhen(reconnectFunction(strategy)) .repeatWhen(reconnectFunction(strategy)) .subscribe(); return new MonoToListenableFutureAdapter<>(connectMono); }
private void tcpClientHandlesLineFeedData(TcpClient client) throws InterruptedException { final int messages = 100; final CountDownLatch latch = new CountDownLatch(messages); final List<String> strings = new ArrayList<>(); Connection c = client.handle((in, out) -> out.sendString(Flux.range(1, messages) .map(i -> "Hello World!" + i + "\n") .subscribeOn(Schedulers.parallel())) .then( in.receive() .asString() .take(100) .flatMapIterable(s -> Arrays.asList(s.split("\\n"))) .doOnNext(s -> { strings.add(s); latch.countDown(); }).then()) ) .wiretap(true) .connectNow(Duration.ofSeconds(30)); System.out.println("Connected"); c.onDispose() .log() .block(Duration.ofSeconds(30)); assertTrue("Expected messages not received. Received " + strings.size() + " messages: " + strings, latch.await(15, TimeUnit.SECONDS)); assertEquals(messages, strings.size()); }
@Test public void writeIdleDoesNotFireWhileDataIsBeingSent() throws InterruptedException { final CountDownLatch latch = new CountDownLatch(1); long start = System.currentTimeMillis(); Connection client = TcpClient.create() .host("localhost") .port(echoServerPort) .handle((in, out) -> { System.out.println("hello"); out.withConnection(c -> c.onWriteIdle(500, latch::countDown)); List<Publisher<Void>> allWrites = new ArrayList<>(); for (int i = 0; i < 5; i++) { allWrites.add(out.sendString(Flux.just("a") .delayElements(Duration.ofMillis(750)))); } return Flux.merge(allWrites); }) .wiretap(true) .connectNow(); System.out.println("Started"); assertTrue(latch.await(5, TimeUnit.SECONDS)); long duration = System.currentTimeMillis() - start; assertThat(duration, is(greaterThanOrEqualTo(500L))); client.disposeNow(); }
@Ignore public void consumerSpecAssignsEventHandlers() throws InterruptedException { final CountDownLatch latch = new CountDownLatch(2); final CountDownLatch close = new CountDownLatch(1); final AtomicLong totalDelay = new AtomicLong(); final long start = System.currentTimeMillis(); TcpClient client = TcpClient.create() .host("localhost") .port(timeoutServerPort); Connection s = client.handle((in, out) -> { in.withConnection(c -> c.onDispose(close::countDown)); out.withConnection(c -> c.onWriteIdle(500, () -> { totalDelay.addAndGet(System.currentTimeMillis() - start); latch.countDown(); })); return Mono.delay(Duration.ofSeconds(3)) .then() .log(); }) .wiretap(true) .connectNow(); assertTrue("latch was counted down", latch.await(5, TimeUnit.SECONDS)); assertTrue("close was counted down", close.await(30, TimeUnit.SECONDS)); assertThat("totalDelay was >500ms", totalDelay.get(), greaterThanOrEqualTo(500L)); s.disposeNow(); }
@Test public void testTcpClient() throws InterruptedException { final CountDownLatch latch = new CountDownLatch(1); Connection client = TcpClient.create() .host("localhost") .port(echoServerPort) .handle((in, out) -> { in.receive() .log("conn") .subscribe(s -> latch.countDown()); return out.sendString(Flux.just("Hello World!")) .neverComplete(); }) .wiretap(true) .connectNow(); latch.await(30, TimeUnit.SECONDS); client.disposeNow(); assertThat("latch was counted down", latch.getCount(), is(0L)); }
@Test public void closingPromiseIsFulfilled() { TcpClient client = TcpClient.newConnection() .host("localhost") .port(abortServerPort); client.handle((in, out) -> Mono.empty()) .wiretap(true) .connectNow() .disposeNow(); }
@Test @Ignore public void readIdleDoesNotFireWhileDataIsBeingRead() throws InterruptedException, IOException { final CountDownLatch latch = new CountDownLatch(1); long start = System.currentTimeMillis(); TcpClient client = TcpClient.create() .port(heartbeatServerPort); Connection s = client.handle((in, out) -> { in.withConnection(c -> c.onReadIdle(500, latch::countDown)); return Flux.never(); }) .wiretap(true) .connectNow(); assertTrue(latch.await(15, TimeUnit.SECONDS)); heartbeatServer.close(); long duration = System.currentTimeMillis() - start; assertThat(duration, is(greaterThanOrEqualTo(500L))); s.disposeNow(); }
@Test public void connectionWillAttemptToReconnectWhenItIsDropped() throws InterruptedException { final CountDownLatch connectionLatch = new CountDownLatch(1); final CountDownLatch reconnectionLatch = new CountDownLatch(1); try { TcpClient tcpClient = TcpClient.newConnection() .host("localhost") .port(abortServerPort); Mono<? extends Connection> handler = tcpClient.handle((in, out) -> { System.out.println("Start"); connectionLatch.countDown(); in.receive() .subscribe(); return Flux.never(); }) .wiretap(true) .connect(); handler.log() .then(handler.doOnSuccess(s -> reconnectionLatch.countDown())) .block(Duration.ofSeconds(30)) .onDispose(); assertTrue("Initial connection is made", connectionLatch.await(5, TimeUnit.SECONDS)); assertTrue("A reconnect attempt was made", reconnectionLatch.await(5, TimeUnit.SECONDS)); } catch (AbortedException ise){ return; } }
@Test public void testIssue462() throws InterruptedException { final CountDownLatch countDownLatch = new CountDownLatch(1); DisposableServer server = TcpServer.create() .port(0) .handle((in, out) -> { in.receive() .log("channel") .subscribe(trip -> countDownLatch.countDown()); return Flux.never(); }) .wiretap(true) .bindNow(); assertNotNull(server); System.out.println("PORT +" + server.address() .getPort()); Connection client = TcpClient.create() .port(server.address() .getPort()) .handle((in, out) -> out.sendString(Flux.just("test"))) .wiretap(true) .connectNow(); assertNotNull(client); client.disposeNow(); server.disposeNow(); assertThat("Latch was counted down", countDownLatch.await(5, TimeUnit.SECONDS)); }
@Test public void exposesRemoteAddress() throws InterruptedException { final int port = SocketUtils.findAvailableTcpPort(); final CountDownLatch latch = new CountDownLatch(1); DisposableServer server = TcpServer.create() .port(port) .handle((in, out) -> { in.withConnection(c -> { InetSocketAddress addr = c.address(); assertNotNull("remote address is not null", addr.getAddress()); latch.countDown(); }); return Flux.never(); }) .wiretap(true) .bindNow(); assertNotNull(server); Connection client = TcpClient.create().port(port) .handle((in, out) -> out.sendString(Flux.just("Hello World!"))) .wiretap(true) .connectNow(); assertNotNull(client); assertTrue("Latch was counted down", latch.await(5, TimeUnit.SECONDS)); client.disposeNow(); server.disposeNow(); }
client.handle((in, out) -> out.sendString(Flux.just("Hello World!\n", "Hello 11!\n"))) .wiretap(true) .connectNow();