feat(progress): keyed Fail for a soft failure, Note for the operator, FailRunning for the job's own (ADR-035)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-02 08:53:43 +02:00
co-authored by Claude Sonnet 5.5
parent a6b8a2b744
commit 5f279d7e71
+27 -4
View File
@@ -21,11 +21,15 @@ type Planned struct {
// Reporter is what a long-running component reports to. Begin starts a phase (total
// is the number of countable units, 0 when there is no honest count), Advance says how
// many are done, Done closes the phase.
// many are done, Done closes the phase. Fail closes a phase that did not work while
// the job goes on (an engine that was down, the other one's text used instead) and
// says why in the log. Note is a log line for the operator that costs no write.
type Reporter interface {
Begin(key string, total int)
Advance(key string, done int)
Done(key string)
Fail(key string, err error)
Note(msg string, kv ...any)
}
// Sink is where a job's progress is persisted. Both calls are best effort: progress
@@ -133,9 +137,26 @@ func (t *Tracker) Done(key string) {
t.save()
}
// Fail marks the phase that was running as failed. What never started stays pending,
// which is what shows the user where the job stopped.
func (t *Tracker) Fail() {
// Fail implements Reporter: one phase failed and the job carries on.
func (t *Tracker) Fail(key string, err error) {
t.mu.Lock()
defer t.mu.Unlock()
s := t.find(key)
if s == nil {
return
}
t.close(s, domain.StepFailed)
t.log.Warn("step failed", "step", key, "elapsed", s.FinishedAt.Sub(s.StartedAt), "err", err)
t.save()
}
// Note implements Reporter.
func (t *Tracker) Note(msg string, kv ...any) { t.log.Info(msg, kv...) }
// FailRunning marks the phase that was running as failed, because the whole job
// failed. What never started stays pending, which is what shows the user where the
// job stopped.
func (t *Tracker) FailRunning() {
t.mu.Lock()
defer t.mu.Unlock()
for i := range t.steps {
@@ -244,3 +265,5 @@ type noop struct{}
func (noop) Begin(string, int) {}
func (noop) Advance(string, int) {}
func (noop) Done(string) {}
func (noop) Fail(string, error) {}
func (noop) Note(string, ...any) {}