/** * Implements a bidirectional stream -> stream call as {@link Flux} -> {@link Flux}, where both the client * and the server independently stream to each other. */ public static <TRequest, TResponse> Flux<TResponse> manyToMany( Flux<TRequest> rxRequest, Function<StreamObserver<TResponse>, StreamObserver<TRequest>> delegate) { try { ReactorProducerConsumerStreamObserver<TRequest, TResponse> consumerStreamObserver = new ReactorProducerConsumerStreamObserver<>(rxRequest); delegate.apply(new CancellableStreamObserver<>(consumerStreamObserver, consumerStreamObserver::cancel)); consumerStreamObserver.rxSubscribe(); return ((Flux<TResponse>) consumerStreamObserver.getRxConsumer()) .transform(Operators.lift(new SubscribeOnlyOnceLifter<TResponse>())); } catch (Throwable throwable) { return Flux.error(throwable); } } }