Skip to content

feat!: BackgroundTaskResult enum instead of bool (fixes #23) - #712

Draft
ened wants to merge 6 commits into
mainfrom
feat/background-task-result
Draft

feat!: BackgroundTaskResult enum instead of bool (fixes #23)#712
ened wants to merge 6 commits into
mainfrom
feat/background-task-result

Conversation

@ened

@ened ened commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

What

Replaces the Future<bool> task handler result with a BackgroundTaskResult enum: success / retry / failure (issue #23, open since 2019).

The real gap this closes: on Android, false always mapped to Result.retry() — there was no way to signal a permanent failure. A task with a broken API key or invalid config was retried forever. Now:

Dart Android iOS
BackgroundTaskResult.success Result.success() .newData
BackgroundTaskResult.retry Result.retry() (backoff) .failed (no auto-retry; re-schedule yourself)
BackgroundTaskResult.failure Result.failure() (permanent, chain stops) .failed

Design notes

  • Enum over sealed class: const values, trivially serializable, matches the issue's original proposal. Name BackgroundTaskResult (not Result) to avoid clashes with user imports.
  • Breaking change (0.10.1 → 0.11.0, pre-1.0 so fine). Migration is mechanical: return true;return BackgroundTaskResult.success;, return false;return BackgroundTaskResult.retry; (or .failure for permanent errors).
  • Web unchanged: the handler result has no OS semantics on web, and the worker bundle must stay Flutter-free (dart compile js), so importing the pigeon-generated enum (which pulls flutter/services) isn't possible. Web keeps Future<bool>.
  • iOS retry: no auto-reschedule — iOS' documented pattern is re-registering the task yourself. Auto-reschedule on retry could be a follow-up enhancement.

Verified

  • dart analyze clean (all packages + example)
  • 19 Dart VM tests pass (incl. updated in-process execution round-trip)
  • 78 Android unit tests pass (debug/profile/release)
  • flutter build ios --debug --no-codesign compiles (Swift mapping incl. the in-process one-off path)
  • SwiftLint clean (only pre-existing warnings)

Migration

Docs updated (README, debugging, customization, task-status) with the new enum and an updated error-handling strategy table.

Migration

  • New docs/migrating-to-background-task-result.mdx migration guide (+ sidebar entry). The change is mechanical and the type system surfaces every site (handler return type is now Future<BackgroundTaskResult>, so each un-migrated return true/false is a compile error). Mapping: true -> BackgroundTaskResult.success, false -> BackgroundTaskResult.retry (preserving pre-0.11 Android behavior), .failure for permanent errors.
  • Docs updated (README, debugging, customization, task-status) with the new enum and an updated error-handling strategy table.

Replace the Future<bool> task handler result with a BackgroundTaskResult
enum: success / retry / failure. This finally exposes Android's
Result.failure() (permanent failure, chain stops) — previously every
'false' was mapped to Result.retry(), so permanently failing tasks were
retried forever. iOS maps retry/failure to a failed fetch (no automatic
retry there by design).

- pigeon: executeTask returns BackgroundTaskResult (regen dart/kotlin/swift)
- android: success->Result.success, retry->Result.retry, failure->Result.failure
- ios: success->.newData, retry/failure->.failed; status tracking updated
  (in-process one-off path included)
- web: unchanged (handler result has no OS semantics there; worker bundle
  must stay Flutter-free)
- docs/example/tests migrated; 78 Android unit tests + 19 Dart tests pass,
  iOS debug build compiles

Breaking: handler must return BackgroundTaskResult instead of bool.
@docs-page

docs-page Bot commented Aug 3, 2026

Copy link
Copy Markdown

To preview the documentation for this pull request, visit the following URL:

docs.page/fluttercommunity/flutter_workmanager~712

Documentation is deployed and generated using docs.page

ened added 2 commits August 3, 2026 07:10
…t failures

Document and test what happens when the BackgroundTaskHandler throws (or its
Future errors): the Pigeon layer turns it into a channel error, which native
implementations map to a permanent failure — Android Result.failure(), iOS
.failed — i.e. no retry. Only BackgroundTaskResult.retry triggers Android
backoff.

- new task_result_test.dart verifies the success value round-trips and a
  thrown exception surfaces as a Pigeon error reply (code 'error')
- extracted shared pigeon test harness (pigeon_test_utils.dart); Workmanager
  statics are per-isolate, so handler-registering tests live in separate files
- BackgroundTaskHandler docs + error-handling table updated (throwing vs
  returning failure)
…hannel error

Background isolates have no console and no debugger, so a thrown handler
exception bubbling into a Pigeon channel error was invisible to the app
and depended on platform-specific error mapping. The plugin now catches
handler exceptions, logs them via debugPrint, and returns
BackgroundTaskResult.failure — the same permanent-failure path as any
other failure on both platforms (Android Result.failure(), iOS .failed).
No retry, no channel error.

- executeTask: try/catch around the handler; a missing handler still retries
- task_result_test: thrown exception now asserts BackgroundTaskResult.failure
  round-trips on the channel and the exception text was logged
- docs: task-status table row + throwing-vs-returning callout updated
ened added a commit that referenced this pull request Aug 3, 2026
…kgroundTaskResult

Ship the breaking change (#712, fixes #23) with tooling: a custom_lint
plugin that flags and auto-fixes un-migrated bool task results.

- use_background_task_result lint: flags 'return true/false' inside
  executeTask callbacks (incl. Future.value(...) / Future<bool>.value(...))
- fix rewrites true -> BackgroundTaskResult.success, false -> retry,
  preserving the historical Android behavior (old false = Result.retry)
- users: dev-dep custom_lint + workmanager_lints, analyzer plugins entry,
  then 'dart fix --apply'; lint keeps guarding against regressions
- docs: migration guide page (docs/migrating-to-background-task-result.mdx)
  + sidebar entry
- melos: new workmanager_lints package; 9 AST-level tests green
…em does the finding

The breaking change is a compile error at every migration site (handler
return type is now Future<BackgroundTaskResult>), so the IDE/analyzer
already finds everything; a custom_lint plugin with two dev deps + config
would be gold-plating for a two-line mapping. Ship the mapping instead:
docs/migrating-to-background-task-result.mdx (+ sidebar entry) with the
before/after table, the false -> retry behavior note, and platform notes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant