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

julioromano

05/03/2021, 1:36 PM
Is there a way to keep track of the children Jobs launched within a given
CoroutineScope
? As if the
CoroutineScope
were a message queue and Jobs were messages in it: Would there be a way to track if the
CoroutineScope
is currently handling Jobs or is sitting idle? What I’m trying to accomplish: I’d like to build an idle/busy signal (possibly as a
Flow<Boolean>
) that will tell me whether a
CoroutineScope
is currently running any coroutines or not.
e

Erik

05/03/2021, 1:57 PM
By convention every coroutine scope's context should contain a
Job
.
Job
has `children: Sequence<Job>`: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/children.html Maybe you can transform that sequence to a
Flow<Boolean>
? I haven't use that sequence ever, though, so I'm not sure how it behaves over time as children appear, start, complete, fail, cancel, etc.
j

julioromano

05/03/2021, 1:59 PM
Yeah that’s the main issue, using Job’s methods I can get a snapshot of the current situation but I won’t be notified of changes.
e

Erik

05/03/2021, 2:05 PM
You could take samples repeatedly over time.... but that's not nice. You could also implement your own coroutine scope that delegates all coroutine scope calls to an existing coroutine scope, but all started child jobs can be kept in a private collection maybe? And whenever a job is added to the collection, you can check if
jobs.any { it.isActive }
or
isCancelled
or
isCompleted
, and emit that into a
Flow<Boolean>
.
j

julioromano

05/03/2021, 2:15 PM
That’d be great if
launch()
was part of the
CoroutineScope
interface. But it’s an extension function 😞
l

louiscad

05/03/2021, 2:17 PM
@elizarov You have an interesting use case for implementing the
Job
interface, though there might be other ways to satisfy that with a dedicated API or changes.
e

Erik

05/03/2021, 2:29 PM
If only the
Job.children
property were a
Flow<Sequence<Job>>
(or a flow of some other iterable type, not sure why it must be a sequence).
🤔 1
l

louiscad

05/03/2021, 2:30 PM
I'd think it was for historical reasons, but I don't know if that's the only reason and if it could become a
Flow
with some compatibility for old code relying on the
Sequence
.
e

Erik

05/03/2021, 2:36 PM
A new property could be added and this one could go through a deprecation cycle, if the new property covers both old and new use cases
It would be a bit like
MutableSharedFlow.subscriptionCount: StateFlow<Int>
.
e

elizarov

05/03/2021, 3:34 PM
But why do you need this idle/busy signal? What are you ultimately trying to do?
j

julioromano

05/03/2021, 4:06 PM
But why do you need this idle/busy signal? What are you ultimately trying to do?
Would love to show a loading indicator in a UI that turns on whenever there are background jobs running. All background jobs are launched as children of a well known
CoroutineScope
.
e

Erik

05/03/2021, 4:11 PM
I'm heavily suspecting
viewModelScope
😉
j

julioromano

05/03/2021, 4:13 PM
I’m heavily suspecting 
viewModelScope
 😉
Nope, this is happening in a pure Kotlin KMM module (no Android, no JDK…)
e

elizarov

05/09/2021, 12:50 PM
Interesting use-case. Unfortunately, there is no stable API to get this done outside of
kotlinx.coroutines
. The Job APi that tracks new children (
attachChild
) is internal and is in state of flux. We can try designing some public API that would expose the information you need (essentially, it could be a
StateFlow
with a number of children), but that’s non-trivial either. Job is highly performance sensitive, so it’ll likely mean that we’ll have to design some separate “watchable job” subclass…. seems too much of an API surface.
What I’d suggest is to track it yourself via your own extensions. Just write your own wrapper to launch your background tasks that would also track how many were launched and how many were terminated via a
StateFlow
, which you can then observe for your “busy indicator”.
🙏 1
👍 1
5 Views