Files
seaweedfs/sw-block/design/v2-second-migration-task-pack.md
T
pingqiuandClaude Opus 4.6 11c6aaf316 feat: Batch 7 + Phase 16C-E — command dispatch extraction + engine refinements
Batch 7: Command dispatch binding extraction
- New weed/server/blockcmd package: CommandHandler interface + DispatchCommands
- volume_server_block.go applyCoreCommandsWithAssignment delegates to dispatcher
- weed/server still owns RecordCommand, EmitCoreEvent, PublishProjection
- v2bridge NOT given command-switch or event-emission semantics

Phase 16C: Rebuilding assignment enters core command path
Phase 16D: Rebuild recovery-task startup is command-driven
Phase 16E: Catch-up recovery-task startup is command-driven

Engine refinements:
- RecoveryTarget on AssignmentDelivered event
- shouldStartRecoveryTask / shouldStartReceiver guards
- bootstrapReason: awaiting_rebuild_start

Bridge/contract updates:
- control_adapter.go: refined translation helpers
- contract.go: executor port alignment

Migration design docs (Batch 1-3 delivered, design artifacts):
- v2-first/second/third-migration-batch.md + task-pack.md
- v2-assignment-translation-unification.md
- v2-execution-muscles-inventory.md
- v2-separation-port-layer-audit.md
- v2-legacy-runtime-exit-criteria.md

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 02:13:08 -07:00

231 lines
6.6 KiB
Markdown

