On the JVM, what's the preferred way to "find and ...
# coroutines
d
On the JVM, what's the preferred way to "find and select a coroutine scope" from a top-level function that isn't
main
? e.g., when implementing
com.github.ajalt.clikt.core.CoreCliktCommand#run
? You can't
Copy code
CoroutineScope().launch {
...
}
as there's nothing to stop the process from exiting and the container from shutting down before it does anything (there's no containing scope). You can't call
join
on that bc there's no suspend context. I've been wantonly using
runBlocking
but I know that's not the preferred pattern. What I don't grok is what is the preferred pattern? (NOTE, this is a long-running headless batch service; so, there's no UI so
MainScope
makes no sense,
coroutineScope
is not allowed bc it's not a suspend context,
GlobalScope
has the same problem as
CoroutineScope()
, neither of these exist:
lifecycleScope, viewModelScope
)
k
run blocking is perfectly fine to use if you KNOW that the synchronous function being invoked won't be invoked from a coroutine. If your call stack looks something like: • run blocking • Click command • Main Then that's totally fine.
👍 1
👍🏾 1
s
Oh no, "find and select a coroutine scope" is one of my lines, isn't it 😄
In Ch3 of the book I have this tip: > Some frameworks, including Spring, Quarkus, and Micronaut, have special support for coroutines, and let you add the suspend modifier directly to your controller methods. Check the documentation for your chosen tool to see what options you have. I think Clikt is an example where this tip applies quite well: if I'm understanding the docs correctly, it looks like you can swap your
CoreCliktCommand
for a SuspendingCliktCommand. It has a suspending
run()
function, inside which you'd be able to use the
coroutineScope()
function.
thank you color 1
I agree with Kevin that
runBlocking
would also likely be okay in that specific scenario too, since this is essentially an entrypoint
j
You're right about Clikt. We use
SuspendingCliktCommand
in Amper so we have suspending entrypoints. You just have to make sure all of them are suspending, it's not possible to mix.
We used to use
runBlocking
when Clikt didn't have that, and I agree with Sam and Kevin that this is one of the rare cases where
runBlocking
is fine