Update packfile design doc to match merged writer and reader implementations - #737
Merged
Merged
Conversation
…tations The packfile design doc has been out of sync with the implementation. Most of the drift came in with the writer (#702) and was never reflected in the doc; the reader (#712) added a few more deltas. This brings the doc end-to-end into alignment with the merged code. From #702 (writer): - Format is a caller-assigned uint32, not the old RecordFormat enum (Compressed/Uncompressed/Raw). Codec is plug-in via NewRecordEncoder. - New WriterOptions fields: NewRecordEncoder factory, ContentHashExtract. - Trailer is 76 bytes (was 64): new format field at offset 8, only flagContentHash remains, magic corrected to 0x48434C53. - Records: caller-encoded payload + library-managed item-size-index CRC; per-record payload integrity is encoder-supplied. - Writer single-goroutine constraint; AppendItem semantics (no-args no-op, empty-bytes item, copy, MaxUint32 error); fsync (not fdatasync); Concurrency <= NumCPU sizing advice. - ErrWriterClosed added to the errors list. From #712 (reader): - ReaderOptions is a struct (was variadic WithConcurrency); default Concurrency is 1, not 8; RecordDecoder is a single concurrent-safe instance, caller-owned, not closed by Reader.Close. - ReadItems / ReadRange return errors instead of panicking; new ErrPositionsUnsorted sentinel. - ReadRange break-early invalidates the last yielded slice; iterator not safe for concurrent iteration; count == 0 is valid. - ReadItems ctx checked at batch boundaries (not per-item); non-atomic on error; empty positions is valid; fn errors returned verbatim. - Close blocks waiting for the background open if it is still in flight. - Implementation notes: errgroup.WithContext, single concurrent-safe decoder + package-level workspace pool, corrected parallel-pipeline gate. New section: Codec Contract (Format, RecordEncoder, RecordDecoder interfaces, zstd subpackage). Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
tamirms
force-pushed
the
update-packfile-design-doc-reader
branch
from
May 13, 2026 13:08
a11d21a to
225231e
Compare
This was referenced May 14, 2026
karthikiyer56
approved these changes
May 18, 2026
…y I/O is backgrounded Open validates options synchronously before starting the background goroutine; only file I/O runs in the background. Both error kinds are still deferred to the first read. Matches the Go doc comment on Open in reader.go, which the design doc had drifted from. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
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.
Summary
The packfile design doc has been out of sync with the implementation. Most of the divergence came in with the writer (#702) and was never reflected in the doc; the reader (#712) added a few more deltas on top. This PR brings the doc end-to-end into alignment with the merged code.
No code changes — doc-only.
Major changes
From #702 (writer) — doc was never updated
WriterOptions.Formatis now a caller-assignedFormat uint32identifier, not the oldRecordFormatenum (Compressed/Uncompressed/Raw). The built-in formats are gone — codec is plug-in viaNewRecordEncoder.NewRecordEncoder func() RecordEncoder(per-worker factory),ContentHashExtractfor per-item transformation before hashing.format uint32field at offset 8; onlyflagContentHashremains (flagNoCompression/flagNoCRCare gone). Magic constant corrected to0x48434C53. Worked-example file-size math updated.[]byte{}records an empty item, parts are copied, oversized items error.fdatasync; the code callsos.File.Sync()which isfsync.runtime.NumCPU()tend to hurt throughput.From #712 (reader)
WithConcurrency). DefaultConcurrencyis 1 (serial), not 8.Reader.Close.ReadItems/ReadRangereturn errors instead of panicking. NewErrPositionsUnsortedsentinel.count == 0is valid.ReadItemsis not atomic on error (fn may have run for some positions and not others). Empty positions slice is valid. fn's error is returned verbatim.ReadItemsuseserrgroup.WithContext(no more atomic-flag cancellation); single concurrent-safe decoder + package-level workspace pool replaces the old per-Reader decoder pool.New section
Format uint32, theRecordEncoder/RecordDecoderinterfaces, and the in-treezstdcodec (*zstd.Compressor/*zstd.Decompressor).Polish
versionbyte vs the caller-assignedFormatfield) at the index-encoding section.Concurrency).Verification
Doc was fact-checked end-to-end against the current implementation in
cmd/stellar-rpc/internal/packfile/via five review passes: three parallel agents on API surface, on-disk format, and behavior/implementation; followed by deep audits dedicated to the writer side and the reader side. All trailer offsets, struct fields, method signatures, error names, default values, lifetime contracts, and implementation claims verified against code.Test plan
🤖 Generated with Claude Code