# V2 Second Migration Task Pack
Date: 2026-04-04
Status: delivered
## Purpose
This note turns the second separation batch into validate-able engineering
tasks.
The first batch proved that contract ownership and translation authority already
belong in `sw-block`. The second batch now targets the remaining physical
coupling: backend bindings.
## Shared Rules
All tasks in this pack inherit these rules:
1. `sw-block` must not directly import `weed/storage/blockvol`
2. reusable execution-muscle logic should move toward `sw-block`
3. weed-side code should shrink toward thin concrete bindings
4. no task in this pack may redefine engine semantics or recovery policy
## Task E: Reader Backend-Binding Extraction
### Goal
Extract reusable reader logic from direct `BlockVol` coupling so the
`BlockVol`-specific part becomes a thin snapshot binding.
### Source
1. `weed/storage/blockvol/v2bridge/reader.go`
2. `weed/server/block_recovery.go` reader shim
### Destination
1. reusable reader logic in `sw-block/bridge/blockvol/runtime`
2. thin `BlockVol` snapshot binding in `weed/storage/blockvol/v2bridge`
### Authority Rule
The reusable logic that shapes backend snapshot data into
`bridge.BlockVolState` belongs with `sw-block` execution muscles.
The weed-side binder may fetch snapshot fields from real `BlockVol`, but it
must not own the reusable state-shaping layer.
### Adapter Boundary
`weed/` may:
1. call `StatusSnapshot()` on real `BlockVol`
2. expose raw backend snapshot data to the extracted layer
`weed/` must not:
1. keep a second contract-shape mapping layer in `block_recovery.go`
2. reinterpret retained-history meaning
### Acceptance
1. reusable reader logic no longer depends on direct `BlockVol` import
2. `weed/storage/blockvol/v2bridge/reader.go` is reduced to thin binding code
3. `readerShimForRecovery` is removed or reduced to trivial wiring
### Validation
1. `go test ./sw-block/bridge/blockvol`
2. `go test ./weed/storage/blockvol/v2bridge -run "TestReader_"`
3. if the recovery shim changes, run:
- `go test ./weed/server -run "TestP4_|TestP16B_"`
### Current proof anchors
1. `TestStorageAdapter_RetainedHistoryFromReader`
2. `TestReader_RealBlockVol_StatusSnapshot`
3. `TestReader_RealBlockVol_HeadAdvancesWithWrites`
## Task F: Pinner Backend-Binding Extraction
### Goal
Extract hold bookkeeping and release lifecycle from direct `BlockVol` coupling
so weed-side code only performs concrete retention-floor binding and state
validation.
### Source
1. `weed/storage/blockvol/v2bridge/pinner.go`
2. `weed/server/block_recovery.go` pinner shim
### Destination
1. reusable hold bookkeeping in `sw-block/bridge/blockvol/runtime`
2. thin `BlockVol` retention binding in `weed/storage/blockvol/v2bridge`
### Authority Rule
Hold bookkeeping is reusable execution-muscle logic. Concrete interaction with
the flusher and `StatusSnapshot()` stays in `weed/`, but ID tracking and release
symmetry should not require direct `BlockVol` imports.
### Adapter Boundary
`weed/` may:
1. install retention-floor callbacks on real `BlockVol`
2. validate requested hold positions against live backend snapshot state
`weed/` must not:
1. keep reusable hold lifecycle ownership trapped in `weed/`
2. force recovery policy knowledge into the pinner binding
### Acceptance
1. reusable hold bookkeeping can live in `sw-block` without `BlockVol` imports
2. weed-side pinner code shrinks toward concrete callback/state binding
3. `pinnerShimForRecovery` is removed or reduced to trivial wiring
### Validation
1. `go test ./sw-block/bridge/blockvol`
2. `go test ./weed/storage/blockvol/v2bridge -run "TestPinner_|TestBridge_"`
3. if the recovery shim changes, run:
- `go test ./weed/server -run "TestP4_|TestP16B_"`
### Current proof anchors
1. `TestStorageAdapter_WALPinRejectsRecycled`
2. `TestStorageAdapter_SnapshotPinRejectsUntrusted`
3. `TestStorageAdapter_PinReleaseSymmetry`
4. `TestPinner_RealBlockVol_HoldWALRetention`
5. `TestPinner_RealBlockVol_HoldRejectsRecycled`
## Task G: Executor Backend-Capability Extraction
### Goal
Split executor logic into:
1. reusable orchestration that belongs with `sw-block` execution muscles
2. concrete backend capabilities and wire operations that remain in `weed/`
### Source
1. `weed/storage/blockvol/v2bridge/executor.go`
2. related tests in:
- `weed/storage/blockvol/v2bridge/*transfer*`
- `weed/storage/blockvol/v2bridge/*snapshot*`
- `weed/storage/blockvol/v2bridge/*truncate*`
### Destination
1. reusable executor orchestration in `sw-block/bridge/blockvol/runtime`
2. thin backend capability bindings in `weed/storage/blockvol/v2bridge`
### Authority Rule
The engine still owns recovery policy. This task does not move policy.
The reusable execution sequence for:
1. bounded WAL replay
2. full-base install plus second catch-up
3. snapshot transfer verification
4. truncate escalation boundary
should no longer be inseparable from direct `BlockVol` imports.
### Adapter Boundary
`weed/` may:
1. implement concrete backend operations on real `BlockVol`
2. own rebuild TCP framing and network transport while it still depends on
`blockvol` protocol types
`weed/` must not:
1. keep the whole recovery step orchestration trapped behind direct
`BlockVol` imports when capability interfaces can be extracted
2. redefine engine-visible boundary meaning
### Acceptance
1. executor reusable logic depends on extracted capability interfaces, not
direct `BlockVol` imports
2. weed-side executor code is reduced to concrete backend/network bindings
3. outcome classification still remains outside the executor layer
### Validation
1. `go test ./sw-block/bridge/blockvol`
2. `go test ./weed/storage/blockvol/v2bridge -run "TestExecutor_|TestBridge_"`
3. focused runtime integration still passes:
- `go test ./weed/server -run "TestBlockService_ApplyAssignments_(PrimaryRole_UsesCoreStartRecoveryTaskForCatchUp|RebuildingRole_UsesCoreRecoveryPathWithoutLegacyDirectStart)"`
### Current proof anchors
1. `TestContract_BlockVolReaderInterface`
2. `TestExecutor_RealBlockVol_StreamWALEntries`
3. `TestExecutor_RealBlockVol_StreamPartialRange`
4. `TestExecutor_ErrorPaths`
## Recommended Execution Order
Recommended order:
1. Task E
2. Task F
3. Task G
Reason:
1. reader extraction is lowest risk and pure read-path
2. pinner extraction adds lifecycle but still avoids policy
3. executor extraction is the largest surface and should build on the previous
two cuts
## Delivery Note
Final outcome:
1. Task E was completed by code change
2. Task F was completed by code change
3. Task G was reviewed and confirmed already clean
4. after Batch 2, `weed/server/block_recovery.go` no longer carries
reader/pinner shim types