Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is `kotlinx.coroutines.withContext` safe to use with Spring WebFlux?

Imagine I have a Spring WebFlux controller implemented with Kotlin that looks something like this:

@RestController
@RequestMapping("/api/foo")
class MyController {
  @GetMapping
  suspend fun getFoo(): FooResource {
    return withContext(Dispatchers.IO) {
      // fetch some resource with some expensive blocking IO call
    }
  }
}

The way I understand WebFlux's concurrency model, there is only one thread available to handle requests, so if I for some reason can't avoid blocking IO calls, I need to somehow offload it to another thread. The kotlinx.coroutines.withContext helper supposedly does exactly that, with the IO dispatcher being specifically designed for such a use case.`I have seen this pattern at several blog posts, so it appears to be common wisdom.

However, [the documentation on Dispatchers.IO says:

This dispatcher shares threads with a Default dispatcher, so using withContext(Dispatchers.IO) { ... } does not lead to an actual switching to another thread — typically execution continues in the same thread. As a result of thread sharing, more than 64 (default parallelism) threads can be created (but not used) during operations over IO dispatcher.

So that leaves me wondering: If WebFlux only uses a single "main thread" for handling requests, and blocking IO might still happen in this thread even if I'm using withContext(Dispatchers.IO): Is this pattern safe to use, and if not, what else should I do?

like image 286
chris Avatar asked Oct 15 '22 20:10

chris


1 Answers

Yes it is safe, you understood withContext correctly.

The piece of doc that you mention here simply talks about an optimization for Dispatchers.IO when switching between IO and Default dispatchers (which avoids context switching).

Using withContext(Dispatchers.IO) from other threads than the Default/IO thread pool will correctly (and always) switch context to that IO thread pool, starting new threads as needed to handle the blocking IO, so this should be the way to go in your case.

like image 100
Joffrey Avatar answered Oct 20 '22 06:10

Joffrey