Browse Source
feat: add contract interfaces and pin/release via release-func pattern (Phase 07 P1)
feat: add contract interfaces and pin/release via release-func pattern (Phase 07 P1)
E5 handoff contract (contract.go): - BlockVolReader: ReadState() → BlockVolState from real blockvol - BlockVolPinner: HoldWALRetention/HoldSnapshot/HoldFullBase → release func - BlockVolExecutor: StreamWALEntries/TransferSnapshot/TransferFullBase/TruncateWAL - Clear import direction: weed-side imports sw-block, not reverse StorageAdapter refactored: - Consumes BlockVolReader + BlockVolPinner interfaces - Pin/release uses release-func pattern (not map-based tracking) - PushStorageAdapter for tests (push-based, no blockvol dependency) 10 bridge tests: - 4 control adapter (identity, address change, role mapping, primary) - 4 storage adapter (retained history, WAL pin reject, snapshot reject, symmetry) - 1 E2E (assignment → adapter → engine → plan → execute → InSync) - 1 contract interface verification Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>feature/sw-block
3 changed files with 266 additions and 187 deletions
-
190sw-block/bridge/blockvol/bridge_test.go
-
82sw-block/bridge/blockvol/contract.go
-
181sw-block/bridge/blockvol/storage_adapter.go
@ -0,0 +1,82 @@ |
|||||
|
package blockvol |
||||
|
|
||||
|
// === Phase 07 P1: Handoff contract ===
|
||||
|
//
|
||||
|
// This file defines the interface boundary between:
|
||||
|
// - sw-block/bridge/blockvol/ (engine-side, no weed imports)
|
||||
|
// - weed/storage/blockvol/v2bridge/ (weed-side, real blockvol imports)
|
||||
|
//
|
||||
|
// The engine-side bridge defines WHAT the weed-side must provide.
|
||||
|
// The weed-side bridge implements HOW using real blockvol internals.
|
||||
|
//
|
||||
|
// Import direction:
|
||||
|
// weed/storage/blockvol/v2bridge/ → imports → sw-block/bridge/blockvol/
|
||||
|
// weed/storage/blockvol/v2bridge/ → imports → sw-block/engine/replication/
|
||||
|
// weed/storage/blockvol/v2bridge/ → imports → weed/storage/blockvol/
|
||||
|
// sw-block/bridge/blockvol/ → imports → sw-block/engine/replication/
|
||||
|
// sw-block/bridge/blockvol/ does NOT import weed/
|
||||
|
|
||||
|
// BlockVolState represents the real storage state from a blockvol instance.
|
||||
|
// Each field maps to a specific blockvol source:
|
||||
|
//
|
||||
|
// WALHeadLSN ← vol.nextLSN - 1 or vol.Status().WALHeadLSN
|
||||
|
// WALTailLSN ← vol.flusher.RetentionFloor()
|
||||
|
// CommittedLSN ← vol.distCommit.CommittedLSN()
|
||||
|
// CheckpointLSN ← vol.flusher.CheckpointLSN()
|
||||
|
// CheckpointTrusted ← vol.superblock.Valid + checkpoint file exists
|
||||
|
type BlockVolState struct { |
||||
|
WALHeadLSN uint64 |
||||
|
WALTailLSN uint64 |
||||
|
CommittedLSN uint64 |
||||
|
CheckpointLSN uint64 |
||||
|
CheckpointTrusted bool |
||||
|
} |
||||
|
|
||||
|
// BlockVolReader reads real blockvol state. Implemented by the weed-side
|
||||
|
// bridge using actual blockvol struct fields. The engine-side bridge
|
||||
|
// consumes this interface via the StorageAdapter.
|
||||
|
type BlockVolReader interface { |
||||
|
// ReadState returns the current blockvol state snapshot.
|
||||
|
// Must read from real blockvol fields:
|
||||
|
// WALHeadLSN ← vol.nextLSN - 1 or vol.Status().WALHeadLSN
|
||||
|
// WALTailLSN ← vol.flusher.RetentionFloor()
|
||||
|
// CommittedLSN ← vol.distCommit.CommittedLSN()
|
||||
|
// CheckpointLSN ← vol.flusher.CheckpointLSN()
|
||||
|
// CheckpointTrusted ← superblock valid + checkpoint file exists
|
||||
|
ReadState() BlockVolState |
||||
|
} |
||||
|
|
||||
|
// BlockVolPinner manages real resource holds against WAL reclaim and
|
||||
|
// checkpoint GC. Implemented by the weed-side bridge using actual
|
||||
|
// blockvol retention machinery.
|
||||
|
type BlockVolPinner interface { |
||||
|
// HoldWALRetention prevents WAL entries from startLSN from being recycled.
|
||||
|
// Returns a release function that the caller MUST call when done.
|
||||
|
HoldWALRetention(startLSN uint64) (release func(), err error) |
||||
|
|
||||
|
// HoldSnapshot prevents the checkpoint at checkpointLSN from being GC'd.
|
||||
|
// Returns a release function.
|
||||
|
HoldSnapshot(checkpointLSN uint64) (release func(), err error) |
||||
|
|
||||
|
// HoldFullBase holds a consistent full-extent image at committedLSN.
|
||||
|
// Returns a release function.
|
||||
|
HoldFullBase(committedLSN uint64) (release func(), err error) |
||||
|
} |
||||
|
|
||||
|
// BlockVolExecutor performs actual recovery I/O. Implemented by the
|
||||
|
// weed-side bridge. It does NOT decide recovery policy — it only
|
||||
|
// executes what the engine tells it to do.
|
||||
|
type BlockVolExecutor interface { |
||||
|
// StreamWALEntries streams WAL entries from startExclusive+1 to endInclusive
|
||||
|
// to the replica. Returns the highest LSN successfully transferred.
|
||||
|
StreamWALEntries(startExclusive, endInclusive uint64) (transferredTo uint64, err error) |
||||
|
|
||||
|
// TransferSnapshot transfers a checkpoint/snapshot at snapshotLSN to the replica.
|
||||
|
TransferSnapshot(snapshotLSN uint64) error |
||||
|
|
||||
|
// TransferFullBase transfers the full extent image to the replica.
|
||||
|
TransferFullBase(committedLSN uint64) error |
||||
|
|
||||
|
// TruncateWAL removes entries beyond truncateLSN from the replica.
|
||||
|
TruncateWAL(truncateLSN uint64) error |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue