I am trying to make use of Kotlin coroutines
along with spring-data-r2dbc
(databaseClient
) in our next Spring Boot service.
I'm already familiar with both concepts but as we dug deeper into the details of implementation I started to ask myself this question.
In most examples I saw, every endpoint that returned some sort of collections, will return Flow instead when migrating to reactive approach.
While there was no other(non-blocking) way to do it with Mono
/Flux
, since we wanted to hand over the subscription to the engine(Webflux
), the situation is very different with Kotlin Flows
. Flow's terminal operations are suspending, which makes them intrinsically non-blocking.
That means I can terminate a Flow in a non-blocking way right when and where I get it, and proceed with a regular List
, for example.
Of course, there can be more complex scenarios with underlying hot publishers, reactive transports/protocols, etc., but in my case it's a very conventional service. The only reason we decided to use reactive approach is because it's IO-bound: for every API call, we will need to fetch data from multiple other services over HTTP/REST, then execute some database queries and then return the combined result.
So, the question is: does it make any sense to spatter Flow in multiple application layers(Controller, Service, Repository) if I can just reduce it to a regular List
on the spot, say, in Repository:
suspend fun findByEvent(id: String): List<MyEntity> =
databaseClient.execute(MY_QUERY)....all().asFlow().toList()
so that the rest of my application layers won't even know anything about Flow
(the entire chain of calls will remain suspendable anyway)?