A seat is handed over as one act, and the holder is on record
`seat <name> --to <node>/<module>` makes one assignment the holder of a seat in the same write that removes the previous one. The row is new (migration 0039); without one, the resolver derives the holder as it always did — the sole eligible assignment, two refused — so nothing changes for a mesh that never hands a seat over. With one, the recorded assignment holds and any other whose module could hold the seat is eligible and silent: not refused, not holding. That is what lets the next holder run beside the current one until the switch (hq design 26, design 28 task 5.3, ADR 0131). Why: the controller finds its own bus through a seat, and the day that seat was left with nobody in it — because two eligible holders could not coexist and the old one's claim was taken away — the control plane looped for two hours while every service stayed up. A handover that is never empty in between is the fix, not a workaround for it. `CanHold` is the one judgement of whether a module may hold a seat — claims it at its scope, provides what it delivers, against the store's row — shared by registration and the handover so they cannot drift apart. The holding belongs to the assignment and goes when it does, so a seat never points at nothing running. Tests: the resolver with and without a record, on the same and another machine, under a former name; the store's row replaced not added, refused for an unassigned target, removed with its assignment; CanHold's four answers and that they follow the store. Full suite green against a real NATS and store.
This commit is contained in:
@@ -222,6 +222,31 @@ func claimProblems(m Manifest) []string {
|
||||
return problems
|
||||
}
|
||||
|
||||
// CanHold is why a module could not hold a seat, or nothing: its definition must claim the seat at
|
||||
// the seat's scope, and provide what the seat delivers, if it delivers anything. The seat is the
|
||||
// store's row, so this is judged only where the store's set is loaded — at registration and in the
|
||||
// handover command (novox/hq ADR 0131), never in the parser.
|
||||
func CanHold(m Manifest, seat Seat) error {
|
||||
var claimed *Claim
|
||||
for i := range m.Claims {
|
||||
if hs, ok := SeatNamed(m.Claims[i].Name); ok && hs.Name == seat.Name {
|
||||
claimed = &m.Claims[i]
|
||||
}
|
||||
}
|
||||
if claimed == nil {
|
||||
return fmt.Errorf("%s does not claim %s", m.Module, seat.Name)
|
||||
}
|
||||
if claimed.At() != seat.Scope {
|
||||
return fmt.Errorf("%s claims %s at scope %q, and %s is a %s seat",
|
||||
m.Module, seat.Name, claimed.At(), seat.Name, seat.Scope)
|
||||
}
|
||||
if seat.Delivers != "" && !providesAt(m, seat.Delivers, seat.Scope) {
|
||||
return fmt.Errorf("%s claims %s, whose holder answers for %q, and %s does not provide %q at %s scope",
|
||||
m.Module, seat.Name, seat.Delivers, m.Module, seat.Delivers, seat.Scope)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func providesAt(m Manifest, provision, scope string) bool {
|
||||
for _, o := range m.Provides {
|
||||
if o.Name == provision && o.At() == scope {
|
||||
|
||||
Reference in New Issue
Block a user