Node agent: say how it keeps each module today, held, failed or at a build of the old form named by its have's build; pin mesh-sdk f609be7 (issue 1126)

This commit is contained in:
2026-10-28 23:50:19 +01:00
parent 91686fdb81
commit abdf85aa4f
4 changed files with 34 additions and 28 deletions
+27 -21
View File
@@ -40,10 +40,11 @@ type Shadow struct {
// ran is, by module, the digest the module's have says runs: what runs, where the agent's list holds only the copy
// from the declaration kept before the switch (issue 1126, probe #532 on shanks).
ran map[string]string
// heldNow is, by module, whether its have says the node holds it today (phase held, or a build of the old form it runs
// as the controller keeps it): a candidate holding it too holds
// it as today (frombus.Scope.HeldToday, issue 1126).
heldNow map[string]bool
// heldNow is, by module, how its have says the node keeps it today as it runs: "held", "failed", or "runs a build of
// the old form" (a `build` and no `fp`, which no registered build of the trunk names); "" when it is composed as any
// other. A candidate that cannot compose it, or holds it only behind one of these, keeps it as today
// (frombus.Scope.HeldToday, issue 1126).
heldNow map[string]string
// answered is, by proposal, the candidate revisions and the input changes (moved) each answer was composed at: a proposal
// is answered again only when either moved (issue 1126, 2026-10-28: shanks answered probe/1126-seed-7 at revision 84
// every 13-17 s, woken by its own modules' haves whose health words changed at every look).
@@ -630,23 +631,20 @@ func (s *Shadow) answerProposal(ctx context.Context, proposal string) (delivery.
// heldToday is what the node holds today: each module whose have's phase is held, and what its own composer holds, the
// node's own composition ("node") among them when it composes none of its own.
func (s *Shadow) heldToday() []string {
set := map[string]bool{}
func (s *Shadow) heldToday() map[string]string {
out := map[string]string{}
s.mu.Lock()
for m, held := range s.heldNow {
if held {
set[m] = true
for m, how := range s.heldNow {
if how != "" {
out[m] = how
}
}
s.mu.Unlock()
for _, m := range s.c.heldNow() {
set[m] = true
if _, said := out[m]; !said {
out[m] = "held"
}
}
out := make([]string, 0, len(set))
for m := range set {
out = append(out, m)
}
sort.Strings(out)
return out
}
@@ -662,14 +660,22 @@ func (s *Shadow) takeRan(u agent.Update) bool {
before, had := s.ran[module]
h, err := delivery.DecodeHave(u.Value)
if s.heldNow == nil {
s.heldNow = map[string]bool{}
s.heldNow = map[string]string{}
}
wasHeld := s.heldNow[module]
// Held today: its have's phase is held, or it runs a build of the old form (not src2:), which no registered build of
// the trunk names, so the controller keeps it as it runs (issue 1126: novox's de-spiegel at build-…, its newer build
// not registered); a seed keeps it so too.
s.heldNow[module] = !u.Deleted && err == nil && h.Phase != delivery.PhaseRemoved &&
(h.Phase == delivery.PhaseHeld || (h.FP != "" && !strings.HasPrefix(h.FP, delivery.SourcePrefix2)))
s.heldNow[module] = ""
if !u.Deleted && err == nil {
switch {
case h.Phase == delivery.PhaseHeld:
s.heldNow[module] = "held"
case h.Phase == delivery.PhaseFailed:
s.heldNow[module] = "failed"
case h.Phase != delivery.PhaseRemoved && h.FP == "" && h.Build != "":
// A build of the old form: its have names a `build` and no `fp`, which no registered build of the trunk
// names, so the controller keeps it as it runs (issue 1126: novox's de-spiegel at build-…); a seed keeps it so.
s.heldNow[module] = "runs a build of the old form"
}
}
holdMoved := wasHeld != s.heldNow[module] // a hold's start or end changes the answer too
if u.Deleted || err != nil || h.Composed == "" || h.Phase == delivery.PhaseRemoved {
delete(s.ran, module)