On Android with AndroidX Work, there's the `Corout...
# coroutines
e
On Android with AndroidX Work, there's the
CoroutineWorker
that does work on a coroutine. This work can be cancelled by the system, it then throws a
CancellationException
. In my apps I want to log any exceptions that are thrown by the crucial part of my work, e.g.:
runCatching { crucialWork() }.onFailure { log(it) }
. However, I see a lot of
JobCancellationException
instances being logged with message
"Job was cancelled"
. I don't want to log regular cancellations without an exceptional cause. So, if I read the documentation of
Job
(https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html), am I right to conclude that I'm only interested in exceptions that are not of type
CancellationException
, or if I catch a
CancellationException
, then I'm only interested if its
cause
is not a
CancellationException
? In other words: I'm interested in 'failed' coroutines, not in 'normally cancelled' coroutines. So, what exceptions do I log, what do I ignore?
f
Use foreground workers to avoid lots of cancellations. You can catch different types of exceptions in different catch blocks.
Cancellation exception does not mean your operation is unsuccessful, but worker is cancelled due to some reason.
Last comment - If you setup a network connectivity policy which means your work needs data connection to complete the job, and it takes a some amount of time to finish the work (uploading photos and videos), make sure data saving plan is off for users and use foreground works all the time. Otherwise, you can expect lots of cancellations.
e
Thanks, but in short: this doesn't answer my question, because a foreground worker can also be cancelled, while my question is about what to log or not. Furthermore, my work really doesn't need to happen in the foreground so I'm fine with the many cancellations in the background. I just want it to happen some time, while knowing about failures.
f
if you are having cancellation exceptions, this is most likely workmanager cancels your job due to reason job does not satisfy a policy. I dont think you can obtain a root cause or etc. An exception in your code does not cancel it but get it failed.
z
Yes, to determine whether the job failed vs cancelled, you need to search up the cause chain to look for a non-
CancellationException
. E.g.
Copy code
catch (e: Throwable) {
  val realCause = generateSequence(e) { e.cause }
      .firstOrNull { it !is CancellationException }
      ?: throw e
  // process realCause
}
e
Thanks, that's what I made already, hoping that it was correct. Using a sequence is much more elegant though, nice one!
r
I did something similar. Yes you should just check for the type of CancellationException