gotoOla
06/25/2020, 2:15 PMQueueReader : CoroutineScope by CoroutineScope(<http://Dispatchers.IO|Dispatchers.IO>) { abstract fun processMessage(msg: Message) }
and then I have an implementation
RabbitQueueReader: QueueReader { override processMessage(msg: Message) { // do the work } }
shouldn't my RabbitQueueReader here also utilize the IO dispatcher? In my logs it seems that it is the default dispatcher that is used in the processMessage functionprivate fun CoroutineScope.launchMessageProcessor() = launch {
for(messages in internalChannel) {
messages.map.async { processMessage(it) }
}
}
Channel<List<Message>>
Zach Klippenstein (he/him) [MOD]
06/25/2020, 2:22 PMCoroutineScope
directly is considered a bad practice, better to have a private val store the scope and reference it explicitly. Which init function is launchMessageProcessor
invoked from? And you’re not using the result from messages.map.async
, so that should be launch
as well.gotoOla
06/25/2020, 2:29 PMCoroutineScope by CoroutineScope(<http://Dispatchers.IO|Dispatchers.IO>)
launch
or async
that would be the coroutinescope (and the dispatcher) that is used (the fact that I could omit the GlobalScope.-prefix also made me feel that I "had" the expected IO-scope there)laucnhMessageProcessor
is called from a start-function that lies within the QueueReader
,
// Code in QueueReader
fun start(runForever: Boolean = true) {
val processors = (1..numberOfProcessors).map {
<http://logger.info|logger.info>("Starting processing channel.")
launchMessageProcessor()
}
)
}
and then that is invoked from my RabbitQueueReaderZach Klippenstein (he/him) [MOD]
06/25/2020, 2:35 PMclass YourClass : CoroutineScope
, instead do
class YourClass {
private val scope: CoroutineScope
gotoOla
06/25/2020, 2:38 PM14:27:16.188 [DefaultDispatcher-worker-2]
Evan R.
06/25/2020, 2:52 PMThis dispatcher shares threads with a Default dispatcher, so using withContext(<http://Dispatchers.IO|Dispatchers.IO>) { ... } does not lead to an actual switching to another thread — typically execution continues in the same thread.
It is likely running on the IO dispatcher, but you’re seeing the default dispatcher’s name there because they both use the same threadpool.
The difference between Dispatchers.Default and Dispatchers.IO is that Dispatchers.IO is designed for long-running, blocking tasks and will spin up new threads if there are not enough threads in the pool. Dispatchers.Default has a fixed number of threads equal to the number of CPU cores on your machine, or at least two.uli
06/25/2020, 3:01 PMinit
is generally dangerous! I guess your scope could have not yet been initialisedZach Klippenstein (he/him) [MOD]
06/25/2020, 3:03 PMQueueReader
needs to use a CoroutineScope
internally is a private implementation detail of that class, but by implementing the interface you’re making it part of its public API.gotoOla
06/26/2020, 9:07 AMinit
-block but rather "an" init function (fun start()...) I think I was just thrown off by the log message as Evan R explainedBut now we've made it also uphold the contract of the CoroutineScope interface, opening up an entirely different world of functions.
I understand that in a ViewModel you wouldn't want to expose that but I might actually want my consumers (e.g. the classes who are extending this) to be aware that they are a CoroutineScope 🤔 hm... I'll put some more thought into this