https://kotlinlang.org logo
#coroutines
Title
# coroutines
d

dave08

03/10/2024, 11:39 AM
If I'm managing a library with both
suspend
and non suspend versions of an api (based on Lettuce Redis client's blocking and non blocking api), and I'd rather manage all the code in either one and adapt to the other, is there a major advantage to just keep them separate -- or is it better to manage the suspend version and use runBlocking as a bridge, or maybe just manage the blocking version and use
with(<http://Dispatchers.IO|Dispatchers.IO>)
to make it into the suspend version?
s

Sam

03/10/2024, 12:39 PM
I think it depends on how this Redis client is actually implemented. If their "non-blocking" client is just a wrapper around the blocking one, you might as well not use it and just call it via the IO dispatcher instead. On the other hand, if it's using true non-blocking IO under the hood, then there's an actual benefit to writing a proper suspending adapter for it.
A quick Google suggests it's a true non blocking client, so I'd recommend doing as much as you can with suspending functions and only blocking at the call site when you absolutely need to
d

dave08

03/10/2024, 12:43 PM
Does it make sense to manage a separate api for blocking calls then? Is calling runBlocking with a suspend version adding significant overhead?
s

Sam

03/10/2024, 12:51 PM
There's probably not much difference at all between using runBlocking and writing a blocking implementation that uses the blocking functions provided by the client itself 👍
☝️ 1
Both approaches will end up using the calling thread to run any code before and after the request, and then blocking the thread while the request is actually in flight
d

dave08

03/10/2024, 12:55 PM
And you're saying that the overhead would probably be negligable?
s

Sam

03/10/2024, 12:56 PM
Yes
👍🏼 1
j

Jacob

03/10/2024, 2:07 PM
I would avoid calling runBlocking from within a library project. Can lead to unexpected nested runBlockings in the client. Chatter I've seen is that nested runBlockings can be bad
💯 2
d

dave08

03/10/2024, 2:51 PM
Yeah, good point. Although it's a bit frustrating to have to manage two sets of almost the same code and have to write the same tests for both. I wish there would be some way out of this... I only really considered this in the first place because anyone using coroutines would just use the non blocking api and wouldn't nest the scopes, but I admit that there could always be funny cases that people actually do what's unexpected.
g

gildor

03/11/2024, 2:39 AM
What kind issue with nested runBlocking? Just curious about it
But I still would probably avoid runBlocking on library level and if such API exposed, I would expects that I use native blocking under the hood I would check if anyone actually using blocking API, because having wrappers for 2 apis look indeed as overkill, if nobody using it anyway
s

Sam

03/11/2024, 7:08 AM
Here's one way things can go wrong when using runBlocking inside an existing coroutine: https://betterprogramming.pub/how-i-fell-in-kotlins-runblocking-deadlock-trap-and-how-you-can-avoid-it-db9e7c4909f1
👌🏼 1
👍 1
d

dave08

03/11/2024, 10:34 AM
Yeah, well, we use both.. most of our microservice frameworks support coroutines, but some (like Keycloak when writing for their SPI...) don't. So I guess it's back to maintaining both then... 🙈, thanks!
g

gildor

03/11/2024, 10:37 AM
If it an internal library, I think it's also could be a meaningful tradeoff to use runBlocking, if it on the right area of the code (so it's unlikely will be used by coroutines code, but let's say blocking service implementation). After all, blocking main thread could cause deadlock without coroutines too, it's just a nature of mixing blocking with callbacks
d

dave08

03/11/2024, 10:45 AM
I just published it, but yeah, maybe in internal libraries it might be a better situation, although Sam has a good point that there's no indication in the function's declaration or anywhere else, so it might be something easy to forget, or when others in the company are using it, they might not be as careful.
g

gildor

03/11/2024, 10:47 AM
Yes, but for a public library it's fine to have coroutines only API, for internal, to support existing code, migrate to runBlocking in some places could be not the worst thing, considering that coroutines API forces everyone to use it
This is why I say that coroutine-bases library shouldn't provide blocking API which is just wrap of suspend functions with runBlocking
5 Views