diff --git a/internal/progress/tracker.go b/internal/progress/tracker.go index 0c6e0d0..f3e94c7 100644 --- a/internal/progress/tracker.go +++ b/internal/progress/tracker.go @@ -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) {}