What are the retry strategy/ mechanism for WorkManager's OneTimeWorkRequest
Asked Answered
U

3

29

I have the following one-time worker.

// Create a Constraints that defines when the task should run
Constraints constraints = new Constraints.Builder()
        .setRequiredNetworkType(NetworkType.UNMETERED)
        .setRequiresBatteryNotLow(true)
        // Many other constraints are available, see the
        // Constraints.Builder reference
        .build();

OneTimeWorkRequest oneTimeWorkRequest =
        new OneTimeWorkRequest.Builder(SyncWorker.class)
                .setConstraints(constraints)
                .addTag(SyncWorker.TAG)
                .build();

According to https://developer.android.com/topic/libraries/architecture/workmanager

// (Returning RETRY tells WorkManager to try this task again
// later; FAILURE says not to try again.)

I was wondering, if SyncWorker keep returning RETRY, what is the retry strategy of WorkManager? For instance, what is the maximum retry count for WorkManager? The documentation isn't clear on this.

Unwind answered 23/5, 2018 at 10:6 Comment(0)
M
37

The default is BackoffPolicy.EXPONENTIAL. We only retry when you ask us to RETRY by returning WorkerResult.RETRY or when constraints that were required for your Worker are now unmet. So for e.g. if you required a NETWORK constraint, and now the device lost its active Network connection - then the Worker will be stopped and be automatically retried (when the constraints are met).

For more information look at the docs.

Monoplane answered 25/5, 2018 at 21:33 Comment(7)
It's weird though because I've had instances where contraints were not met, and after the contraints became met, it would defer the execution of the worker. Any insight on this behavior?Dinar
@remedy you can return RETRY from your doWork method()Fatten
@Fatten I'm aware of the RETRY. I just now realized though that all of these executions are deferred. So even if we do retry, the retry execution will be deferred.Dinar
@remedy ya but it will be executed after some time. do you want to execute something immediately then you must use startForeGroundServiceFatten
@Monoplane and how about the scenario when there is a need to retry some unique (named) work just after the last worker in the queue? I have N workers of the same type that may need to retry if some information is not available yet, but if one of them fails, I need to retry it just when the others in the queue could try to take its information first (to avoid the same worker fail "forever" until its specific information is available). Is it possible to design this workflow?Opsonin
But would it keep retrying if nothing changes or stop after 10mins?Selena
Hi, I also want to know if it will keep retrying if it is stoped after 10minsForseti
H
22

This following example retry 3 times on caught Exception before quit.

class RepeatWorker(context : Context, params : WorkerParameters)
    : Worker(context, params) {

    private fun doSomeThing() {
        // do something
    }

    override fun doWork(): Result {

        if (runAttemptCount > 3) {
            return Result.failure()
        }

        try {
            doSomeThing()
        }
        catch (e: Exception) {
            e.printStackTrace()
            return Result.retry()
        }
        return Result.success()
    }
}

NOTE: Default BackoffPolicy is exponential, where 1st retry in 30s (minimum retry period is 10s and maximum retry period never exceed 18000s/5 hours).

fun start() : LiveData<WorkInfo> {
    val WORK_NAME = "SingleBackupWorker"

    val constraints = Constraints.Builder()
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .build()

    val work = OneTimeWorkRequestBuilder<BackupWorker>()
            .setConstraints(constraints)
            .setInitialDelay(5, TimeUnit.SECONDS)
            .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 1, TimeUnit.MINUTES)
            .build()

    WorkManager.getInstance().enqueueUniqueWork(WORK_NAME, ExistingWorkPolicy.REPLACE, work)

    return WorkManager.getInstance().getWorkInfoByIdLiveData(work.id)
}
Hostility answered 14/6, 2019 at 14:47 Comment(4)
Hey where do you get the info about the maximum retry period?Popham
developer.android.com/topic/libraries/architecture/workmanager/…Bart
hmm, there really should be an example in the docs about using runAttemptCount to limit the amount of retriesCorked
> "maximum retry period never exceed 18000s/5 hours)." That is misleading. You can not set more than 5 hours for backoff delay, but the worker will retry forever, exponentially, until it succeeds or fails.Monotony
L
1

Gets the current run attempt count for any work from runAttemptCount . Note that for periodic work, this value gets reset between periods. Link :-

https://developer.android.com/reference/androidx/work/ListenableWorker#getRunAttemptCount()

example :

override fun doWork(): Result {

    if (runAttemptCount < maxRetryConstantIWant) {
    ..... 
    .....
    .....
    } else { Result.Failure }
}

Here runAttemptCount is worker method.

Looselimbed answered 25/1, 2021 at 9:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.