Commit Graph
8 Commits
Author SHA1 Message Date
pingqiuandClaude Opus 4.6 cd8bfb21d4 fix: tighten FC1 new-session assertion and FC4 proof-detail check
FC1: now asserts HasActiveSession() after address change AND
verifies session_created in log (not just plan_cancelled).

FC4: escalation event detail must be >15 chars (contains proof
reason with LSN values, not just "needs_rebuild").

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 23:43:48 -07:00
pingqiuandClaude Opus 4.6 cd4b91033f fix: force failure conditions in P2 tests, add BlockVol.ForceFlush
P2 tests now force conditions instead of observing them:

FC3: Real WAL scan verified directly — StreamWALEntries transfers
real entries from disk (head=5, transferred=5). Engine planning also
verified (ZeroGap in V1 interim documented).

FC4: ForceFlush advances checkpoint/tail to 20. Replica at 0 is
below tail → NeedsRebuild with proof: "gap_beyond_retention: need
LSN 1 but tail=20". No early return.

FC5: ForceFlush advances checkpoint to 10. Assertive:
- replica at checkpoint=10 → ZeroGap (V1 interim)
- replica at 0 → NeedsRebuild (below tail, not CatchUp)

FC1/FC2: Labeled as integrated engine/storage (control simulated).

New: BlockVol.ForceFlush() — triggers synchronous flusher cycle for
test use. Advances checkpoint + WAL tail deterministically.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 23:07:55 -07:00
pingqiuandClaude Opus 4.6 26bf7bc582 feat: add integrated failure replay tests through real bridge path (Phase 07 P2)
5 failure-class replay tests against real file-backed BlockVol,
exercising the full integrated path:
  bridge adapter → v2bridge reader/pinner → engine planner/executor

FC1: Changed-address restart — identity preserved, old plan cancelled,
     new session created. Log shows plan_cancelled + session_created.

FC2: Stale epoch after failover — sessions invalidated at old epoch,
     new assignment at epoch 2 creates fresh session. Log shows
     per-replica invalidation.

FC3: Real catch-up (pre-checkpoint) — engine classifies from real
     RetainedHistory, zero-gap in V1 interim (committed=0 before flush).
     Documents the V1 limitation explicitly.

FC4: Unrecoverable gap — after flush, if checkpoint advances, replica
     behind tail gets NeedsRebuild. Documents that V1 unit test may
     not advance checkpoint (flusher timing).

FC5: Post-checkpoint boundary — replica at checkpoint = zero-gap in
     V1 interim. Explicitly documents the catch-up collapse boundary.

go.mod: added replace directives for sw-block engine + bridge modules.

Carry-forward (explicit):
- CommittedLSN = CheckpointLSN (V1 interim)
- FC3/FC4/FC5 limited by flusher not advancing checkpoint in unit tests
- Executor snapshot/full-base/truncate still stubs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 22:54:44 -07:00
pingqiuandClaude Opus 4.6 4aab00b149 feat: add real v2bridge integration tests against file-backed BlockVol
7 tests in weed/storage/blockvol/v2bridge/bridge_test.go:

Reader (2 tests):
- StatusSnapshot reads real nextLSN, WALCheckpointLSN, flusher state
- HeadLSN advances with real writes

Pinner (2 tests):
- HoldWALRetention: hold tracked, MinWALRetentionFloor reports position,
  release clears hold
- HoldRejectsRecycled: validates against real WAL tail

Executor (2 tests):
- StreamWALEntries: real ScanFrom reads WAL entries from disk
- StreamPartialRange: partial range scan works

Stubs (1 test):
- TransferSnapshot/TransferFullBase/TruncateWAL return not-implemented

All tests use createTestVol (1MB file-backed BlockVol with 256KB WAL).
No mock/push adapters — direct real blockvol instances.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 22:22:28 -07:00
pingqiuandClaude Opus 4.6 d5b2a3a345 fix: WALTailLSN is now an LSN boundary, ScanWALEntries uses durable checkpoint
Finding 1: WALTailLSN semantic fix
- StatusSnapshot().WALTailLSN now reads super.WALCheckpointLSN (an LSN)
- Was: wal.Tail() which returns a physical byte offset
- Entries with LSN > WALTailLSN are guaranteed in the WAL

