SegmentManager.AppendBatch was passing sm.active.CurrentOffset() (byte
offset from file header) as the new segment's startSequence on rotation.
The result: segment-N+1's header.startSequence was a byte count (e.g.
50000), not the actual sequence number. Recovery's continuity check at
recovery.go:181-184 (segment.StartSequence != expectedSequence) failed,
making Phase 1 multi-segment recovery completely broken.
Oracle bg_ef425776 noted: "C8 是隐藏炸弹:单 segment 时一切正常,
第一次轮转后就坏".
Changes:
- wal/segment_manager.go: AppendBatch now takes batchStartSequence uint64
parameter. On rotation, passes it to rotate (which writes it to the new
segment's header.startSequence). The previous byte-offset argument is
replaced by the actual sequence number.
- wal/writer.go: processBatch passes baseSequence (already allocated by
seqManager.AllocateBatch) to AppendBatch.
- wal/segment_manager_test.go: 6 existing AppendBatch call sites updated
to pass batchStartSequence (tracked via local currentSeq variable).
Added 2 new tests:
- TestSegmentManagerRotationWritesCorrectStartSequence: verifies new
segment's header.startSequence matches the first rotated batch's
sequence (and explicitly != old byte offset, catching C8 regression).
- TestSegmentManagerMultiSegmentRecoveryRoundTrip: end-to-end test that
writes across multiple segments, closes, recovers, and verifies all
batches replay. Before C8 fix, recovery failed at continuity check.
Verified: each new test fails on pre-fix code (segment-1 startSequence
is byte offset, recovery fails) and passes after the fix. Full suite
green including go test -race ./... .
Audit context: docs/audit-3.2.md C8 (Oracle-discovered bg_2e86d33b).
Replace polling loop (Collect + Sleep) with proper batch collection:
- Block on first request via channel receive
- Start 500µs timer for collection window
- Accumulate requests until timer fires or batch reaches 32KB
- Shutdown handling at all blocking points
Design doc §3.2.5: '等待组提交触发(500µs 或 32KB,先到者触发)'
Add GroupCommitDelay config field (default 500µs, must be > 0 and < 10ms).
- Sync() now flushes BlockWriter before fd.Sync() for durability
- Pre-validate encoding before sequence allocation (design doc compliance)
- Remove dead _ = rec assignment in recover.go
- Remove unused maxPayload field from SegmentWriter
- Handle Put error in MemTable.Publish with panic on invariant violation
- wal/commit_queue.go: bounded buffered channel for write requests
- wal/writer.go: single-goroutine main loop implementing 11-step write flow
with group commit, sequence allocation, MemTable publish/abort, write-stopped
- wal/recovery.go: BatchReplayer interface, ReplayBatch, ReplaySegmentFile,
RecoverFromSegments with fragment reassembly and tail corruption handling
- Comprehensive tests for all modules, all pass with -race