@Override public Mono<Void> onClose() { return connection.onClose(); }
@Override public void dispose() { connection.dispose(); }
@Override public Flux<Frame> receive() { return delegate.receive().doOnNext(frameCounters); }
.send(sendProcessor) .doFinally(this::handleSendProcessorCancel) .subscribe(null, this::handleSendProcessorError); Disposable receiveDisposable = connection.receive().subscribe(this::handleFrame, errorConsumer); .onClose() .doFinally( s -> { String.format("No keep-alive acks for %d ms", keepAlive.getTimeoutMillis()); errorConsumer.accept(new ConnectionErrorException(message)); connection.dispose(); }); keepAliveHandler.send().subscribe(sendProcessor::onNext);
@DisplayName("does not fragment an already-fragmented frame") @Test void sendFragment() { Frame frame = toAbstractionLeakingFrame( DEFAULT, 1, createPayloadFrame(DEFAULT, true, true, (ByteBuf) null, null)); when(delegate.onClose()).thenReturn(Mono.never()); new FragmentationDuplexConnection(DEFAULT, delegate, 2).sendOne(frame.retain()); verify(delegate).send(publishers.capture()); StepVerifier.create(Flux.from(publishers.getValue())).expectNext(frame).verifyComplete(); }
@DisplayName("does not reassemble non fragmentable frame") @Test void reassembleNonFragmentableFrame() { Frame frame = toAbstractionLeakingFrame(DEFAULT, 1, createTestCancelFrame()); when(delegate.receive()).thenReturn(Flux.just(frame.retain())); when(delegate.onClose()).thenReturn(Mono.never()); new FragmentationDuplexConnection(DEFAULT, delegate, 2) .receive() .as(StepVerifier::create) .expectNext(frame) .verifyComplete(); }
@Override public ClientTransport get() { if (onClose.isDisposed()) { throw new IllegalStateException("WeightedClientTransportSupplier is closed"); } int i = selectCount.get(); return () -> clientTransportFunction .apply(socketAddress) .connect() .doOnNext( duplexConnection -> { logger.debug("opened connection to {} - active connections {}", socketAddress, i); Disposable onCloseDisposable = onClose.doFinally(s -> duplexConnection.dispose()).subscribe(); duplexConnection .onClose() .doFinally( s -> { int d = selectCount.decrementAndGet(); logger.debug( "closed connection {} - active connections {}", socketAddress, d); onCloseDisposable.dispose(); }) .subscribe(); errorPercentage.insert(1.0); }) .doOnError(t -> errorPercentage.insert(0.0)); }
/** * Sends a single {@code Frame} on this connection and returns the {@code Publisher} representing * the result of this send. * * @param frame {@code Frame} to send. * @return {@code Publisher} that completes when the frame is written on the connection * successfully and errors when it fails. */ default Mono<Void> sendOne(Frame frame) { return send(Mono.just(frame)); }
@Override public boolean isDisposed() { return connection.isDisposed(); }
@Override public double availability() { return source.availability(); } }
@Override public Mono<Void> sendOne(Frame frame) { if (debugEnabled) { LOGGER.debug("sending -> " + frame.toString()); } return source.sendOne(frame); }
connection.onClose().doFinally(signalType -> terminate()).subscribe(null, errorConsumer); .send(sendProcessor) .doFinally(this::handleSendProcessorCancel) .subscribe(null, this::handleSendProcessorError); connection.receive().subscribe(this::handleIncomingFrames, errorConsumer); lifecycle.setTerminationError(err); errorConsumer.accept(err); connection.dispose(); }); keepAliveHandler.send().subscribe(sendProcessor::onNext);
@DisplayName("does not fragment non-fragmentable frame") @Test void sendNonFragmentable() { Frame frame = toAbstractionLeakingFrame(DEFAULT, 1, createTestCancelFrame()); when(delegate.onClose()).thenReturn(Mono.never()); new FragmentationDuplexConnection(DEFAULT, delegate, 2).sendOne(frame.retain()); verify(delegate).send(publishers.capture()); StepVerifier.create(Flux.from(publishers.getValue())).expectNext(frame).verifyComplete(); }
@DisplayName("does not reassemble a non-fragment frame") @Test void reassembleNonFragment() { Frame frame = toAbstractionLeakingFrame( DEFAULT, 1, createPayloadFrame(DEFAULT, false, true, (ByteBuf) null, null)); when(delegate.receive()).thenReturn(Flux.just(frame.retain())); when(delegate.onClose()).thenReturn(Mono.never()); new FragmentationDuplexConnection(DEFAULT, delegate, 2) .receive() .as(StepVerifier::create) .expectNext(frame) .verifyComplete(); }
@Override public ClientTransport get() { if (onClose.isDisposed()) { throw new IllegalStateException("WeightedClientTransportSupplier is closed"); } int i = selectCount.get(); return () -> clientTransportFunction .apply(socketAddress) .connect() .doOnNext( duplexConnection -> { logger.debug("opened connection to {} - active connections {}", socketAddress, i); Disposable onCloseDisposable = onClose.doFinally(s -> duplexConnection.dispose()).subscribe(); duplexConnection .onClose() .doFinally( s -> { int d = selectCount.decrementAndGet(); logger.debug( "closed connection {} - active connections {}", socketAddress, d); onCloseDisposable.dispose(); }) .subscribe(); errorPercentage.insert(1.0); }) .doOnError(t -> errorPercentage.insert(0.0)); }
@Override public Mono<Void> send(Publisher<Frame> frames) { Objects.requireNonNull(frames, "frames must not be null"); return delegate.send(Flux.from(frames).doOnNext(frameCounters)); }
@Override default double availability() { return isDisposed() ? 0.0 : 1.0; } }
@Override public double availability() { return connection.availability(); }
errorConsumer); return connection.sendOne(setupFrame).thenReturn(wrappedRSocketClient); });
.send(sendProcessor) .doFinally(this::handleSendProcessorCancel) .subscribe(null, this::handleSendProcessorError); Disposable receiveDisposable = connection.receive().subscribe(this::handleFrame, errorConsumer); .onClose() .doFinally( s -> { String.format("No keep-alive acks for %d ms", keepAlive.getTimeoutMillis()); errorConsumer.accept(new ConnectionErrorException(message)); connection.dispose(); }); keepAliveHandler.send().subscribe(sendProcessor::onNext);