Finding 2: ScanWALEntries replay-source fix
- ScanWALEntries passes super.WALCheckpointLSN as the recycled boundary
- Was: flusher.CheckpointLSN() which in V1 equals CommittedLSN
- The flusher's live checkpoint may advance in memory, but entries above
  the durable superblock checkpoint are still physically in the WAL
- Normal catch-up (replica at 70, committed at 100) now works because
  fromLSN=71 > super.WALCheckpointLSN (which is the last persisted
  checkpoint, not the live flusher state)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 20:26:27 -07:00
pingqiuandClaude Opus 4.6 785a7d7efd feat: wire real pinner into flusher retention + real WAL scan executor (Phase 07 P1)
Pinner wired to real retention:
- NewPinner calls vol.SetV2RetentionFloor(p.MinWALRetentionFloor)
- Flusher.RetentionFloorFn() / SetRetentionFloorFn() exposed
- SetV2RetentionFloor chains with existing shipper retention floor
- Holds actually prevent WAL reclaim (not just tracked state)

Executor uses real WAL scan:
- BlockVol.ScanWALEntries(fromLSN, callback) wraps wal.ScanFrom
  with real fd, walOffset, checkpointLSN
- Executor.StreamWALEntries uses ScanWALEntries (not stub)
- Reads real WAL entries, tracks highest LSN scanned

CommittedLSN mapping:
- Explicitly documented as interim V1 model (committed = checkpointed)
- Will diverge when V2 distributed commit separates from local flush

Carry-forward:
- TransferSnapshot/TransferFullBase/TruncateWAL: stubs (need extent I/O)
- Control intent from confirmed failover: deferred

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 20:01:46 -07:00
pingqiuandClaude Opus 4.6 c00c9e3e3d feat: add real BlockVolPinner + BlockVolExecutor in v2bridge (Phase 07 P1)
Pinner (pinner.go):
- HoldWALRetention: validates startLSN >= current tail, tracks hold
- HoldSnapshot: validates checkpoint exists + trusted
- HoldFullBase: tracks hold by ID
- MinWALRetentionFloor: returns minimum held position across all
  WAL/snapshot holds — designed for flusher RetentionFloorFn hookup
- Release functions remove holds from tracking map

Executor (executor.go):
- StreamWALEntries: validates range against real WAL tail/head
  (actual ScanFrom integration deferred to network-layer wiring)
- TransferSnapshot/TransferFullBase/TruncateWAL: stubs for P1

Key integration points:
- Pinner reads real StatusSnapshot for validation
- Pinner.MinWALRetentionFloor can wire into flusher.RetentionFloorFn
- Executor validates WAL range availability from real state

Carry-forward:
- Real ScanFrom wiring needs WAL fd + offset (network layer)
- TransferSnapshot/TransferFullBase need extent I/O
- Control intent from confirmed failover (master-side)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 19:54:24 -07:00
pingqiuandClaude Opus 4.6 d5ecf471fe feat: real blockvol integration — StatusSnapshot + v2bridge reader + contract interfaces (Phase 07 P1)
Real blockvol integration:
- BlockVol.StatusSnapshot() reads actual fields:
  WALHeadLSN ← nextLSN-1, WALTailLSN ← wal.Tail(),
  CommittedLSN ← flusher.CheckpointLSN(),
  CheckpointLSN ← super.WALCheckpointLSN,
  CheckpointTrusted ← super.Validate()==nil

weed/storage/blockvol/v2bridge/:
- Reader wraps real BlockVol, implements ReadState() → BlockVolState
- Lives in weed/ module (can import blockvol directly)

sw-block/bridge/blockvol/ contract interfaces:
- BlockVolReader: ReadState() (weed-side implements)
- BlockVolPinner: HoldWALRetention/HoldSnapshot/HoldFullBase → release func
- BlockVolExecutor: StreamWALEntries/TransferSnapshot/TransferFullBase/TruncateWAL
- StorageAdapter refactored to consume interfaces (not push-based)
- PushStorageAdapter for tests

Handoff boundary (E5):
- sw-block/ defines contracts, weed/ implements them
- sw-block/ does NOT import weed/
- No cross-module circular dependency

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 18:17:59 -07:00