Separate acknowledgement from execution

When work is accepted, show a job ID and a route back to its status. “Queued” means the service accepted the job, not that execution began. “Running” means the service reports active work. Use a percentage only when the backend measures a meaningful numerator and denominator; otherwise use an indeterminate progress treatment and explain the current phase.

The W3C's progress technique shows that changing aria-valuenow alone may not announce updates. It pairs the progress indicator with a live status message. Updates should be useful rather than chatty: announce important phase changes and terminal results.

“Cancel requested” is its own state

Cancellation is often a request, not an immediate fact. After the operator asks to cancel, say “Cancellation requested; work may continue until the service confirms.” Prevent repeated cancellation requests but keep the job ID visible.

MDN documents that AbortController can abort browser-side requests, response consumption, and streams. That does not establish that a remote background job stopped. Show “Cancelled” only after the job service acknowledges its terminal state, and disclose any partial effects that cannot be rolled back.

Preserve unknown as an honest outcome

If status polling fails, keep the last confirmed phase and timestamp but label the current state unknown. Do not convert a lost status response into “Failed” and do not assume a completed result. The job ID is the reconciliation handle.

State Minimum visible content
Queued Job ID, accepted time, next status check
Running Current phase or measured progress
Cancel requested Request time and pending acknowledgement
Completed Completion time and result link
Failed Specific failure and safe retry policy
Cancelled Server acknowledgement and partial effects
Unknown Last confirmed state and reconciliation action

Acceptance checks

  • The job remains identifiable after navigation or reload.
  • Queued and running are not compressed into one spinner state.
  • Percent complete appears only when meaningfully measured.
  • Cancel requested remains pending until server acknowledgement.
  • Closing the page or aborting fetch never claims the job stopped.
  • Terminal results remain retrievable.
  • Unknown is distinct from failed and completed.
  • Important phase and terminal changes are programmatic status messages.

These checks do not implement a queue, idempotency, cancellation, rollback, or durable result storage. Those guarantees belong to the job service.