diff --git a/docs/dev/catalog.md b/docs/dev/catalog.md index 8570b3d..b2fbaa5 100644 --- a/docs/dev/catalog.md +++ b/docs/dev/catalog.md @@ -420,6 +420,29 @@ pub enum JobKind { } ``` +**Thumbnails are not queued (decided 2026-09-26, #73).** `Thumbnail` is kept only so its number +stays taken, and is listed in `JobKind::RETIRED`. Up to 0.16.0 every remote scan enqueued one per +photograph, and nothing claimed the kind — no `JobHandler` was ever registered for it, on desktop or +Android (the same `dr-ui`), and the catalog snapshot carries `jobs` but the merge never reads them +(§8.2). The reference catalog held 23,582 such rows, about 1 MB with its indexes. Thumbnails are +made another way, and by the right source of truth: + +- the grid asks a worker for the cells it is drawing, which serves them from the thumbnail store or + range-fetches the embedded preview (§7.2); +- the thumbnail sweep's work list is *what the store does not hold* (`thumbnails_outstanding`). + +The store is shared between devices (§7.3), so it is the only thing that knows another device already +made a thumbnail; a per-device queue row cannot. A queue row would be a second, staler record of the +same debt. Metadata is owed the same way — `metadata_state < 2` is the sweep's work list — so the local +walk no longer enqueues `ExtractMetadata` either. + +The rows already queued are dropped by `jobs::drop_retired`, from `runner::recover` at every catalog +open, rather than by a migration: a schema bump would make a device still on an older build refuse the +synced snapshot, and "every open" rather than "once" because an older build sharing the catalog +queues them again on its next scan. With the rows gone it is one probe of the `(kind, subject_id)` +index. `every_queued_kind_has_a_consumer` (dr-catalog) holds the rule: it reads the shipping sources +and fails if any kind is enqueued that no handler or claim names. + ### 6.2 Coalescing is the point `UNIQUE(kind, subject_id)` on `jobs` means enqueueing is idempotent: an image touched five times @@ -443,7 +466,8 @@ priority governs the whole app: Visible-cell work is enqueued by the grid as it scrolls, at `Interactive`. The effect is that a freshly scanned library fills in *where the user is looking* first, and grinds through the rest -behind them. +behind them. (As built, thumbnails and metadata get this ordering without the queue — the grid +requests its visible cells directly and the sweeps take what is left; see §6.1.) ### 6.4 Durability and failure diff --git a/docs/dev/outstanding.md b/docs/dev/outstanding.md index a42cb52..058b063 100644 --- a/docs/dev/outstanding.md +++ b/docs/dev/outstanding.md @@ -258,11 +258,13 @@ the platform half — a foreground `Service`, `FOREGROUND_SERVICE` and `POST_NOT manifest, and a stated Doze behaviour. The build step that blocked it is no longer a blocker: the APK now compiles its own Java. -Note also that **no handler is registered**, deliberately. The only enqueue site reachable in the -shipping app produces remote thumbnail jobs already served by the async grid worker, and -`walk::scan_root` — which holds the other two enqueue sites — has no caller outside an example. -Wiring the sweep to claim from the queue is the honest next step and is an async rewrite of -`library.rs`. +Note also that **no handler is registered**, deliberately — and, since #73, nothing enqueues +either. The remote scan's per-photograph `Thumbnail` jobs, and `walk::scan_root`'s `Thumbnail` and +`ExtractMetadata` jobs, duplicated debts the thumbnail store and `metadata_state` already record, +and were never claimed; they were removed and `Thumbnail` retired ([catalog.md §6.1](catalog.md)). +Feeding FR-PLAT-AND-4's platform half is therefore a matter of choosing a kind whose work has no +better source of truth, registering its handler, and enqueuing it in the same change — +`every_queued_kind_has_a_consumer` refuses the enqueue without the handler. **FR-PLAT-AND-5 — built.** A tiered eviction registry drives GPU caches, then proxies, then thumbnails, from `MainEvent::LowMemory` and `MainEvent::Stop`.