fix(products): bomb-safe image processing + per-image error isolation; honest claim/resumability docs (SLICE-7 review)
ci / check (push) Has been cancelled
ci / check (pull_request) Has been cancelled

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-12 00:58:10 -07:00
parent 757412ef2a
commit c929282e07
5 changed files with 71 additions and 21 deletions
+17 -4
View File
@@ -155,12 +155,25 @@ them concurrently:
and multicast ranges are blocked); redirects are followed only within the
same guard — a redirect to a private IP is rejected mid-chain.
- **Bounds:** ≤ 20 MB response body, ≤ 30 s per fetch.
- **Per-image idempotent claim:** each `CatalogImage` row is claimed before
fetch; a restart that finds a row already `claimed` skips it — making the
phase resumable.
- **Per-image presence/idempotency check (`claim_image_for_fetch`):** before
processing, each `CatalogImage` row is checked so an already-handled row is
skipped. This is a presence guard adequate for the **single-worker,
in-process** model — the deployed app runs one uvicorn worker, recovery runs
at startup over prior-process runs, and a fresh confirm always targets a new
run, so two phase invocations never process the same run's images
concurrently. It is **not** a cross-process lock. A true multi-worker claim
would need a distinct in-flight status transition (`pending → fetching` with
`RETURNING`, or `SELECT … FOR UPDATE SKIP LOCKED`) — that is the future seam
if the fetch phase ever moves multi-process or onto a queue (§6.9).
- **Startup recovery scan:** on process start the app scans for runs stuck in
`fetching_images` and re-enqueues their pending images (emits TEL-5). This
covers crash/restart scenarios without a separate scheduler.
covers crash/restart scenarios without a separate scheduler. On a mid-fetch
process restart (e.g. a deploy) the phase is interrupted and the run is left
resumable: pending images stay `pending`, fetched ones stay `fetched`, and
the startup scan completes the run. Any pool-closed error in an in-flight
worker at shutdown is benign — the uncommitted image stays `pending` and is
re-fetched on resume. Mid-flight interruption is tolerated by construction
(§6.9).
- **Progress tracking:** the run row carries `image_progress`,
`image_counts`, and `image_outcomes` (updated per image); these fields feed
the run-detail UI panel.