A holder by derivation is recorded before an assignment can unsettle it (hq 170)
`assign ace postgres` made the control plane's own store unresolvable: postgres's manifest claims mesh-store, nobody was ever recorded as its holder, and with two eligible assignments and nothing on record both claimed and both were refused — novox's included. ADR 0110 says the assignment holds, by a deliberate act; ADR 0131 gave the record its force but left a seat nobody handed over held by whichever assignment happened to be alone. Before acting on an assignment the controller now writes the derived answer down: every mesh-scoped seat the store knows, resolved to exactly one holder with nothing on record, gets that holder recorded — the same record `seat <name> --to <node>/<module>` makes by hand. The next assignment able to hold the seat then stands beside the holder, eligible and silent. A seat with two derived claimants is left for a person; a seat on record is never rewritten; seats the store does not list stay held by derivation as before. And the refusal, when it still happens, names the handover that records the holder. Verified: catalogue tests against the real catalogue; the cmd suite against a store (the only failure, TestConvergingPreviewsThenChanges…, fails identically on main).
This commit is contained in:
@@ -158,3 +158,16 @@ func TestAStoreRowWithoutAProtocolKeepsTheCompiledOne(t *testing.T) {
|
||||
t.Fatalf("the store's own columns were not kept: %+v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestARefusalWithNothingOnRecordNamesTheHandover(t *testing.T) {
|
||||
busSeatDelivering(t, "mesh-bus")
|
||||
elsewhere := []Held{{Claim: "mesh-broker", Scope: ScopeMesh, Node: "anchor", Module: "old-broker"}}
|
||||
|
||||
_, problems := checkClaims([]Manifest{newBroker()}, Node{Name: "laptop"}, elsewhere, nil)
|
||||
if len(problems) != 1 {
|
||||
t.Fatalf("two derived claimants across machines were not refused: %v", problems)
|
||||
}
|
||||
if !strings.Contains(problems[0], "`seat mesh-broker --to anchor/old-broker`") {
|
||||
t.Fatalf("the refusal does not name the handover that records the holder: %s", problems[0])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -707,9 +707,14 @@ func checkClaims(modules []Manifest, node Node, elsewhere []Held, holdings []Hel
|
||||
}
|
||||
switch h.Scope {
|
||||
case ScopeMesh:
|
||||
// Both claim and nobody is on record, or this refusal could not have happened.
|
||||
// The remedy is the handover that records the holder (novox/hq ADR 0131,
|
||||
// 04-ISSUES/170), so it is named here rather than left to be found.
|
||||
problems = append(problems, fmt.Sprintf(
|
||||
"%s on %s claims %q, which %s on %s already holds — one per mesh",
|
||||
h.Module, node.Name, h.Claim, e.Module, e.Node))
|
||||
"%s on %s claims %q, which %s on %s already holds — one per mesh. Nothing is "+
|
||||
"on record for it; `seat %s --to %s/%s` records the holder, and the other "+
|
||||
"assignment then stands beside it, eligible and silent",
|
||||
h.Module, node.Name, h.Claim, e.Module, e.Node, h.Claim, e.Node, e.Module))
|
||||
case ScopeSite:
|
||||
if node.Site != "" && node.Site == e.Site {
|
||||
problems = append(problems, fmt.Sprintf(
|
||||
|
||||
Reference in New Issue
Block a user