Two builds of one pin make two libraries, and every snapshot pairs with only one of them #162
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
make-sample-media.shstamps every file it generates with the moment the imagewas built, and nothing puts them back. So two builds of the same pinned commit
produce libraries that differ in nothing but their timestamps — and a snapshot
cut against one of them no longer pairs with the other.
That is not hypothetical. Two images are on this machine right now, both of which
cargo xtask reference build --checkis happy with:jellyfin-rs/upstream:pinned(0e5cf3e7)ephyra/upstream:pinned(298b062a)The committed snapshots were cut against the first. Running
cargo xtask reference up --freshre-exports the library from the second, andephyra-app::scan_ingest::a_row_carries_the_time_its_own_file_was_writtenthenreports 12 of 20 rows disagreeing about their dates — upstream
2026-08-16 17:08:19, ours2026-08-20 20:27:33. Nothing in the failure says the media wasre-exported; it reads as the scan having got the dates wrong.
Why it bites
upcallsexport_media, whichdocker cps the baked library onto the hostover whatever was there. Any
up --fresh,bootstrap, ordown --wipefollowedby
updoes it. So a rebuild of the image silently invalidates every snapshot ondisk, and the only symptom is a date comparison in a crate that has nothing to do
with either.
crates/ephyra-app/corpus/README.mdalready warns about the neighbouring trap —cp -rinto a worktree stamping every file with the moment it ran, twelve rowsthen disagreeing about their dates and nothing saying why. This is the same
failure with the image as the cause.
What would fix it
Make the generated library a function of the pin rather than of the clock: have
make-sample-media.shtouch -devery file it writes to a fixed timestamp — thepinned commit's own date is the obvious one, and it is already in
pin.envterritory. Then two builds of one pin produce one library, a snapshot survives an
image rebuild, and
build --check's promise that the image "carries the librarythis tree describes" becomes true of the timestamps as well as of the bytes.
The cheap half, if the above is not wanted:
export_mediawarns when the mediait is about to overwrite has different timestamps from the media it is exporting,
and
reference/README.mdsays a rebuild invalidates the snapshots.How to know it is done
Build the image twice from a clean cache and diff the two exports with
find … -printf '%T@ %p\n': the two agree. Thenup --freshagainst a committedsnapshot and
a_row_carries_the_time_its_own_file_was_writtenpasses.Fixed in
feea61c.The issue named the timestamps; the bytes were the other half of it. Comparing the two images on this machine showed three files differing byte for byte at the same length —
Night Signal (2022).mkv,Test Pattern S01E03.mkv,Test Pattern S02E02.mkv— which is Matroska's randomSegmentUID, itsDateUTCand the CRC-32 elements over them. So the library was a function of the clock in two ways at once.What landed in
make-sample-media.sh:Measured, which is what the issue asked for: generating the library twice with the patched script gives 21 files,
BYTES IDENTICALandMTIMES IDENTICAL. Before the change the same comparison reported the three mkvs differing.Beside it, so the fix cannot be undone by accident:
upleaves a library already on the host where it is, and--freshdiscards the server's state without it — the media is a fixture every snapshot was scanned against, not state the server wrote. Verified:cargo xtask reference up --freshnow logslibrary already at …anda_row_carries_the_time_its_own_file_was_writtenpasses, where before it reported 12 of 20 rows disagreeing.What remains, and where it belongs. The library on this machine was laid down by a build from before any of this, so it does not match what the image would now write, and the committed snapshots are cut against it. Nothing breaks — the export guard is what keeps the pair together — but the next image rebuild has to re-lay the media and rebuild the snapshots with it.
reference/README.mdsays so where it says how to grow the fixture, and that rebuild is the one #148 and #117 are already waiting on.