mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-09-20 13:30:46 +02:00
Finding 1: ProcessAssignments now calls v2Orchestrator.ProcessAssignment - BlockService.v2Orchestrator field (RecoveryOrchestrator) - ProcessAssignment result logged at glog V(1) - No more `_ = intent` — engine state actually changes Finding 2: localServerID documented as interim - BlockService.localServerID = listenAddr (transport-shaped) - Field doc explicitly states: INTERIM, should be registry-assigned - Used only for replica/rebuild local identity 3 integration tests (qa_block_v2bridge_test.go): - CreatesEngineSender: ProcessAssignment → engine has sender + session - EpochBump: epoch 1 → invalidate → epoch 2 → new session - AddressChange: same ServerID, different IP → sender preserved, endpoint updated Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
159 lines
4.2 KiB
Go
159 lines
4.2 KiB
Go
package weed_server
|
|
|
|
import (
|
|
"testing"
|
|
|
|
engine "github.com/seaweedfs/seaweedfs/sw-block/engine/replication"
|
|
"github.com/seaweedfs/seaweedfs/weed/storage/blockvol"
|
|
"github.com/seaweedfs/seaweedfs/weed/storage/blockvol/v2bridge"
|
|
)
|
|
|
|
func newTestControlBridge() *v2bridge.ControlBridge {
|
|
return v2bridge.NewControlBridge()
|
|
}
|
|
|
|
func newTestOrchestrator() *engine.RecoveryOrchestrator {
|
|
return engine.NewRecoveryOrchestrator()
|
|
}
|
|
|
|
// ============================================================
|
|
// Phase 08 P1: ProcessAssignments → V2 engine state tests
|
|
// Proves real assignment delivery changes engine state.
|
|
// ============================================================
|
|
|
|
func TestV2Bridge_ProcessAssignment_CreatesEngineSender(t *testing.T) {
|
|
bs := &BlockService{
|
|
v2Bridge: newTestControlBridge(),
|
|
v2Orchestrator: newTestOrchestrator(),
|
|
localServerID: "vs1:9333",
|
|
}
|
|
|
|
// Real assignment from master.
|
|
bs.ProcessAssignments([]blockvol.BlockVolumeAssignment{
|
|
{
|
|
Path: "pvc-test-1",
|
|
Epoch: 1,
|
|
Role: uint32(blockvol.RolePrimary),
|
|
ReplicaServerID: "vs2",
|
|
ReplicaDataAddr: "10.0.0.2:9333",
|
|
ReplicaCtrlAddr: "10.0.0.2:9334",
|
|
},
|
|
})
|
|
|
|
// Engine should have a sender for this replica.
|
|
orch := bs.V2Orchestrator()
|
|
sender := orch.Registry.Sender("pvc-test-1/vs2")
|
|
if sender == nil {
|
|
t.Fatal("engine should have sender for pvc-test-1/vs2 after ProcessAssignment")
|
|
}
|
|
if !sender.HasActiveSession() {
|
|
t.Fatal("sender should have active session (catch-up recovery)")
|
|
}
|
|
}
|
|
|
|
func TestV2Bridge_ProcessAssignment_EpochBump(t *testing.T) {
|
|
bs := &BlockService{
|
|
v2Bridge: newTestControlBridge(),
|
|
v2Orchestrator: newTestOrchestrator(),
|
|
localServerID: "vs1:9333",
|
|
}
|
|
|
|
// Epoch 1 assignment.
|
|
bs.ProcessAssignments([]blockvol.BlockVolumeAssignment{
|
|
{
|
|
Path: "pvc-test-1",
|
|
Epoch: 1,
|
|
Role: uint32(blockvol.RolePrimary),
|
|
ReplicaServerID: "vs2",
|
|
ReplicaDataAddr: "10.0.0.2:9333",
|
|
ReplicaCtrlAddr: "10.0.0.2:9334",
|
|
},
|
|
})
|
|
|
|
orch := bs.V2Orchestrator()
|
|
|
|
// Epoch bump.
|
|
orch.InvalidateEpoch(2)
|
|
orch.UpdateSenderEpoch("pvc-test-1/vs2", 2)
|
|
|
|
// Epoch 2 assignment.
|
|
bs.ProcessAssignments([]blockvol.BlockVolumeAssignment{
|
|
{
|
|
Path: "pvc-test-1",
|
|
Epoch: 2,
|
|
Role: uint32(blockvol.RolePrimary),
|
|
ReplicaServerID: "vs2",
|
|
ReplicaDataAddr: "10.0.0.2:9333",
|
|
ReplicaCtrlAddr: "10.0.0.2:9334",
|
|
},
|
|
})
|
|
|
|
sender := orch.Registry.Sender("pvc-test-1/vs2")
|
|
if sender == nil {
|
|
t.Fatal("sender should exist at epoch 2")
|
|
}
|
|
if !sender.HasActiveSession() {
|
|
t.Fatal("should have new session at epoch 2")
|
|
}
|
|
|
|
// Log shows invalidation.
|
|
hasInvalidation := false
|
|
for _, e := range orch.Log.EventsFor("pvc-test-1/vs2") {
|
|
if e.Event == "session_invalidated" {
|
|
hasInvalidation = true
|
|
}
|
|
}
|
|
if !hasInvalidation {
|
|
t.Fatal("log must show session invalidation on epoch bump")
|
|
}
|
|
}
|
|
|
|
func TestV2Bridge_ProcessAssignment_AddressChange(t *testing.T) {
|
|
bs := &BlockService{
|
|
v2Bridge: newTestControlBridge(),
|
|
v2Orchestrator: newTestOrchestrator(),
|
|
localServerID: "vs1:9333",
|
|
}
|
|
|
|
// First assignment.
|
|
bs.ProcessAssignments([]blockvol.BlockVolumeAssignment{
|
|
{
|
|
Path: "pvc-test-1",
|
|
Epoch: 1,
|
|
Role: uint32(blockvol.RolePrimary),
|
|
ReplicaServerID: "vs2",
|
|
ReplicaDataAddr: "10.0.0.2:9333",
|
|
ReplicaCtrlAddr: "10.0.0.2:9334",
|
|
},
|
|
})
|
|
|
|
orch := bs.V2Orchestrator()
|
|
sender := orch.Registry.Sender("pvc-test-1/vs2")
|
|
if sender == nil {
|
|
t.Fatal("sender should exist")
|
|
}
|
|
|
|
// Same ServerID, different address (address change).
|
|
bs.ProcessAssignments([]blockvol.BlockVolumeAssignment{
|
|
{
|
|
Path: "pvc-test-1",
|
|
Epoch: 1,
|
|
Role: uint32(blockvol.RolePrimary),
|
|
ReplicaServerID: "vs2",
|
|
ReplicaDataAddr: "10.0.0.5:9333", // different IP
|
|
ReplicaCtrlAddr: "10.0.0.5:9334",
|
|
},
|
|
})
|
|
|
|
// Sender identity preserved (same pointer).
|
|
senderAfter := orch.Registry.Sender("pvc-test-1/vs2")
|
|
if senderAfter != sender {
|
|
t.Fatal("sender identity must be preserved across address change")
|
|
}
|
|
|
|
// Endpoint updated.
|
|
if senderAfter.Endpoint().DataAddr != "10.0.0.5:9333" {
|
|
t.Fatalf("endpoint not updated: %s", senderAfter.Endpoint().DataAddr)
|
|
}
|
|
}
|