1

Say I have two Monos, one which resolves to Void/empty and the other producing an Integer, how can I execute both in parallel, and continue on as a Mono<Integer>. Specifically both of these Monos are results of WebClient requests. Only one of these produces a useful value, but both need to be successful to continue.

eg.

Mono<Void> a = sendSomeData();
Mono<Integer> b = getSomeNumber();

Mono<Integer> resultingStream = runConcurrentAndGetValue(a, b);

How would I write runConcurrentAndGetValue(a,b) ?

Initially I didn't need the value and was using Mono.when(a,b) and building off of the Mono<Void>. But now I need the value. I tried using Mono.zip(a,b).map(Tuple2::getT2) but then learned that zip will cancel b because a has a lower cardinality (0), and will end up with no item as a result.

I could use Mono.when(a).then(b) but I would really prefer to be able to execute these concurrently. What is the right operator/composition to use in this case?

Edit:

One option I can think of is just a hack to emit an unused value like:

Mono.zip(a.then(Mono.just("placeholder")), b).map(Tuple2::getT2)
rewolf
  • 5,561
  • 4
  • 40
  • 51
  • `zip` will return an empty mono if either of the monos passed in result in an empty mono. In your case `sendSomeData` always returns an empty mono causing the `map` to never be executed. – Michael McFadyen Oct 29 '20 at 20:32
  • @MichaelMcFadyen yeah, that's what I meant by the 'lower cardinality' bit. – rewolf Oct 29 '20 at 23:50
  • Partly related: https://stackoverflow.com/questions/48172582/is-it-possible-to-start-monos-in-parallel-and-aggregate-the-result – AlikElzin-kilaka Aug 29 '22 at 05:41

1 Answers1

0

You could use reactor.core.publisher.Flux#merge(Publisher<? extends I>...) method and take last element.

Mono<Integer> a = sendSomeData().then(Mono.empty);
Mono<Integer> b = getSomeNumber();


Mono<Integer> result = Flux.merge(a, b).last();
result.map(...);
Alexander Pankin
  • 3,787
  • 1
  • 13
  • 23
  • Yeah I was hoping that I could find a way to do this without casting, or changing `a`. Also, I think I'd have to use `mergeSequential` to be sure of the order if I want to use `last()`. – rewolf Oct 30 '20 at 14:39
  • If you are sure `a` is always empty, you shouldn't care about order. If you declare `a` as `Mono`, you still can return empty Mono there. In that case you always get one-element Flux and you can use `last()` to wait both Monos completion – Alexander Pankin Oct 30 '20 at 14:44