No build reaches a machine without a gate; a release plan walks what waits (hq ADR 0236)
A send carries the machine's whole declaration, so at the switch to roll the next send of anything would have carried the old default's backlog, unjudged, to every machine. A gated send now carries and judges everything waiting on its machine; every other send is refused or leaves the machine; a release plan walks what waits one machine at a time, the control node last, and one that fails holds the next until a person releases it.
This commit is contained in:
@@ -476,6 +476,10 @@ func advancePlans(ctx context.Context, open *stores) {
|
||||
return
|
||||
}
|
||||
defer release()
|
||||
// What waits for a gate, released one machine at a time (ADR 0236).
|
||||
if _, err := releaseBacklog(ctx, open, ""); err != nil {
|
||||
fmt.Printf("plans: what waits for a gate could not be looked at: %v\n", err)
|
||||
}
|
||||
advanceHeld(ctx, open)
|
||||
}
|
||||
|
||||
@@ -531,6 +535,9 @@ func advanceHeld(ctx context.Context, open *stores) {
|
||||
func advanceOnce(ctx context.Context, open *stores, p *inventory.Plan,
|
||||
edges []inventory.Edge, rollsOut func(string) bool) (bool, error) {
|
||||
inv := open.inventory
|
||||
if p.Release != nil {
|
||||
return advanceRelease(ctx, open, p)
|
||||
}
|
||||
if p.Tier >= len(p.Tiers) {
|
||||
p.State = inventory.PlanDone
|
||||
fmt.Printf("%s: done — %s at %s, %d tier(s)\n", p.ID, p.Repository, short(p.Commit), len(p.Tiers))
|
||||
@@ -631,6 +638,9 @@ func advanceOnce(ctx context.Context, open *stores, p *inventory.Plan,
|
||||
// The first machine refused or failed what it was sent, or never said: the gate failed, and
|
||||
// the build is put back there (novox/hq ADR 0236); the rest are left as they were.
|
||||
gateFailed(ctx, open, p, m, state, firstRunning(state.First, running), step.failed)
|
||||
if state.Gate != nil && len(state.Gate.Carried) > 0 {
|
||||
failCarried(ctx, open, p, state.Gate, m)
|
||||
}
|
||||
p.Note += fmt.Sprintf("; %s left as it was", orNone(strings.Join(step.rest, ", ")))
|
||||
fmt.Printf("%s: %s\n", p.ID, p.Note)
|
||||
return true, nil
|
||||
@@ -653,6 +663,9 @@ func advanceOnce(ctx context.Context, open *stores, p *inventory.Plan,
|
||||
continue
|
||||
case inventory.GateFailed:
|
||||
gateFailed(ctx, open, p, m, state, state.Gate.Machines, state.Gate.Why)
|
||||
if len(state.Gate.Carried) > 0 {
|
||||
failCarried(ctx, open, p, state.Gate, m)
|
||||
}
|
||||
p.Note += fmt.Sprintf("; %s left as it was", orNone(strings.Join(step.rest, ", ")))
|
||||
fmt.Printf("%s: %s\n", p.ID, p.Note)
|
||||
return true, nil
|
||||
@@ -677,7 +690,20 @@ func advanceOnce(ctx context.Context, open *stores, p *inventory.Plan,
|
||||
}
|
||||
// What sendToEach answers, not what was asked: the machine holding the bus is sent before
|
||||
// the first when its user list must change (issue 249), and the plan waits for it too.
|
||||
sent, err := sendRollout(ctx, open, step.send)
|
||||
var sent []string
|
||||
var carried []inventory.CarriedMove
|
||||
switch {
|
||||
case step.first:
|
||||
// **A gated send** (ADR 0236): everything waiting on the first machine goes with the build,
|
||||
// and the gate judges all of it there.
|
||||
own := inventory.CarriedMove{Module: m, Node: step.send[0], From: before[m], To: state.Commit, Build: state.Build}
|
||||
carried, sent, err = gatedSend(ctx, open, step.send[0], &own)
|
||||
case policy.Together:
|
||||
sent, err = sendRollout(withScope(ctx, sendScope{modules: map[string]bool{m: true}}), open, step.send)
|
||||
default:
|
||||
// The rest, after the gate passed: nothing else may move with it that no gate has seen.
|
||||
sent, err = sendRollout(ctx, open, step.send)
|
||||
}
|
||||
if err != nil {
|
||||
// Not marked sent, so the next step tries again (issue 249): a grant that could not be
|
||||
// issued is a send that did not happen.
|
||||
@@ -690,6 +716,8 @@ func advanceOnce(ctx context.Context, open *stores, p *inventory.Plan,
|
||||
}
|
||||
state.First = sent
|
||||
state.FirstAt = &now
|
||||
state.Gate = &inventory.PlanGate{Component: coreComponent(m), Machines: firstRunning(sent, running),
|
||||
From: state.Previous, To: state.Commit, Since: &now, Carried: carried}
|
||||
p.State = inventory.PlanRolling
|
||||
p.Note = fmt.Sprintf("tier %d built; sent %s to %s first", p.Tier, m, strings.Join(sent, ", "))
|
||||
fmt.Printf("%s: tier %d built; sent %s to %s first, the rest once it reports it applied\n",
|
||||
@@ -1059,6 +1087,18 @@ func plansCommand(ctx context.Context, args []string) error {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("%s — %s\n", p.ID, planLineWith(p, now, buildSeatPause(ctx, inv, []inventory.Plan{p})))
|
||||
if r := p.Release; r != nil {
|
||||
// A release plan's walk (ADR 0236): machines done, the one judged, those to come.
|
||||
fmt.Printf(" machines in order: %s; done: %s; skipped: %s\n", strings.Join(r.Order, ", "),
|
||||
orNone(strings.Join(r.Done, ", ")), orNone(strings.Join(r.Skipped, ", ")))
|
||||
if r.Gate != nil {
|
||||
fmt.Printf(" %s\n", gateLine(r.Gate))
|
||||
for _, c := range r.Gate.Carried {
|
||||
fmt.Printf(" %-22s %s → %s\n", c.Module, short(c.From), short(c.To))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
for i, tier := range p.Tiers {
|
||||
marker := " "
|
||||
if i == p.Tier && p.Open() {
|
||||
|
||||
Reference in New Issue
Block a user