package com.margelo.nitro.one import android.content.Context import androidx.work.Worker import androidx.work.WorkerParameters import java.util.concurrent.TimeUnit // runs One.BackgroundTasks work when WorkManager dispatches it. delivery // starts ReactHost and a Headless JS task without mounting an Activity. the // coordinator owns completion and expiration; a warm listener never replays // headless invocations, which would execute the same work twice. class OneBackgroundWorker( appContext: Context, params: WorkerParameters, ) : Worker(appContext, params) { @Volatile private var executionId: String? = null @Volatile private var finished = false override fun doWork(): Result { val identifier = inputData.getString(OneBackgroundTasksCoordinator.KEY_IDENTIFIER) ?: return Result.failure() val kindValue = inputData.getInt(OneBackgroundTasksCoordinator.KEY_KIND, 0) val kind = if (kindValue == BackgroundTaskKind.PROCESSING.value) { BackgroundTaskKind.PROCESSING } else { BackgroundTaskKind.REFRESH } if (isStopped) return Result.failure() val record = OneBackgroundTasksCoordinator.launch(identifier, kind, headless = true) executionId = record.executionId var headless: OneBackgroundTaskRuntime.Execution? = null try { headless = OneBackgroundTaskRuntime.start(applicationContext, record) if (isStopped) return Result.failure() // WorkManager stops workers past ~10 minutes; cap the wait below // it so expiration still reports through the coordinator. val completed = record.completion.await(9, TimeUnit.MINUTES) finished = true return if (completed && record.success && !isStopped) Result.success() else Result.failure() } catch (e: InterruptedException) { Thread.currentThread().interrupt() return Result.failure() } catch (e: Exception) { android.util.Log.e("OneBackgroundTasks", "headless execution failed", e) return Result.failure() } finally { finished = true OneBackgroundTasksCoordinator.expire(record.executionId) headless?.finish() } } override fun onStopped() { executionId?.let { id -> if (!finished) { finished = true OneBackgroundTasksCoordinator.expire(id) } } super.onStopped() } }