feat(nixos): delta prefetch for upgrades via pifinder-differ - #42
Open
mrosseel wants to merge 5 commits into
Open
feat(nixos): delta prefetch for upgrades via pifinder-differ#42mrosseel wants to merge 5 commits into
mrosseel wants to merge 5 commits into
Conversation
Before nix downloads whole store paths, ask the delta server for byte-level zstd patches against same-stem paths the device already holds (any retained generation), reconstruct the target NAR with zstd --patch-from, verify sha256 BEFORE import, and register via an import stream assembled locally from the response's references and deriver. Everything imported is a path nix no longer downloads; every failure falls back to the binary cache per path. Off by default: pifinder.deltaUrl = "" disables the whole path. The window_log from the server is capped at 2^28 (256 MiB decode memory) on the device. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Rate limiting is per update, not per IP: prefetch opens a session with POST /update-start naming the target toplevel; the server sizes the request budget from that closure's real size and the token rides an x-update-session header on every /delta and blob request. NAT-friendly (each device gets its own budget) and unavailable to abuse (unknown toplevels are refused). No session -> prefetch disabled for the run, normal downloads as before. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Upstream renumbered nearby-ranking to ADR 0030 (our 0029 was byte-identical — dropped in favour of upstream's numbering) and its 0029 is the fov-gate ADR. Our delta-updates ADR moves to 0031. Conflicts: nearby.py/test_nearby.py taken from upstream (same fix, upstream evolved in review); observations_db.py keeps the nixos shared identity cache which supersedes upstream's batch resolve; test_ui_modules.py takes upstream (superset: adds the details-serialise test). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Device-side applier for the delta-update transport. Before
nixos_upgradelets nix download whole store paths, it asks the pifinder-differ server (running beside Attic on the cache host) for byte-level zstd patches against same-stem store paths the device already holds — across all retained generations — and imports whatever it can reconstruct. Every imported path is one nix no longer downloads.Measured server-side on real CI build pairs: 255 MiB of changed store paths compress to 1.5 MiB of patches (0.6%).
How
delta_updates.py(new, stdlib-only likenixos_upgrade):/nix/storePOST /delta→ 200 (patch ready) / 202 (computing, bounded retry) / 204 (full download)zstd --patch-fromagainstnix-store --dumpof the base (canonical on both ends)nix-store --importdoes not check the NAR against the path name, so this is the line between a bad patch and a corrupt storenix-store --exportoutput for paths with and without references/derivernixos_upgrade.py: one prefetch call betweenestimate_downloadandrun_build, plus a re-estimate so progress denominators match what nix actually fetchesservices.nix: newpifinder.deltaUrloption (default""= disabled), env wiring,zstdin the upgrade service pathSafety
deltaUrlshort-circuits before any work.nix-store --verify-path) — each falls back to the normal binary-cache download;prefetch_deltascan never raise into the upgrade.Tests
23 new unit tests (
pytest -m unit): stem/path parsing, candidate ordering, byte-exact import-stream framing, protocol states, apply guardrails, never-raises. Fulltest_nixos_upgrade.pysuite still passes.Not in this PR
The server is currently loopback-only on the cache host; exposing it (e.g.
https://deltas.pifinder.euvia Caddy) is a separate infra change, after which enabling is a one-linepifinder.deltaUrlsetting per device.🤖 Generated with Claude Code