Gabriel Feo
01/18/2020, 7:30 PMGabriel Feo
01/18/2020, 7:30 PMAdam Powell
01/18/2020, 7:33 PMCoroutineScope
or if you can't do that because the function already has a receiver, accept a CoroutineScope
to launch into as a parameterRick Busarow
01/18/2020, 7:33 PMRick Busarow
01/18/2020, 7:34 PMGabriel Feo
01/18/2020, 8:57 PMCoroutineScope
on the class level? 😐Dico
01/19/2020, 10:40 AMThreadLocalContext
, set that to the coroutine context at launch and access the thread local from your function.Michael Friend
01/20/2020, 3:29 PMCoroutineScope
via a way someone else mentioned. Otherwise since the function isn’t a suspend
function you have no guarantee it was called inside a CoroutineScope
. Launching a coroutine in the caller’s scope is a side effect that may cause bugs when not denoted by either suspend
or a CoroutineScope
receiver/argumentAdam Powell
01/20/2020, 3:39 PMcallbackFlow
or suspendCancellableCoroutine
and keeping an implementation of the interface completely internal to another suspending abstraction you expose is a common pattern for this sort of thing. In that setup it's much easier to communicate from non-suspending code back into suspending code.Adam Powell
01/29/2020, 2:15 AMAdam Powell
01/29/2020, 2:17 AMAdam Powell
01/29/2020, 2:17 AMsuspend fun
and if a caller wants to block a thread for it, they can wrap it in their own runBlocking
Adam Powell
01/29/2020, 2:18 AMTask
API as your surface instead. Anything but blocking a thread on it.Gabriel Feo
01/29/2020, 2:26 AMGabriel Feo
01/29/2020, 2:26 AMrunBlocking
, calling it from a coroutine would block the current thread, it wouldn’t be able to suspend on it, did I get this right? That’s a good point.
I still need to find a way to keep this out of the domain layer interface though. The domain layer shouldn’t impose coroutines, from my point of view. This is an infrastructure concernAdam Powell
01/29/2020, 2:26 AMAdam Powell
01/29/2020, 2:27 AMrunBlocking
sets up a coroutine event loop on the calling thread; it basically means you have a coroutine dispatcher with only one thread - the caller of runBlocking
. It lets you time-share a single calling thread that way.Adam Powell
01/29/2020, 2:28 AMsuspend
APIs. That's kind of like saying that a domain layer shouldn't use abstract class
or extension functions or any other language featureGabriel Feo
01/29/2020, 2:31 AMsuspend
as a concurrency feature, a coroutines-specific feature, of which the domain layer (I’m thinking of the DDD pattern separating strict domain modeling from any infrastructure concerns). But it’s really a language feature, and it doesn’t actually impose anything on implementations, does it? 🤦🏻Gabriel Feo
01/29/2020, 2:32 AMAdam Powell
01/29/2020, 2:33 AMsuspend fun
itself, yes. You could make an argument about the kotlinx.coroutines
runtime library, but it's quite a small dependency and it's multiplatform; it's probably more practical to think of it as an extension to the kotlin stdlib. You wouldn't necessarily restrict using it in a domain layer any more than you'd restrict the use of List<T>
as a utility classAdam Powell
01/29/2020, 2:34 AMGabriel Feo
01/29/2020, 3:10 AMsuspend
! This is the simplest and most abstract part of coroutines. I actually had no problem other than perspective 😅Gabriel Feo
01/29/2020, 3:10 AM