2

The following test method:

@Test
void testMe() {
    Flux.just(1, 2, 3, 4, 5)
            .map(this::saveInDb)
            .toStream().count();
}

int saveInDb(int element) {
    System.out.println(element + " successfully stored in DB.");
    return element;
}

prints always:

1 successfully stored in DB.
2 successfully stored in DB.
3 successfully stored in DB.
4 successfully stored in DB.
5 successfully stored in DB.

The question that I have: how to prevent any saving to DB when some particular element available in the Flux?

For example: I do not want to store anything to DB when element 5 exists in Flux.

Is it even possible to implement this requirement in a non-blocking fashion?

Martin Tarjányi
  • 8,863
  • 2
  • 31
  • 49
user471011
  • 7,104
  • 17
  • 69
  • 97
  • you can either filter https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Flux.html#filter-java.util.function.Predicate- or just have an `if-statement` in your `map` statement. – Toerktumlare Oct 04 '20 at 10:46

2 Answers2

0

It is only possible if you can fit the whole Flux into memory:

Flux.just(1, 2, 3, 4, 5)
    .collectList()
    .filter(items -> !items.contains(5))
    .flatMapIterable(x -> x)
    .map(this::saveInDb)

If the Flux can't fit into the memory you can:

  • buffer the Flux and check the presence only in the buffered subsets (this might not be right for your use case)
  • consume the Flux twice, first check the presence with a filter, if the item was not present then subscribe again (this obviously only works if the Flux is guaranteed to have the same output on both occasions)
Martin Tarjányi
  • 8,863
  • 2
  • 31
  • 49
  • you dont need to `collectList` https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Flux.html#filter-java.util.function.Predicate- – Toerktumlare Oct 04 '20 at 18:24
  • @ThomasAndolf, may I ask you to provide an example? – user471011 Oct 04 '20 at 18:47
  • an example? you just filter the flux, and then map. Why the collectList, and flatMapIterable? – Toerktumlare Oct 05 '20 at 06:48
  • 1
    @ThomasAndolf I think the original use case was to do ZERO processing if any element in the `Flux` matches the "predicate". `map`+`filter` can only prevent processing of _particular_ elements (the ones that don't match the filter) – Simon Baslé Oct 05 '20 at 08:02
0

The simplest way is to use takeUntil or takeWhile.

Also throwing dedicated exception with onErrorComplete might be an option:

    Flux.just(1, 2, 3, 4, 5)
    .map(val -> {
      if (val.equals(5)) {
        throw new RuntimeException("Stopping flux");
      }
      return val;
    })
    .map(this::saveInDb)
    .onErrorComplete(RuntimeException.class)
    .toStream()
    .count();

Just replace RuntimeException to something more specific.

Sergey Ch
  • 91
  • 1
  • 5