Leave moving the plans after a build's outcome to the look in the serving controller, so a release's retried send no longer runs on the event loop (issue 1708)
This commit is contained in:
@@ -104,3 +104,39 @@ func TestTheRecordsSettleAnOutcomeWithWhatTheBuildDid(t *testing.T) {
|
|||||||
t.Fatalf("an outcome's words were kept for a second settle: %q", got)
|
t.Fatalf("an outcome's words were kept for a second settle: %q", got)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 1708/AC5: given a serving controller (its look at the plans running), when an outcome was taken into the plans,
|
||||||
|
// then moving them (a release's sends, which may retry for minutes) is left to the look, off the event loop
|
||||||
|
// (2026-10-21 14:28:40 to 14:32:10: the loop sent okioki's release to g14 after mesh-delivery-builder's outcome).
|
||||||
|
func TestAnOutcomeLeavesMovingThePlansToTheLook(t *testing.T) {
|
||||||
|
l := withLooker(t)
|
||||||
|
moved := false
|
||||||
|
advanceAfterOutcome(func() { moved = true })
|
||||||
|
if moved {
|
||||||
|
t.Fatal("the plans were moved on the event loop after an outcome, where a send that retries holds every message")
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case <-l.signal:
|
||||||
|
default:
|
||||||
|
t.Fatal("the look was not asked to move the plans after an outcome")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1708/AC5: given no look running (a command, which has no event loop), when an outcome was taken, then the plans are
|
||||||
|
// moved at once, as before.
|
||||||
|
func TestAnOutcomeMovesThePlansWhereNoLookRuns(t *testing.T) {
|
||||||
|
lookerMu.Lock()
|
||||||
|
before := theLooker
|
||||||
|
theLooker = nil
|
||||||
|
lookerMu.Unlock()
|
||||||
|
t.Cleanup(func() {
|
||||||
|
lookerMu.Lock()
|
||||||
|
theLooker = before
|
||||||
|
lookerMu.Unlock()
|
||||||
|
})
|
||||||
|
moved := false
|
||||||
|
advanceAfterOutcome(func() { moved = true })
|
||||||
|
if !moved {
|
||||||
|
t.Fatal("with no look running, an outcome left the plans unmoved")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -136,6 +136,18 @@ func askToLook() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// askedToLook asks the serving controller's look at the plans, and says whether there was one to ask.
|
||||||
|
func askedToLook() bool {
|
||||||
|
lookerMu.RLock()
|
||||||
|
l := theLooker
|
||||||
|
lookerMu.RUnlock()
|
||||||
|
if l == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
l.ask()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// startPlanLooks starts the look at the open plans, and asks for the first: the controller took the lease, and a
|
// startPlanLooks starts the look at the open plans, and asks for the first: the controller took the lease, and a
|
||||||
// plan left by a replaced controller resumes from there (ADR 0406 §6). It replaces the rollout's 30 second ticker.
|
// plan left by a replaced controller resumes from there (ADR 0406 §6). It replaces the rollout's 30 second ticker.
|
||||||
// It answers a channel that is closed once the look has returned after the context ended, for a test that restores what
|
// It answers a channel that is closed once the look has returned after the context ended, for a test that restores what
|
||||||
|
|||||||
@@ -761,7 +761,19 @@ func planBuiltSaying(ctx context.Context, open *stores, module, commit, failed s
|
|||||||
fmt.Printf("%s: %s; the tiers after it are not asked\n", p.ID, p.Note)
|
fmt.Printf("%s: %s; the tiers after it are not asked\n", p.ID, p.Note)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
advanceHeld(ctx, open)
|
advanceAfterOutcome(func() { advanceHeld(ctx, open) })
|
||||||
|
}
|
||||||
|
|
||||||
|
// advanceAfterOutcome moves the plans after an outcome was taken into them: **in the serving controller, by asking
|
||||||
|
// the look** (novox/hq issue 1708). The outcome is taken on the event loop, and moving the plans may send machines
|
||||||
|
// their declarations, a release's send retried for minutes among them; done here it held every report, build and
|
||||||
|
// merge behind it (2026-10-21 14:28:40 to 14:32:10). The look runs off the loop, holding the plans itself. Where no
|
||||||
|
// look runs (a command, which has no event loop) the plans are moved at once, as before.
|
||||||
|
func advanceAfterOutcome(advance func()) {
|
||||||
|
if askedToLook() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
advance()
|
||||||
}
|
}
|
||||||
|
|
||||||
// startedBeside is the id of a started walk open beside this one that it is related to — a merge's walk past
|
// startedBeside is the id of a started walk open beside this one that it is related to — a merge's walk past
|
||||||
|
|||||||
Reference in New Issue
Block a user