fix(logs): deep-review round 3 — a failure nobody could record is one scrubbed line

- The download and edit failure lines go back after their DB write: a job the
  write could not fail is not a failed job, and the worker's child_exit line
  already says it failed.
- The download child's runner is the last stop before Python's hook: an
  escaping exception is one download.child.failed line with its chain scrubbed,
  then exit 1, instead of a raw stderr traceback carrying the URL.
- A crash the database will not record carries its stack once, and the
  fail-write line has an event code.
- The job's own generic-extractor name is taken out as a literal (formats.hiding),
  so brackets and colons in a direct link's file name no longer leak; the
  pattern stays as the fallback. `Downloading just the video <id>` is covered.
- Tests: scrubbed_stack's cause, suppress, unprintable and text-format paths,
  the image steps' failure kinds, the watchdog error through the real
  _fail_running, exact poster/storyboard messages, ffmpeg skip marker.
This commit is contained in:
2026-09-18 23:44:42 +02:00
parent 0b672ed6e7
commit 89c77ae6b5
9 changed files with 407 additions and 81 deletions
+10 -2
View File
@@ -329,10 +329,14 @@ def _report_worker_error(job_id: int, exc: Exception, cause: str, fail: Callable
already stopped it (a cancel that landed first is not a failure, `_fail_running`).
The line goes out even when failing the job raises (the database is down): as
`download.worker.error`, since the job was not failed, and the raise goes on to the caller."""
`download.worker.error`, since the job was not failed, and the raise goes on to the caller —
without `exc` as its context, which this line has already carried with its stack."""
failed = False
try:
failed = fail()
except BaseException as write_error:
write_error.__suppress_context__ = True
raise
finally:
log.error(
"job %s: worker error (%s)",
@@ -599,7 +603,11 @@ def _worker_loop(idx: int) -> None:
# re-raise. Failing the job hit the database, and letting that out would end this
# worker thread for good; boot recovery settles a job left `running`.
except Exception: # noqa: BLE001
log.exception("could not fail job %s after its crash", job_id)
log.exception(
"could not fail job %s after its crash",
job_id,
extra=logs.event("download.worker.fail_write_failed", job_id=job_id),
)
def main() -> None: