Record why thumbnails are not queued
catalog.md §6 still described the design of 2026-08-09, where the grid enqueued Thumbnail jobs at Interactive and a runner drained them. It was never built that way: the grid asks a worker directly and the sweep's work list is what the thumbnail store lacks. The one enqueue that did exist fed a queue nobody claimed (#73). §6.1 now states the decision and its evidence: the store is shared between devices and is the only record that knows a thumbnail exists, metadata is owed through metadata_state the same way, the retired rows are dropped at open rather than by a migration so no older device loses the synced catalog, and every_queued_kind_has_a_consumer holds the rule. §6.3 notes that the priority ordering is had without the queue. outstanding.md's FR-PLAT-AND-4 paragraph said the scan's thumbnail jobs were the one reachable enqueue; it now says nothing enqueues, and that feeding the runner means a handler and its enqueue in the same change. Refs #73
This commit is contained in:
+25
-1
@@ -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
|
### 6.2 Coalescing is the point
|
||||||
|
|
||||||
`UNIQUE(kind, subject_id)` on `jobs` means enqueueing is idempotent: an image touched five times
|
`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
|
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
|
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
|
### 6.4 Durability and failure
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
manifest, and a stated Doze behaviour. The build step that blocked it is no longer a blocker: the
|
||||||
APK now compiles its own Java.
|
APK now compiles its own Java.
|
||||||
|
|
||||||
Note also that **no handler is registered**, deliberately. The only enqueue site reachable in the
|
Note also that **no handler is registered**, deliberately — and, since #73, nothing enqueues
|
||||||
shipping app produces remote thumbnail jobs already served by the async grid worker, and
|
either. The remote scan's per-photograph `Thumbnail` jobs, and `walk::scan_root`'s `Thumbnail` and
|
||||||
`walk::scan_root` — which holds the other two enqueue sites — has no caller outside an example.
|
`ExtractMetadata` jobs, duplicated debts the thumbnail store and `metadata_state` already record,
|
||||||
Wiring the sweep to claim from the queue is the honest next step and is an async rewrite of
|
and were never claimed; they were removed and `Thumbnail` retired ([catalog.md §6.1](catalog.md)).
|
||||||
`library.rs`.
|
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
|
**FR-PLAT-AND-5 — built.** A tiered eviction registry drives GPU caches, then proxies, then
|
||||||
thumbnails, from `MainEvent::LowMemory` and `MainEvent::Stop`.
|
thumbnails, from `MainEvent::LowMemory` and `MainEvent::Stop`.
|
||||||
|
|||||||
Reference in New Issue
Block a user