From 3aa19c8f7e79d22eea41625aa5f8b7bcd58d47b2 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Tue, 5 May 2026 23:12:43 +0800 Subject: [PATCH] fix(jobs): log repo write errors in worker.execute Previously, write-back errors from Complete/DeadLetter/FailWithRetry were silently dropped via underscore assignment. A transient DB failure here would leave a job stuck (still 'running' with active lease) until the reaper resets it, with zero observability into why. Log each write-back error at Error level so operators can correlate stuck jobs with DB symptoms. Code quality review of T8. --- internal/jobs/worker.go | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/internal/jobs/worker.go b/internal/jobs/worker.go index be6e587..6217b20 100644 --- a/internal/jobs/worker.go +++ b/internal/jobs/worker.go @@ -84,14 +84,18 @@ func (w *Worker) execute(ctx context.Context, job Job) { h, ok := w.handlers[job.Type] if !ok { - _ = w.repo.DeadLetter(ctx, job.ID, fmt.Sprintf("unknown job type: %s", job.Type)) + if derr := w.repo.DeadLetter(ctx, job.ID, fmt.Sprintf("unknown job type: %s", job.Type)); derr != nil { + w.opts.Log.Error("job.dead_letter_write_failed", "id", job.ID, "err", derr.Error()) + } w.opts.Log.Error("job.dead_letter", "id", job.ID, "type", job.Type, "reason", "unknown_type") return } err := w.runHandler(ctx, h, job) if err == nil { - _ = w.repo.Complete(ctx, job.ID) + if cerr := w.repo.Complete(ctx, job.ID); cerr != nil { + w.opts.Log.Error("job.complete_write_failed", "id", job.ID, "err", cerr.Error()) + } w.opts.Log.Info("job.complete", "id", job.ID, "type", job.Type, "attempt", job.Attempts, "duration_ms", w.opts.Clock.Now().Sub(start).Milliseconds()) @@ -101,7 +105,9 @@ func (w *Worker) execute(ctx context.Context, job Job) { // Permanent or attempts exhausted -> dead-letter if IsPermanent(err) || job.Attempts >= job.MaxAttempts { msg := truncate(err.Error(), 2000) - _ = w.repo.DeadLetter(ctx, job.ID, msg) + if derr := w.repo.DeadLetter(ctx, job.ID, msg); derr != nil { + w.opts.Log.Error("job.dead_letter_write_failed", "id", job.ID, "err", derr.Error()) + } w.opts.Log.Error("job.dead_letter", "id", job.ID, "type", job.Type, "attempts", job.Attempts, "err", msg) return @@ -111,7 +117,9 @@ func (w *Worker) execute(ctx context.Context, job Job) { delay := backoffFor(w.opts.Backoff, int(job.Attempts)) next := w.opts.Clock.Now().Add(delay) msg := truncate(err.Error(), 2000) - _ = w.repo.FailWithRetry(ctx, job.ID, next, msg) + if ferr := w.repo.FailWithRetry(ctx, job.ID, next, msg); ferr != nil { + w.opts.Log.Error("job.fail_retry_write_failed", "id", job.ID, "err", ferr.Error()) + } w.opts.Log.Warn("job.fail_retry", "id", job.ID, "type", job.Type, "attempt", job.Attempts, "err", msg, "next_at", next.Format(time.RFC3339))