From 1108edc3037508bc304832c4e2a44641f92e632b Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Wed, 21 Feb 2024 19:04:32 +0530 Subject: [PATCH] DownloadWorkerUtil: Cancel all failed downloads on init WorkManager downloads can fail due to n number of reason. Regardless of the reason there might be not enough time to mark the download as failed within the worker causing the download to keep the status as downloading on next startup, thus blocking the queue. Always check for downloads with downloading status on init and cancel them if work manager cannot find atleast one ongoing work for it. Signed-off-by: Aayush Gupta --- .../aurora/store/util/DownloadWorkerUtil.kt | 52 ++++++++++++------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/com/aurora/store/util/DownloadWorkerUtil.kt b/app/src/main/java/com/aurora/store/util/DownloadWorkerUtil.kt index 9685ff524..12c4cfabf 100644 --- a/app/src/main/java/com/aurora/store/util/DownloadWorkerUtil.kt +++ b/app/src/main/java/com/aurora/store/util/DownloadWorkerUtil.kt @@ -50,29 +50,35 @@ class DownloadWorkerUtil @Inject constructor( private val TAG = DownloadWorkerUtil::class.java.simpleName fun init() { - // Run cleanup for last finished download and drop it database GlobalScope.launch { - downloadDao.downloads() - .collectLatest { list -> - // Check and trigger next download in queue, if any - if (!list.any { it.downloadStatus == DownloadStatus.DOWNLOADING }) { - val enqueuedDownloads = list.filter { it.downloadStatus == DownloadStatus.QUEUED } - enqueuedDownloads.firstOrNull()?.let { - try { - if (context.isIgnoringBatteryOptimizations() || CommonUtil.inForeground()) { - Log.i(DOWNLOAD_WORKER, "Downloading ${it.packageName}") - trigger(it) - } else { - Log.i(TAG, "Not in foreground or ignoring battery optimization") - cancel() - } - } catch (exception: Exception) { - Log.i(DOWNLOAD_WORKER, "Failed to download app", exception) - downloadDao.delete(it.packageName) + cancelFailedDownloads(downloadDao.downloads().firstOrNull() ?: emptyList()) + }.invokeOnCompletion { + observeDownloads() + } + } + + private fun observeDownloads() { + GlobalScope.launch { + downloadDao.downloads().collectLatest { list -> + // Check and trigger next download in queue, if any + if (!list.any { it.downloadStatus == DownloadStatus.DOWNLOADING }) { + val enqueuedDownloads = list.filter { it.downloadStatus == DownloadStatus.QUEUED } + enqueuedDownloads.firstOrNull()?.let { + try { + if (context.isIgnoringBatteryOptimizations() || CommonUtil.inForeground()) { + Log.i(DOWNLOAD_WORKER, "Downloading ${it.packageName}") + trigger(it) + } else { + Log.i(TAG, "Not in foreground or ignoring battery optimization") + cancel() } + } catch (exception: Exception) { + Log.i(DOWNLOAD_WORKER, "Failed to download app", exception) + downloadDao.delete(it.packageName) } } } + } } } @@ -118,6 +124,16 @@ class DownloadWorkerUtil @Inject constructor( .cancelAllWorkByTag(if (updatesOnly) DOWNLOAD_UPDATE else DOWNLOAD_APP) } + private suspend fun cancelFailedDownloads(downloadList: List) { + val workManager = WorkManager.getInstance(context) + + downloadList.filter { it.isRunning }.forEach { + workManager.getWorkInfosByTagFlow("$PACKAGE_NAME:${it.packageName}").firstOrNull() + ?.all { workInfo -> workInfo.state.isFinished } + ?.run { downloadDao.updateStatus(it.packageName, DownloadStatus.CANCELLED) } + } + } + private fun trigger(download: Download) { val inputData = Data.Builder() .putString(DOWNLOAD_DATA, gson.toJson(download))