dimsuz
11/28/2022, 1:24 PMJob
's ?
fun allJobs(): Job {
val job1: Job
val job2: Job
val job3: Job
return combine(job1, job2, job3) // HOW?
}
fun main() {
allJobs().cancel() // cancels all 3 jobs
}
Is it possible or do I have to use some pattern which is similar to this?Sam
11/28/2022, 1:28 PMSam
11/28/2022, 1:30 PMSam
11/28/2022, 1:35 PMfun Iterable<Job>.cancelAll() = forEach(Job::cancel)
bezrukov
11/28/2022, 1:40 PMreturn scope.launch { // scope here is up to you
job1.join()
job2.join()
job3.join()
}
But note, cancelling that job won't cancel the "children" because they're not children.
For that purpose in our codebase we have Job.joinOrCancel function that allows you to "attach" job from another Job tree to your current execution context:
suspend fun Job.joinOrCancel() {
try {
join()
} catch (e: CancellationException) {
withContext(NonCancellable) {
cancelAndJoin()
}
}
}
Similarly it can be done for Iterable<Job>
, then you can do what I initially suggested:
scope.launch {
listOf(job1, job2, job3).joinOrCancel()
}
But overall, these tricks are hacky, so as @Sam said, try to properly structure your jobs firstdimsuz
11/28/2022, 1:49 PMJob
instance, i.e. in my example I couldn't do this:
fun allJobs(): Job = listOf(job1,job2,job3).forEach(::cancel())
because this wouldn't return a new Jobdimsuz
11/28/2022, 1:50 PMdimsuz
11/28/2022, 1:50 PMSam
11/28/2022, 1:51 PMreturn Job().also { j -> j.invokeOnCompletion { e -> otherJobs.forEach { it.cancel(e) } } }
dimsuz
11/28/2022, 1:51 PMdimsuz
11/28/2022, 1:52 PMJoffrey
11/28/2022, 2:41 PMdimsuz
11/28/2022, 6:34 PMgildor
11/29/2022, 9:36 AMdimsuz
11/29/2022, 12:22 PMdimsuz
11/29/2022, 12:23 PMgildor
11/30/2022, 2:07 AMyou allow an api user to combine downloads into groups and cancelling them as oneIt looks as a very broad task, but my first idea is do not expose Job at all and expose specialised API for user, not allow to mangle with low level stuff like job
dimsuz
12/01/2022, 3:52 PMgildor
12/02/2022, 7:31 AM