Repository navigation
feat(portable): publish split archives that Git can delta - #267
Conversation
Gzip generations are new incompressible blobs, so every hourly store snapshot added about 68 MB. --compression split commits the uncompressed database as ordered, verified 32 MiB parts: consecutive real generations now transfer as a 0.5 MB thin pack and add about 0.5 MB when packed. Refresh, init, status, runtime staging and recovery read split stores and verify each part and the reassembled database. After advancing, strict refresh runs a bounded geometric repack so subscribers also keep each generation as a delta; a large loose backlog is skipped and reported.
|
🦞👀 Pull request received. I will update this pull request when review starts. ClawSweeper review completeClawSweeper finished reviewing this revision. The review result is being finalized. |
Keep the existing no-repack contract for raw and gzip subscribers and reconcile the strict-refresh documentation with the split-store exception.
Implicit reader refreshes fast-forward without repacking, so a later strict refresh can be a ref no-op while split objects are still loose. Consolidate whenever the checkout generation is split; report current when nothing is loose.
|
Real-data subscriber proof. I built Both runs promoted the mirror with the manifest Owner decisions (Hannes delegated the storage decisions, "decide on the rest"):
|
Subscribers that keep fetched packs (fetch.unpackLimit or a large catch-up) have nothing loose but carry duplicate delta bases. Treat only a single pack with no loose objects as consolidated.
|
Proof at
New tests cover packed fetches with |
Keep consolidation failures nonfatal for the validated generation, but return a bounded, credential-safe repack_reason with the next step.
|
Failure-path proof at After the permission was restored, the retry returned |
|
ClawSweeper status: review started. I am starting a fresh review of this pull request: feat(portable): publish split archives that Git can delta This is item 1/1 in the current shard. Shard 0/1. This temporary status tracks the active review worker. The completed review will appear in the durable ClawSweeper review comment. Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted. |
|
Production subscriber upgrade. The deployed subscriber ran the official v0.9.5 release. It now runs a build of merged main ( As before the upgrade, the writable local mirror stays Operational note: under launchd, a locally built binary must be signed with the fleet's local code-signing identity, and the unchanged agent plist re-registered (bootout/bootstrap). Without that, macOS killed the job with |
The portable store publishes a new gzip archive every hour. Gzip output cannot delta against the previous generation, so each snapshot adds about 68 MB to
openclaw/gitcrawl-storeand to every subscriber. The subscriber checkout here has reached 47 GiB. This PR adds a split packaging that Git can delta, plus reader support. No history is trimmed and no published ref changes.Export.
portable export --compression splitcommits the finalized, uncompressed SQLite bytes as ordered parts:NAME.part-000,NAME.part-001and so on, 32 MiB each, or--max-archive-byteswhen that is smaller. At most 64 parts are allowed. The manifest recordscompression: "split"andarchiveParts: [{path, bytes, sha256}]. Because the parts are the database,archiveBytesandarchiveSha256equaloutputBytesandsha256. JSON output listsarchive_parts. Gzip and raw exports are unchanged.Readers. Refresh, init, status, runtime staging and malformed-source recovery all accept split stores. They check part names, sizes, digests, the per-part budget and the digest of the ordered concatenation before reassembling and validating the database as usual. Older readers fail closed with
unsupported compressionand keep their last good mirror.Subscriber storage. When the checkout's generation is split, strict refresh runs
git repack -d --geometric=2within the same deadline and growth budget. Each generation is then kept as a delta instead of eight new full objects. This also runs on a ref no-op, because implicit reader fast-forwards fetch without repacking. The result is reported asrepack: "geometric", or"current"when nothing is loose. If more than 512 loose objects are present, for example years of loose gzip generations, the repack is skipped and reported as"skipped-loose-backlog". A failure is reported but does not undo the validated generation. Raw and gzip stores keep the existing no-repack contract.Measured on real data. I exported two consecutive production generations (13:26Z and 14:26Z today) with this build:
Validation. On Go 1.27.3:
go test -raceoninternal/portableandinternal/cli: passed.The gitcrawl-store publisher change that switches the hourly workflow to
--compression splitis a separate PR in that repository and pins this commit.