Say a walk that waits too long, and a delivery's own stalls (hq ADR 0239)
mesh/merge-gate pass: builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step; every machine composes with the change as it…
mesh/repo-check fail: its merge-check.sh failed: FAIL
mesh/delivery delivered
mesh/delivery-group group feat/mesh-delivery-waits-said delivered: every member is delivered
mesh/merge-gate pass: builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step; every machine composes with the change as it…
mesh/repo-check fail: its merge-check.sh failed: FAIL
mesh/delivery delivered
mesh/delivery-group group feat/mesh-delivery-waits-said delivered: every member is delivered
A walk mesh-delivery never lets go waited for ever with nothing open: S16 says it at 30 minutes, urgent at 4 hours, naming plans go. Phase B: probe D14 reads the delivery owner's stalled and raises delivery.<id>.stalled, and H2 takes the table's transition through its close.
This commit is contained in:
@@ -75,6 +75,11 @@ const (
|
||||
staleRefusalsWithin = 5 * time.Minute
|
||||
// leaseBound is how long the lease may go unrenewed (S12): the key's age.
|
||||
leaseBound = broker.LeaseTTL
|
||||
// waitBound is how long a walk may wait for its delivery's word before it is said, and waitUrgentAfter
|
||||
// before it is urgent (S16, novox/hq ADR 0239): a group member may wait behind another for a while; four
|
||||
// hours without a word is the delivery's owner broken, whatever it says of itself.
|
||||
waitBound = 30 * time.Minute
|
||||
waitUrgentAfter = 4 * time.Hour
|
||||
)
|
||||
|
||||
// callBounds are the verbs that may run longer than callDefault, and how long (S7).
|
||||
@@ -195,6 +200,15 @@ var signalsTable = []signalRow{
|
||||
newest: func(f *signalFacts) time.Time {
|
||||
return newestOf(f.handActs, func(a link.HandAct) time.Time { return a.At })
|
||||
}},
|
||||
{Row: "S16", Signal: "a walk waiting for its delivery's word is let go", Emitter: "mesh-delivery, through deliver",
|
||||
Trigger: "each merge whose walk waits (novox/hq ADR 0239)",
|
||||
Bound: "30 min, then urgent after 4 h — raised by the controller whatever mesh-delivery says of itself, " +
|
||||
"naming `plans go` as the way on",
|
||||
Kind: kindWalkWaiting, Severity: conditions.Warning, Phase: 3,
|
||||
needs: func(f *signalFacts) error { return f.plansErr }, watch: watchWaits,
|
||||
newest: func(f *signalFacts) time.Time {
|
||||
return newestOf(f.waits, func(w waitFacts) time.Time { return w.since })
|
||||
}},
|
||||
}
|
||||
|
||||
// watchFacts is S14: the snapshot a merge check is fed is older than its bound, or none was kept since
|
||||
@@ -317,6 +331,33 @@ func watchPlans(f *signalFacts) []conditions.Observation {
|
||||
return out
|
||||
}
|
||||
|
||||
// kindWalkWaiting is S16's kind: plan.<id>.waiting.
|
||||
const kindWalkWaiting = "waiting"
|
||||
|
||||
// watchWaits is S16: a walk that has waited for its delivery's word past its bound, said by the controller
|
||||
// itself — a delivery's owner that is up and never says go (a bug, a delivery stuck in its own table) would
|
||||
// otherwise leave a merge waiting for ever with nothing open (novox/hq ADR 0239).
|
||||
func watchWaits(f *signalFacts) []conditions.Observation {
|
||||
var out []conditions.Observation
|
||||
for _, w := range f.waits {
|
||||
in := f.now.Sub(w.since)
|
||||
if in <= waitBound {
|
||||
continue
|
||||
}
|
||||
severity := conditions.Warning
|
||||
if in > waitUrgentAfter {
|
||||
severity = conditions.Urgent
|
||||
}
|
||||
out = append(out, conditions.Observation{Scope: conditions.ScopePlan, ID: w.id, Kind: kindWalkWaiting,
|
||||
Severity: severity,
|
||||
Summary: fmt.Sprintf("the walk of %s %s has waited %s for %s's word to start: `mesh-delivery.show` for the "+
|
||||
"delivery that landed as %s says why; `plans go %s --why …` starts it by hand", w.repository,
|
||||
short(w.commit), ago(in), w.awaits, short(w.commit), w.id),
|
||||
Said: fmt.Sprintf("waiting since %s for %s", w.since.UTC().Format(time.RFC3339), w.awaits)})
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func watchLoop(f *signalFacts) []conditions.Observation {
|
||||
if f.loop.pending == 0 {
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user