D4 (part): the builder says each run that ended on a transport fault, in its log and on its key's step (ADR 0664 §3, issue 1748)

builder_seat_queue listing asks waiting to be given again, and the claim row for a FailedUntilChanged key, are left for D4's rest.

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
This commit is contained in:
2026-11-09 22:58:12 +01:00
parent eed1738d8f
commit 397d2d120a
2 changed files with 23 additions and 1 deletions
@@ -310,7 +310,18 @@ func (b *Builder) answer(ctx context.Context, l *lane, ask sdkstep.StepAsk, aske
var firstDecline time.Time
declines := map[string]string{} // node -> why it declined, the last
for {
step, why, err := b.waitOnce(ctx, ask, again)
// Each run that ended on a transport fault is said in the log and on the key's step; the bus gives the ask again (ADR 0664 §3).
seen := buildrun.WithStepSeen(ctx, func(st sdkstep.Step) {
if st.State != sdkstep.StepAgain {
return
}
said := fmt.Sprintf("run %d of %s on %s ended on a transport fault, given again by the bus at %s: %s", st.Run, l.module, st.Node, st.AgainAt.UTC().Format(time.RFC3339), st.Reason)
b.logf("%s: %s", key, said)
if err := asked.note(ctx, ask.Language, ask.ID, said); err != nil {
b.logf("%s: the run said on the key's step could not be written: %v", key, err)
}
})
step, why, err := b.waitOnce(seen, ask, again)
switch {
case errors.Is(err, errCheck):
continue
@@ -779,8 +779,19 @@ func TestAFailedPublishOfACandidatesImageIsWrittenToTheKey(t *testing.T) { // re
t.Fatalf("candidate build = %+v", v)
}
r.bm.fails["ace/build_image_build"] = "push to the registry: connection refused"
// Issue 1748: a run of the ask that ended on a transport fault is said in the log and on the key, and is no end.
inner, log := r.asks.Answer, &logged{}
r.asks.Answer = func(a buildstep.StepAsk) buildstep.Step {
r.asks.Write(buildstep.Step{ID: a.ID, Node: "g14", State: buildstep.StepAgain, Run: 1, AgainAt: time.Now(), Reason: "lookup registry: i/o timeout"})
return inner(a)
}
r.b.Logf = log.logf
r.b.Module(context.Background(), "m", moduleValue(t, "modules/m")) // the merge: the trunk names the fingerprint
r.b.Wait()
r.asks.Answer, r.b.Logf = inner, t.Logf
if !log.has("run 1 of", "on g14 ended on a transport fault", "lookup registry: i/o timeout") {
t.Errorf("a run given again was not said: %v", log.lines)
}
v := valueOf(t, r.st, r.key)
if v.State != builds.BuildFailed || !strings.Contains(v.Error, "connection refused") || !strings.Contains(v.Error, "publish") {
t.Fatalf("build = %+v, want failed naming the publish and its reason", v)