Let a recorded module's move that restarts nothing roll out with its walk (issue 785)

Under a module's own record (its manifest's, or its irreplaceable data's), every
move waited for a person's push, even one that only changed a tools bundle: the
database server stayed behind on ace on 2026-10-15 although its walk said it
recreated none of its containers. ADR 0377 lets such a move roll out.

A move is judged per machine against the build that machine was last sent: it
goes when no container, mounted file, data path, data declaration, provider or
(for a module with data) long-running process changes. A person's record, the
bus and any move that cannot be judged still wait. The walk keeps per machine
which way each recorded module went and why, says it in its note and log, and
status names a machine behind with `push <node>` only for a move that waits.
This commit is contained in:
jochen
2026-10-15 14:27:37 +02:00
parent f7928a2bf7
commit 0d1bb035cb
16 changed files with 1003 additions and 8 deletions
+12 -1
View File
@@ -1476,6 +1476,16 @@ type CurrentBuild struct {
Commit string
// RollOut is the module's upgrade policy, as Upgrade.RollOut.
RollOut bool
// From is where the policy came from, as Upgrade.From: a move under a module's own `record` — its manifest's or
// its irreplaceable data's — rolls out when it recreates nothing and moves no data (novox/hq ADR 0377), one under
// a person's or the bus's never does.
From string
}
// OwnRecord is whether a module records because its manifest says so or because it keeps irreplaceable data
// (novox/hq ADR 0377 §1): the `record` whose moves that recreate nothing roll out.
func (b CurrentBuild) OwnRecord() bool {
return !b.RollOut && (b.From == catalogue.FromModule || b.From == catalogue.FromData)
}
// CurrentBuilds is every module's current build and upgrade policy, in one read: what a send records
@@ -1497,7 +1507,8 @@ func (i *Inventory) CurrentBuilds(ctx context.Context) (map[string]CurrentBuild,
if err := rows.Scan(&name, &b.Commit, &chosen, &together, &why, &by, &manifest); err != nil {
return nil, err
}
b.RollOut = upgradeFrom(chosen, together, why, by, manifest).RollOut
u := upgradeFrom(chosen, together, why, by, manifest)
b.RollOut, b.From = u.RollOut, u.From
out[name] = b
}
return out, rows.Err()
+5
View File
@@ -313,6 +313,11 @@ type PlanModule struct {
// Rest is, per machine of the rest, the declaration the send after the first-node gate carried there (novox/hq ADR
// 0282 decision 6): the machine's first report of it, applied, is when the build runs there.
Rest map[string]SentDeclaration `json:"rest,omitempty"`
// Recorded is, for a module whose policy records, per machine running it with a move, which way the walk took it
// (novox/hq ADR 0377 §6): "went out: …" when the move recreates none of its containers and moves none of its
// data, or "waits: …" with the recreate words, the data change named, the person's or the bus's hold, or why it
// could not be judged.
Recorded map[string]string `json:"recorded,omitempty"`
}
// PlanGate is one module's rollout record at its gate (to-be 45 §8): the component, the first machine,
+2 -2
View File
@@ -73,10 +73,10 @@ func TestTheCurrentBuildsAreTheCatalogues(t *testing.T) {
t.Fatal(err)
}
// Rolled out by default, one machine first and gated (novox/hq ADR 0236).
if got := current["resolver"]; got != (CurrentBuild{Commit: "c1", RollOut: true}) {
if got := current["resolver"]; got != (CurrentBuild{Commit: "c1", RollOut: true, From: catalogue.FromDefault}) {
t.Errorf("resolver is at %+v", got)
}
if got := current["by-hand"]; got != (CurrentBuild{RollOut: true}) {
if got := current["by-hand"]; got != (CurrentBuild{RollOut: true, From: catalogue.FromPerson}) {
t.Errorf("a module with no source is at %+v", got)
}
}