0
votes

There's this concept of back-pressure on project reactor, which is transparent from developers. Want to understand how it really works.

Let's use the following code block

fun consumeMethod(data: Flux<String>) {
  data
    .flatMap { slowHttpCall(it) }
    .subscribe()
}

Is my understanding correct regarding the flow of execution:

  1. When we call subscribe(), it will request the publisher to send ALL of the data.
  2. Moving up to the flatMap, let's say it will request 32 elements to the publisher.
  3. The publisher then will send 32 elements
  4. Moving down to flatMap again, it will call slowHttpCall() for 32 elements without waiting until each http call to complete. So right now we have 32 ongoing http calls
  5. Let's stop here

At this point, will flatMap request more element from the publisher? Or will it wait until all 32 http calls to complete before requesting for more? Or will it wait until 1 complete and request 1? How much will it request and why?

Thank you

1

1 Answers

2
votes

It will NOT wait until all in progress HTTP calls are completed. It will request new items as some of the in-progress ones complete.

flatMap has an overloaded version which lets you define a concurrency parameter (by default 256) which puts a limit on how many inner publishers can be in progress at most. If the number of in-progress publishers is less than the defined limit then flatMap will request additional items from the source publisher.

Now, the request rate doesn't seem to be consistent. Most of the time flatMap requests items one by one, sometimes it requests more. Probably a Reactor developer can provide more insight on that.

You can check the behavior of your exact use case by using log operator:

Flux.range(1, 1000)
        .log()
        .flatMap { Mono.delay(Duration.ofMillis(Random.nextLong(1000, 3000))).thenReturn(it) }
        .log(null, Level.WARNING)
        .blockLast()

More on backpressure in this answer: https://stackoverflow.com/a/57298393/6051176