more refactoring
Some checks failed
Build and Publish / BuildAndDeploy (push) Successful in 3m6s
Build and Publish / BuildAndDeployAmd64 (push) Has been cancelled

This commit is contained in:
matst80
2025-10-10 13:22:36 +00:00
parent c30be581cd
commit 159253b8b0
13 changed files with 1475 additions and 295 deletions

View File

@@ -81,13 +81,17 @@ func TestMultiNodeOwnershipNegotiation(t *testing.T) {
link(syncedA, hostB, addrB)
link(syncedB, hostA, addrA)
// Rebuild rings after manual cross-link so deterministic ownership works immediately.
syncedA.ForceRingRefresh()
syncedB.ForceRingRefresh()
// Allow brief stabilization (control plane pings / no real negotiation needed here).
time.Sleep(200 * time.Millisecond)
// Create a deterministic cart id for test readability.
cartID := ToCartId(fmt.Sprintf("cart-%d", time.Now().UnixNano()))
// Mutation payload (local ownership claim expected on nodeA).
// Mutation payload (ring-determined ownership; no assumption about which node owns).
addItem := &messages.AddItem{
ItemId: 1,
Quantity: 1,
@@ -101,31 +105,53 @@ func TestMultiNodeOwnershipNegotiation(t *testing.T) {
Country: "se",
}
// Apply mutation on nodeA (should create local grain + claim ownership).
if _, err := syncedA.Apply(cartID, addItem); err != nil {
t.Fatalf("nodeA Apply addItem error: %v", err)
// Determine ring owner and set primary / secondary references.
ownerHost := syncedA.DebugOwnerHost(cartID)
var ownerSynced, otherSynced *SyncedPool
var ownerPool, otherPool *GrainLocalPool
switch ownerHost {
case hostA:
ownerSynced, ownerPool = syncedA, poolA
otherSynced, otherPool = syncedB, poolB
case hostB:
ownerSynced, ownerPool = syncedB, poolB
otherSynced, otherPool = syncedA, poolA
default:
t.Fatalf("unexpected ring owner %s (expected %s or %s)", ownerHost, hostA, hostB)
}
// Validate nodeA local pool has the grain.
if _, ok := poolA.grains[cartID]; !ok {
t.Fatalf("nodeA expected local grain ownership but grain missing")
// Apply mutation on the ring-designated owner.
if _, err := ownerSynced.Apply(cartID, addItem); err != nil {
t.Fatalf("owner %s Apply addItem error: %v", ownerHost, err)
}
// Attempt to mutate same cart from nodeB (should route remotely, not create local duplication).
// Validate owner pool has the grain and the other does not.
if _, ok := ownerPool.GetGrains()[cartID]; !ok {
t.Fatalf("expected owner %s to have local grain", ownerHost)
}
if _, ok := otherPool.GetGrains()[cartID]; ok {
t.Fatalf("non-owner unexpectedly holds local grain")
}
// Prepare change mutation to be applied from the non-owner (should route remotely).
change := &messages.ChangeQuantity{
Id: 1, // line id is 1 after first AddItem
Id: 1, // line id after first AddItem
Quantity: 2,
}
// Apply on nodeB; if ownership logic works, this will call remote RPC and succeed without creating a local grain.
if _, err := syncedB.Apply(cartID, change); err != nil {
t.Fatalf("nodeB remote Apply changeQuantity error: %v", err)
// Apply remotely via the non-owner.
if _, err := otherSynced.Apply(cartID, change); err != nil {
t.Fatalf("non-owner remote Apply changeQuantity error: %v", err)
}
// NodeB should NOT have a local grain (ownership), but may or may not have a remote proxy
// entry in remoteIndex depending on internal propagation. We assert it does NOT hold local.
if _, local := poolB.grains[cartID]; local {
t.Fatalf("nodeB unexpectedly created local grain (ownership duplication)")
// Remote re-mutation already performed via otherSynced; removed duplicate block.
// NodeB local grain assertion:
// Only assert absence if nodeB is NOT the ring-designated owner. If nodeB is the owner,
// it is expected to have a local grain (previous generic ownership assertions already ran).
if ownerHost != hostB {
if _, local := poolB.GetGrains()[cartID]; local {
t.Fatalf("nodeB unexpectedly created local grain (ownership duplication)")
}
}
// Fetch state from nodeB to ensure we see updated quantity (2).