Skip to content

Commit

Permalink
Chunked the extension install job in case too many extensions are bei…
Browse files Browse the repository at this point in the history
…ng updated at once

The limit is around 62 extensions, but to be safe it runs 32 per job (which jobs still update 3 at a time)

Closes #1584
  • Loading branch information
Jays2Kings committed Jul 31, 2023
1 parent 2e78af9 commit 51d4f80
Showing 1 changed file with 33 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import androidx.work.ForegroundInfo
import androidx.work.NetworkType
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.OutOfQuotaPolicy
import androidx.work.WorkInfo
import androidx.work.WorkManager
import androidx.work.WorkerParameters
import androidx.work.workDataOf
Expand All @@ -33,6 +34,7 @@ import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withPermit
import kotlinx.coroutines.withContext
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
Expand Down Expand Up @@ -136,11 +138,20 @@ class ExtensionInstallerJob(val context: Context, workerParams: WorkerParameters

activeInstalls.forEach { extensionManager.cleanUpInstallation(it) }
activeInstalls.clear()
extensionManager.emitToInstaller("Finished", (InstallStep.Installed to null))
val hasChain = withContext(Dispatchers.IO) {
WorkManager.getInstance(context).getWorkInfosByTag(TAG).get().any {
it.state == WorkInfo.State.BLOCKED
}
}
if (!hasChain) {
extensionManager.emitToInstaller("Finished", (InstallStep.Installed to null))
}
if (instance?.get() == this) {
instance = null
}
context.notificationManager.cancel(Notifications.ID_EXTENSION_PROGRESS)
if (!hasChain) {
context.notificationManager.cancel(Notifications.ID_EXTENSION_PROGRESS)
}
return Result.success()
}

Expand All @@ -160,27 +171,33 @@ class ExtensionInstallerJob(val context: Context, workerParams: WorkerParameters
}

fun startJob(context: Context, info: List<ExtensionManager.ExtensionInfo>, showUpdatedExtension: Int = -1) {
val json = Json.encodeToString(info.toTypedArray())
val request = OneTimeWorkRequestBuilder<ExtensionInstallerJob>()
.addTag(TAG)
.setInputData(
workDataOf(
KEY_EXTENSION to json,
KEY_SHOW_UPDATED to showUpdatedExtension,
),
)
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
.build()
WorkManager.getInstance(context)
.enqueueUniqueWork(TAG, ExistingWorkPolicy.REPLACE, request)
// chunked to satisfy input limits
val requests = info.chunked(32).map {
OneTimeWorkRequestBuilder<ExtensionInstallerJob>()
.addTag(TAG)
.setInputData(
workDataOf(
KEY_EXTENSION to Json.encodeToString(it.toTypedArray()),
KEY_SHOW_UPDATED to showUpdatedExtension,
),
)
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
.build()
}
var workContinuation = WorkManager.getInstance(context)
.beginUniqueWork(TAG, ExistingWorkPolicy.REPLACE, requests.first())
for (i in 1 until requests.size) {
workContinuation = workContinuation.then(requests[i])
}
workContinuation.enqueue()
}

fun activeInstalls(): List<String>? = instance?.get()?.activeInstalls
fun removeActiveInstall(pkgName: String) = instance?.get()?.activeInstalls?.remove(pkgName)

fun stop(context: Context) {
instance?.get()?.job?.cancel()
WorkManager.getInstance(context).cancelUniqueWork(TAG)
WorkManager.getInstance(context).cancelAllWorkByTag(TAG)
}

fun isRunning(context: Context) = WorkManager.getInstance(context).jobIsRunning(TAG)
Expand Down

0 comments on commit 51d4f80

Please sign in to comment.