learningequality / kolibri-installer-android

Android wrapper for Kolibri.
MIT License
26 stars 22 forks source link

Manually update task status when task is cancelled or an Android exception occurs during its execution #203

Closed bjester closed 5 months ago

bjester commented 7 months ago

Observed behavior

When a task is cancelled by the Android system (interrupted) or perhaps if it fails with an exception on the Android side, the task could get into a state where it would have to wait for the next reconciliation to be properly handled within Kolibri. This may cause significant delays and the user may not realize why.

Errors and logs

2024-01-29 20:55:48.388  9506-9597  Kolibri.Fo...oundWorker org.learningequality.Kolibri         D  Stopping foreground remote task aa73f1bc-8393-4675-8070-d51e234cfdf6
2024-01-29 20:55:48.388  9506-9506  WM-Processor            org.learningequality.Kolibri         D  Processor aa73f1bc-8393-4675-8070-d51e234cfdf6 executed; reschedule = true
2024-01-29 20:55:48.388  9506-9506  WM-SystemJobService     org.learningequality.Kolibri         D  aa73f1bc-8393-4675-8070-d51e234cfdf6 executed on JobScheduler
2024-01-29 20:55:48.390  9506-9597  WM-Processor            org.learningequality.Kolibri         D  WorkerWrapper interrupted for aa73f1bc-8393-4675-8070-d51e234cfdf6
2024-01-29 20:55:48.391  9506-9597  WM-StopWorkRunnable     org.learningequality.Kolibri         D  StopWorkRunnable for aa73f1bc-8393-4675-8070-d51e234cfdf6; Processor.stopWork = true
2024-01-29 20:55:48.393  9506-9597  WM-WorkerWrapper        org.learningequality.Kolibri         I  Work [ id=aa73f1bc-8393-4675-8070-d51e234cfdf6, tags={ kolibri_job_type:kolibri.core.auth.tasks.soud_sync_processing, kolibri_job_long_running, kolibri_task_id:50, org.learningequality.Kolibri.ForegroundWorker } ] was cancelled
                                                                                                    java.util.concurrent.CancellationException: Task was cancelled.
                                                                                                        at androidx.work.impl.utils.futures.AbstractFuture.cancellationExceptionWithCause(AbstractFuture.java:1183)
                                                                                                        at androidx.work.impl.utils.futures.AbstractFuture.getDoneValue(AbstractFuture.java:513)
                                                                                                        at androidx.work.impl.utils.futures.AbstractFuture.get(AbstractFuture.java:474)
                                                                                                        at androidx.work.impl.WorkerWrapper$2.run(WorkerWrapper.java:316)
                                                                                                        at androidx.work.impl.utils.SerialExecutorImpl$Task.run(SerialExecutorImpl.java:96)
                                                                                                        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
                                                                                                        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
                                                                                                        at java.lang.Thread.run(Thread.java:784)
2024-01-29 20:55:48.393  9506-9597  WM-WorkerWrapper        org.learningequality.Kolibri         D  Work interrupted for Work [ id=aa73f1bc-8393-4675-8070-d51e234cfdf6, tags={ kolibri_job_type:kolibri.core.auth.tasks.soud_sync_processing, kolibri_job_long_running, kolibri_task_id:50, org.learningequality.Kolibri.ForegroundWorker } ]

Expected behavior

Since we already have code that implements reconciliation by writing directly to the job_storage.sqlite3 database, we can reuse that to make additional defensive handling that more swiftly reconciles tasks with Kolibri under specific circumstances:

1) When the worker's onStopped method is called: we're allowed to do synchronous operations in this method (ref, ref) 2) When the result from processing the task encounters an exception: this generally doesn't happen if the task fails within python, so this catches the Android side of it (ref)

User-facing consequences

Longer delays during task processing when edge cases occur

Context

Kolibri 0.16.0 on Android