Say a message two walks held once, in the message of the walk whose limit is due (ADR 0505 §7)
This commit is contained in:
@@ -370,3 +370,40 @@ func TestAWalkSaidAgainWithItsDeclaredMachinesActsOnce(t *testing.T) {
|
||||
t.Fatalf("its end was told %d times: %+v", n, dt.sends)
|
||||
}
|
||||
}
|
||||
|
||||
// ADR 0505 §7: a message two walks first held, the sooner of which ends at its limit, is said exactly once — in that
|
||||
// walk's end message — and not again on its own for the other walk; once per channel when it is urgent.
|
||||
func TestAMessageTwoWalksFirstHeldIsSaidOnceAtTheSoonerLimit(t *testing.T) {
|
||||
for _, sev := range []string{Warning, Urgent} {
|
||||
h, tg, dt, c, _ := newHolder(t)
|
||||
walk(t, h, "plan-a", WalkStarted, "", c.now(), 360, novox("gitea")) // its limit: 6 min and the settle
|
||||
walk(t, h, "plan-b", WalkStarted, "", c.now(), 1200, novox("mesh-issues")) // its limit: 22 min
|
||||
k := cond("machine.novox.network", sev, "novox lost its default route")
|
||||
k.Raised = c.now()
|
||||
h.Condition(EventRaised, k)
|
||||
runFor(h, c, 7*time.Minute)
|
||||
walk(t, h, "plan-a", WalkEnded, WalkDelivered, c.now(), 0) // settles until its limit, 8 min after the hold
|
||||
runFor(h, c, 3*time.Minute)
|
||||
count := func(ch *fakeChannel) int {
|
||||
n := 0
|
||||
for _, m := range ch.sends {
|
||||
if strings.Contains(m.Text(), headlineOf(k.Key)) {
|
||||
n++
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
want := map[*fakeChannel]int{dt: 1, tg: 0}
|
||||
if sev == Urgent {
|
||||
want[tg] = 1
|
||||
}
|
||||
for ch, n := range want {
|
||||
if got := count(ch); got != n {
|
||||
t.Fatalf("%s: said %d times on %s, want %d: %+v", sev, got, ch.name, n, ch.sends)
|
||||
}
|
||||
}
|
||||
if !heard("Still open after the delivery of gitea to novox:", dt) {
|
||||
t.Fatalf("%s: not told in the sooner walk's end message: %+v", sev, dt.sends)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -598,6 +598,16 @@ func (h *Holder) settledWalks(now time.Time) {
|
||||
// due tells what it holds in its message instead. Called at each flush.
|
||||
func (h *Holder) overdueHolds(now time.Time) {
|
||||
h.mu.Lock()
|
||||
// What a walk whose own end or bound is due holds is told in that walk's message, and nowhere else: one place
|
||||
// says it, so a message two walks hold is never said twice.
|
||||
tellsItself := map[string]bool{}
|
||||
for _, w := range h.walks {
|
||||
if !now.Before(w.holdEnd()) {
|
||||
for key := range w.Held {
|
||||
tellsItself[key] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
due := map[string]HeldMessage{}
|
||||
var touched []*Walk
|
||||
for _, w := range h.walks {
|
||||
@@ -607,7 +617,7 @@ func (h *Holder) overdueHolds(now time.Time) {
|
||||
}
|
||||
for key, hm := range w.Held {
|
||||
if hm.past(now) {
|
||||
if prev, ok := due[key]; !ok || hm.At.Before(prev.At) {
|
||||
if prev, ok := due[key]; !tellsItself[key] && (!ok || hm.At.Before(prev.At)) {
|
||||
due[key] = hm
|
||||
}
|
||||
delete(w.Held, key)
|
||||
|
||||
Reference in New Issue
Block a user