Take the server's shards and dates when the scan completes, not after the sweep
Benchmarks / CPU and I/O (per commit) (push) Successful in 8m28s
Benchmarks / Frame budget (on demand) (push) Skipped
Build and test / Desktop (Linux) (push) Failing after 36s
Build and test / Layer separation (push) Successful in 28s
Traceability / Requirement traces (push) Failing after 39s
🐳 Android image / Build and push (push) Successful in 2s
Build and test / android-image (push) Successful in 2s
🐳 Windows image / Build and push (push) Successful in 1s
Build and test / windows-image (push) Successful in 1s
Build and test / Android (aarch64) (push) Successful in 43m11s
Build and test / Windows (x86_64, cross) (push) Failing after 41m4s
Benchmarks / CPU and I/O (per commit) (push) Successful in 8m28s
Benchmarks / Frame budget (on demand) (push) Skipped
Build and test / Desktop (Linux) (push) Failing after 36s
Build and test / Layer separation (push) Successful in 28s
Traceability / Requirement traces (push) Failing after 39s
🐳 Android image / Build and push (push) Successful in 2s
Build and test / android-image (push) Successful in 2s
🐳 Windows image / Build and push (push) Successful in 1s
Build and test / windows-image (push) Successful in 1s
Build and test / Android (aarch64) (push) Successful in 43m11s
Build and test / Windows (x86_64, cross) (push) Failing after 41m4s
The derived sync fired only after the metadata sweep, so a fresh device re-derived every thumbnail it scrolled past, re-detected faces and re-read every header for hours before adopting the shards and snapshot that held all of it. It now fires as soon as the scan completes — the first moment the rows the merges key on exist — and the sweep starts behind it. In steady state that pass is one listing. The catalog merge gains a fourth half: capture metadata (captured_at, offset, camera, lens, ISO) for images still at metadata_state < 2, matched by oc:fileid from a remote row at 2. A date is a fact about the file's bytes, not local state, and the snapshot already carried it. The sweep's per-chunk query then finds nothing left, and the timeline is whole on a fresh device without a header fetch. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -530,6 +530,15 @@ Three invariants, each tested:
|
||||
| Re-storing an existing id updates in place, never migrates | Migrating would rewrite a sealed shard |
|
||||
| Merging another client's shard is insert-only and idempotent | Both copies derive from the same bytes by the same code, so neither is better; preferring ours avoids dirtying a shard others have synced |
|
||||
|
||||
**When the exchange runs.** Corrected 2026-09-20. It fired only after the metadata sweep — hours
|
||||
on a large library — so a fresh device re-derived every thumbnail it looked at, re-detected faces
|
||||
and re-read every header before adopting the shards and snapshot that held all of it. It now also
|
||||
fires the moment the scan completes, which is the first moment the rows the merges key on exist,
|
||||
and the sweep starts behind it. In steady state that pass is one listing. The catalog merge also
|
||||
takes **capture metadata** (`captured_at`, offset, camera, lens, ISO) for images still at
|
||||
`metadata_state < 2`, matched by `oc:fileid` — a date is a fact about the file's bytes, not local
|
||||
state, and the snapshot already carried it; the sweep's per-chunk query then finds nothing left.
|
||||
|
||||
**The transfer**, in `dr-ui`'s `derived_sync`, exchanges shards with `.darkroom-derived/` under the
|
||||
library root. `ThumbStore::shards()` reports which are sealed, so an up-to-date client's whole pass
|
||||
is one listing plus whichever shard is still open.
|
||||
|
||||
Reference in New Issue
Block a user