Once chain_moved records the kind, a plan is a key of the rollouts bucket under its id and the open batch is the same key in state assembling. A save refuses a copy another save moved since (the plan's own Revision, kept in its value, counts saves) and keeps the merges the record holds, so a copy read before a merge moved cannot lay it back. The merges a batch or walk answers are the record's held field, with the columns the table had; a merge no plan answers stays, flagged, in the record that held it last, or in the record kept for those. A merge moved to a plan is written to the receiving record first and then taken from the giving one; one found in both is read from the one it entered last and repaired at the next cut. Plans and merges are read from a view kept by one watch of the bucket. A bus that does not answer, a lease lost and a key moved are now not-now like the store being away, so a merge whose plan could not be written is held and handed over again, never acknowledged. The start moves release_plan and batched_merge into the bucket, one kind, counted against both tables.
27 lines
1.0 KiB
Go
27 lines
1.0 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"testing"
|
|
|
|
"github.com/novox/mesh-controller/internal/link"
|
|
)
|
|
|
|
// **A merge whose plan could not be saved is held, never taken** (novox/hq ADR 0407 decision 3, issue 1092): the merge is
|
|
// carried until its plan is saved, and the bus acknowledges the announcement only when the controller answers without
|
|
// ErrTryAgain (link.Server.sourceMoved), so a failed save of any kind must answer it.
|
|
func TestAFailureToSaveAMergesPlanIsHeldAndNotTaken(t *testing.T) {
|
|
cause := errors.New("the plan for novox/mesh-catalog is not written: the plan was written by somebody else since it was read")
|
|
held := unsaved(cause)
|
|
if !errors.Is(held, link.ErrTryAgain) || !errors.Is(held, cause) {
|
|
t.Fatalf("a failed save answers %v", held)
|
|
}
|
|
if unsaved(nil) != nil {
|
|
t.Fatal("a save that worked answers an error")
|
|
}
|
|
// Not the same as notNow, which holds a merge only for a store that is away.
|
|
if errors.Is(notNow(cause), link.ErrTryAgain) {
|
|
t.Fatal("notNow holds every failure; the premise of this test is gone")
|
|
}
|
|
}
|