Skip to content

Jobs and logs

/jobs. Everything the machine has been asked to do for you — extractions, AI article drafts, card runs — with the step log and, when one stops, why.

This is the record that outlives the tab. A panel that polls a job inside a component says what happened and takes the message with it when you navigate away; the reason a job failed is kept here.

What is in the list

Your own jobs, from any browser or session: the last 20, newest first.

Each row: the title, the status, the step count, the last step, and — for a failure — the reason. Open the log to read every step, with the per-chunk extraction summaries and any questions that were skipped because no correct answer could be found.

Control Does
Log The full step list, polled every 3 s while the job is running
Cancel Only while it is genuinely running
Forget Takes the row off your list

Forget stops nothing and deletes nothing. A job is a record of work, not the work itself: forgetting one clears a line somebody has already dealt with so the ones they have not are not buried under it. The steps and status go with it, but the job's claim is kept, so forgetting is not permission for a redelivery to run the work again.

Only from your own list. An id alone is not authority to touch anybody else's, and the keys behind it are shared.

How long the record lasts

Redis, throughout, under extraction:* keys — the prefix predates articles, cards and diagrams using the same machinery, and renaming it would strand every job in flight at the moment of deploy.

While running 1 hour, refreshed by the job's own writes
Once stopped 24 hours
The list itself 24 hours
Heartbeat believed for 15 minutes after its last refresh

The two retentions were once different numbers — the record went at an hour and the list at a day — so a job that ended at ten was a dangling id by eleven: the read said unknown, the list skipped the row, and a failure nobody happened to be watching for left nothing behind at all.

"The worker handling this stopped before it finished"

The one message worth recognising.

failed is written in an except, and an except needs the process to still be there. A worker killed by the OOM reaper, or recreated by a deploy mid-extraction, leaves running in Redis for ever.

So every job beats while it works, and the rule is applied on the reading side: status running with no heartbeat means the worker went with it. The first reader writes that back as a failure, so every list agrees about it and the next reader is not asked to work it out again.

The message says: "The worker handling this stopped before it finished — most likely it was restarted. Nothing was left half-saved; start it again when you are ready."

Fifteen minutes is generous on purpose: the gap between two steps is a model call, and extracting a fifty-page chunk or drawing a diagram can take minutes. Calling a slow job dead is worse than calling a dead job slow.

Jobs do not run twice

Celery redelivers on a broker reconnect, and nothing stopped a second delivery of the same id from making a second batch of drafts or a second article. A job now claims its id with a Redis SET NX before it does anything; the second delivery finds it taken and returns.

Reaching the log from elsewhere

  • The extraction panel on a document links here if it finishes without recording a batch.
  • The AI draft panel in Editorial names this page when a draft fails.
  • Settings → Tools has a Jobs card, and the workbench has a Jobs and logs link.

There is no badge in the site header any more. It polled every thirty seconds, on every page, for everybody, for a number almost nobody had a use for.

Two vestiges

GET /quizzes/job/{job_id} is moderator-gated while the list at GET /quizzes/jobs is open to any signed-in user; in practice only moderators start jobs. And a completed job's row still offers Open Quiz for a quiz_id — extraction lands in a draft batch now, and the field is only read for jobs that ran before that change and whose keys are still in Redis.

Underneath

The Celery services, the beat schedule and the one scheduled job that destroys anything are in Background work.