Constraints and Chaining

Constraints, Backoff and Chaining Work

Constraints (network type, charging, battery not low, idle, storage not low) hold a request until the device is ready, and stop a running worker if they stop holding. Backoff follows a Result.retry(): the delay doubles each time with EXPONENTIAL (the default, from 30 seconds) or grows by a fixed step with LINEAR, between 10 seconds and 5 hours.

Chains run one-time requests in order; each link gets the previous link's output Data as input, and a failure fails the rest. BookNest's "sync now" is a two-link chain:

sync/SyncScheduler.kt: an expedited sync, then a reportKotlin
  fun syncNow(context: Context) {
    val sync = OneTimeWorkRequestBuilder<CatalogSyncWorker>()
      .setConstraints(online)
      .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 10, TimeUnit.SECONDS)
      .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
      .build()
    val report = OneTimeWorkRequestBuilder<SyncReportWorker>().build()
    WorkManager.getInstance(context)
      .beginUniqueWork("sync-now", ExistingWorkPolicy.REPLACE, sync)
      .then(report)                              // runs only if sync succeeds
      .enqueue()
    ...
  }

setExpedited() asks to start at once, within a quota, and allows only network and storage constraints: an early version with the battery constraint threw IllegalArgumentException: Expedited jobs only support network and storage constraints in build(). Fixed, --ez syncNow true logged the states from getWorkInfosForUniqueWorkFlow("sync-now") (logcat -v time, without date and process id):

Output of 161
07:04:37.643 D/BookNestWork: enqueued sync 23e8788b then report
07:04:38.439 D/BookNestWork: sync-now: [SyncReportWorker=BLOCKED, CatalogSyncWorker=RUNNING]
07:04:41.995 D/BookNestWork: sync-now: [SyncReportWorker=ENQUEUED, CatalogSyncWorker=SUCCEEDED]
07:04:43.599 D/BookNestWork: report: 6 books in the local catalog
07:04:43.751 D/BookNestWork: sync-now: [SyncReportWorker=SUCCEEDED,
  CatalogSyncWorker=SUCCEEDED]

With the test server answering 503 until 07:05:36, a second "sync now" backed off:

Output of 161
07:05:00.922 D/BookNestWork: sync attempt 1, id=30d54e85
07:05:03.119 W/BookNestNet: refresh failed: HTTP 503
07:05:14.435 D/BookNestWork: sync attempt 2, id=30d54e85
07:05:35.143 D/BookNestWork: sync attempt 3, id=30d54e85
07:06:15.871 D/BookNestWork: sync attempt 4, id=30d54e85
07:06:16.918 D/BookNestNet: refreshed 6 books from the network

After each Worker result RETRY, the next attempt came 10.0, 20.0 and 40.1 seconds later.