Hey all. We're evaluating some tech debt in our s...
# coroutines
m
Hey all. We're evaluating some tech debt in our stack, and I'd like to get some advice. When we first adopted coroutines, we got it very very wrong. One of our mis-steps was doing stuff like this:
Copy code
suspend fun doSomething():Flux<T>
ie., a Suspend function, that returns a reactive type. (Returning a
Flux<>
instead of a flow is a conscious choice, but
suspend
is a mis-step). We know we need to fix this, but this pattern is in heavy usage throughout the code. My question is: What are the negative impacts of this pattern? Is this likely to be causing any performance issues? Thx
s
The negative impacts aren’t specifically related to performance. When you call a suspending function, the expectation is that any asynchronous computations will be performed before the function returns. When you return a Flow, the expectation is that the asynchronous computations are performed upon collecting the flow. The problems with a suspend function that returns a flow are things like: • Callers always have to have suspend capability, even if they just wanted to pass the flow on to some other code without collecting it • It’s unclear when any suspending computation will actually happen, and what coroutine context it will have when it does • It can be unclear whether attempting to collect the flow more than once will behave differently from if you called the suspending function again to create a new flow
Luckily any suspending function that returns a flow can be trivially converted:
Copy code
fun getFlow() = flow {
    emitAll(getFlowFromSuspendingFunction())
}
e
a
suspend fun
with no suspend points shouldn't have a performance penalty at runtime (aside from the extra context passed through), as Kotlin skips creating the state machine when it is unnecessary
👍 2
so the negatives are mostly around the misleading API and what forces that has on the rest of your code
m
ok, thanks both - that's very helpful!