hi folks, I'm facing the following problem: most o...
# coroutines
s
hi folks, I'm facing the following problem: most of my app is non-blocking (via Spring WebFlux), but I need to integrate one piece of the framework represented by a class that has non-suspend methods I need to override. In one of these methods, I need to access a piece of information that is stored in a "non-blocking context", i.e. something I'd access in a
suspend fun
with something like
GlobalContext.getContext().awaitSingle().informationINeed
. But I cannot write that code as-is in the method where it needs to run since the method is an override and doesn't have the
suspend
modifier. I was considering wrapping the code with `runBlocking`; is this the way to go or am I missing something?
r
The general tip to wrap blocking code on your suspend applications is to use
Copy code
suspend fun myWrapper() = withContext(<http://Dispatchers.IO|Dispatchers.IO>) {
   blockingCodeHere()
}
Most literature tends to point to that being the solution: https://kt.academy/article/cc-dispatchers (last two paragraphs of the IO dispatcher tackle that). If I understood you right, you have a blocker interface being implemented which you need to call from your suspending code. This way, the caller can wrap the overriden function. If you have a override fun, and you need to call suspend functions from within, I suppose you could reach for the runBlocking, indeed.
s
yeah it's the last case you mention I have, thanks đź‘Ť
c
about the last one: ensure the blocking functions from the interface are never called from other coroutines, otherwise you have two coroutine systems in the same callstack, and that does weird things with cancellation
As a rule of thumb, a coroutine should never call
runBlocking
, even transitively through a callchain that isn't suspending
s
@CLOVIS yeah I guess that’s the hunch I had that made me ask. In the meantime, I clarified my problem and I’m thinking: is there a way to obtain the context of a parent coroutine caller within a non-suspend function?
c
You could pass the
CoroutineScope
down as a regular argument, but you still wouldn't be able to
suspend
, just
launch
stuff in the parent's scope.
I guess you could pass the
CoroutineScope
down to the function, and use
runBlocking(parentScope)
, but honestly I'm not sure at all what it will do.
s
Eh unfortunately the call stack is on the framework side so I don’t have control of function signatures and calls. But the more I think about this, the more it tells me I’m doing something wrong with mixing blocking and non blocking
đź‘Ť 1
c
Does the framework really have to block? Wouldn't it be enough if it just
launch
'd?
But yes, this is one of the limitations of coroutines: the suspend mechanism requires control over the entire stacktrace.
s
Well I’m not sure there’s much point in answering that question, as I’m not in control of the chain of calls within Spring anyway. In theory the problem would be solved if I could “suspend” the function I need to use without breaking the override contract, but that’s also not possible
đź‘Ť 1
It’s also not coroutine code originally, but project reactor which gets conveniently wrapped in coroutines