Search code examples
kotlinreactor

Should parallel API call use Schedulers.parallel() or Schedulers.boundedElastic()


To be honest I have no idea how schedulers work in reactor. I have read few of them and this what I found.

Schedulers.parallel() is good for CPU-intensive but short-lived tasks. It can execute N such tasks in parallel (by default N == number of CPUs)

Schedulers.elastic() and Schedulers.boundedElastic() are good for more long-lived tasks (eg. blocking IO tasks). The elastic one spawns threads on-demand without a limit while the recently introduced boundedElastic does the same with a ceiling on the number of created threads.

So in my API calls there's a task where I have to poll request over and over again until its state is ready.

Flux.just(order1, order2)
    .parallel(4)
    .runOn(Schedulers.parallel())
    .flatMap { order -> createOrder(order) }
    .flatMap { orderId -> 
       pollConfirmOrderStatus(orderId)
          .retryWhen(notReady)
    }
    .collectList()
    .subscribe()

As you can see I use Schedulers.parallel() and it works fine, but I'm concerning about blocking CPU usage since my server doesn't have that much CPU cores. The pollConfirmOrderStatus takes about 1-2 minutes so I'm not sure if it would block other process in my server from accessing CPU. So should I use Schedulers.parallel() or Schedulers.bondedElastic() here.


Solution

  • If your method pollConfirmOrderStatus() doesn't block the parallel Scheduler's threads it should be fine. Otherwise then you might be blocking all the available thread in the parallel Scheduler, which might end up in a deadlock if your state never gets ready.

    Here, it explains that parallel scheduler is reserved for non-blocking calls, and that you can use BlockHound to spot blocking calls from non-blocking intended threads. https://spring.io/blog/2019/03/28/reactor-debugging-experience