Media processing: failure is a first-class state #168

Closed
opened 2026-08-09 19:49:13 +00:00 by rosa · 0 comments
Owner

Part of the "defer media processing to a background job" spec (PR #165; ADR-0020).
Completes the deferred pipeline by making failure a first-class outcome rather than
an endlessly-retried job.

What to build

Have the optimize_media job classify its failures and drive the Media to a
terminal Failed state where appropriate.

A permanent failure — bytes that passed the request-path magic-byte sniff but
are undecodable, a decompression bomb over the decode bound, anything outside the
allowlist — marks the Media Failed, deletes the staged original, and does not
retry (maps to the terminal Error::Abort classification). A transient failure
— out of memory under load, a full disk — retries with backoff a bounded number of
times (maps to the retryable Error::Failed), and once retries are exhausted the
Media falls to Failed.

Because the upload was fire-and-forget, a Failed Media is surfaced on its author's
own views rather than left to render as a silently broken image. (A dedicated
notification channel beyond surfacing the status is out of scope — spec.)

Acceptance criteria

  • Undecodable / decompression-bomb / off-allowlist input in the job marks the Media Failed with no retry and deletes the staged original.
  • A transient failure retries with backoff and, once exhausted, leaves the Media Failed.
  • The permanent/transient split maps onto the existing terminal-vs-retryable job classification.
  • A Failed Media is visible as Failed on its author's own views.
  • GET /media/{id} returns 404 for a Failed Media, and its Photo stays omitted from page and feeds.
  • Job-handler tests assert the classification directly: a bomb/undecodable/off-allowlist input yields the terminal outcome and a Failed Media with the staged file gone; a transient failure yields the retryable outcome.

Blocked by

Part of the "defer media processing to a background job" spec (PR #165; ADR-0020). Completes the deferred pipeline by making failure a first-class outcome rather than an endlessly-retried job. ## What to build Have the `optimize_media` job classify its failures and drive the Media to a terminal **Failed** state where appropriate. A **permanent** failure — bytes that passed the request-path magic-byte sniff but are undecodable, a decompression bomb over the decode bound, anything outside the allowlist — marks the Media **Failed**, deletes the staged original, and does not retry (maps to the terminal `Error::Abort` classification). A **transient** failure — out of memory under load, a full disk — retries with backoff a bounded number of times (maps to the retryable `Error::Failed`), and once retries are exhausted the Media falls to Failed. Because the upload was fire-and-forget, a Failed Media is surfaced on its author's own views rather than left to render as a silently broken image. (A dedicated notification channel beyond surfacing the status is out of scope — spec.) ## Acceptance criteria - [ ] Undecodable / decompression-bomb / off-allowlist input in the job marks the Media Failed with no retry and deletes the staged original. - [ ] A transient failure retries with backoff and, once exhausted, leaves the Media Failed. - [ ] The permanent/transient split maps onto the existing terminal-vs-retryable job classification. - [ ] A Failed Media is visible as Failed on its author's own views. - [ ] `GET /media/{id}` returns 404 for a Failed Media, and its Photo stays omitted from page and feeds. - [ ] Job-handler tests assert the classification directly: a bomb/undecodable/off-allowlist input yields the terminal outcome and a Failed Media with the staged file gone; a transient failure yields the retryable outcome. ## Blocked by - #167
rosa closed this issue 2026-08-10 00:09:52 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
rosa/vernier#168
No description provided.