Unable to return value back to CoroutineWorker when an exception is thrown

57 views Asked by At

I'm having troubles using Coroutines in WorkManager. Here is the snippet of Worker class.

class ExampleWorker (context, workerParams) : CoroutineWorker(context, workerParams) {

   override suspend fun doWork(): Result = withContext(Dispatchers.IO) {
      //set foreground
      try {
          val result = provider.getMeResult()

          if(result.success) return@withContext Result.success
          else return@withContext Result.failure()
      } catch(e: Exception) {
          handleErrors()
          return@withContext Result.failure()
      } finally {
        //clean up tasks
      }
   }
}

Here is the getMeResult()

class Provider {
   private val resultState = State()
   private val exceptionHandler = CoroutineHandler { _, throwable -> 
       //set result state to failed
       resultState.status = FAILED
       resultState.code = someErrorCode
   }
   private val runScope = CoroutineScope(Dispatchers.Default + exceptionHandler)
   private val jobsList = mutableListOf<Job>()

   suspend fun getMeResult(): State {
       val runJob = runScope.launch {
          someLongRunningTask() // spits result out to a channel, say itemsChannel
       }
       itemsChannel.consumeEach {
          //spawn a new coroutine to run the job concurrently
          val job = runScope.launch {
             somebackgroundTask() //Point A
          }

          jobsList.add(job)
       }
       //wait for all jobs to complete
       jobsList.joinAll()
   }
   //wait parent coroutine to complete
   runJob?.join()

   //once you reach here, looks everything has worked. Update run state to complete 
   resultState.status = COMPLETE

   return resultState
}

Ideally, this works as expected and result status is returned. However, whenever an error is thrown from Point A, exception handler receives the error and getMeResult() returns COMPLETE value. Worker catch block is never invoked, no error code was set. How can I make this work so that the Worker gets failed status when an error occurs? Also, when I cancel runJob within exceptionHandler, it fires multiple CancellationException with root cause as the actual exception type, but that cause is always null if I catch it within the parent Coroutine.

Hope it makes sense.

0

There are 0 answers