mirror of
https://github.com/runbear-io/beardrive.git
synced 2026-08-25 08:08:08 +02:00
Delta sync: large files move as content-defined chunks (#161)
* feat(sync): delta sync — large files move as content-defined chunks Files over 4 MiB push as chunks/<sha256> pieces plus a manifests/<sha256> chunk list keyed by the whole file's hash, so Op.Blob alone locates it and the journal format is byte-identical. A 1-byte edit to a 20 MiB file now transfers ~2 MB instead of ~21 MB, both directions; chunk boundaries come from a rolling hash (restic/chunker), so front insertions stay cheap. The hub reassembles whole blobs on demand (spool, verify, backfill, serve), which is the entire backward-compatibility story: old clients ask for blobs/<sha> and never learn anything changed. Proven by e2e tests that build the real pre-change binary from the pinned merge-base commit. The push skip-proof is one Exists per chunk — three cheaper proxies (local basis, manifest existence, stored manifest content) each proved false or forgeable across four CTO review rounds and are recorded in the code comment. Hub-side, manifests are write-once and must name only chunks the store holds; reassembly is bounded at 256 MiB against amplified manifests. Also: per-file sync ceiling 32 -> 100 MiB; import refuses archives whose journals reference content they do not hold (--allow-incomplete overrides). Deploy hubs before clients: old hubs refuse chunk keys (push degrades to offline-retry), and old clients cap reads at 32 MiB so 32-100 MiB files report "blob corrupt on remote" until the client upgrades. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R6nqxi5a9qcENmJvrgBJF7 * fix(test): fetch the pinned pre-delta commit on shallow CI clones buildOldBinary archives the pinned merge-base sha, which a fetch-depth-1 actions/checkout does not have — all three old-binary e2e tests failed in CI with exit 128 while passing on any full local clone. On archive failure, fetch just that commit (--depth=1, one object; actions/checkout persists credentials so the in-job fetch works) and retry. Verified against a real GitHub shallow clone: archive fails, the single-sha fetch succeeds, archive then yields the pre-delta tree. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R6nqxi5a9qcENmJvrgBJF7 --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
33ca0caeab
commit
0dd474baab
@@ -264,7 +264,11 @@ creates a NEW project (it never joins an existing one by name — pass `--name`
|
||||
if the archive's name is taken), and the destination hub needs uploads
|
||||
enabled. A single file in the archive may spool at most 256 MiB to local disk
|
||||
during import; `--max-blob` raises that if the project really holds a bigger
|
||||
file. Shares,
|
||||
file. Import refuses an archive whose journals reference content the archive
|
||||
does not hold — the shape a pre-delta-sync `bdrive export` produces against a
|
||||
newer hub, where large files live as chunks the old binary doesn't know to
|
||||
collect; re-export with a current `bdrive`, or pass `--allow-incomplete` to
|
||||
import anyway (the missing files are listed and stay missing). Shares,
|
||||
invite links, and read-heat stay behind (they belong to the hub, not the
|
||||
project store). Step-by-step walkthrough:
|
||||
[Migrate between hubs](/reference/migration/).
|
||||
|
||||
@@ -91,3 +91,11 @@ Nothing is keyed by folder path, which is why moves and renames are free.
|
||||
```
|
||||
|
||||
Also here for a running project: `daemon.pid` and `daemon.log`.
|
||||
|
||||
The hub's storage adds two key classes the local store never holds: files
|
||||
larger than 4 MiB travel as content-defined `chunks/<sha256>` pieces plus a
|
||||
`manifests/<sha256>` chunk list keyed by the whole file's hash (delta sync —
|
||||
a small edit to a large file uploads roughly one chunk, not the file). Local
|
||||
blobs stay whole; chunking exists only on the wire and in the hub's store,
|
||||
and the hub reassembles a whole blob on demand for any client that asks for
|
||||
`blobs/<sha256>`, so older clients keep working unchanged.
|
||||
|
||||
Reference in New Issue
Block a user