Skip to main content

Background Jobs and the Queue

Most of the work REQQA does on your behalf is slow. Running the DeFOSPAM analysers against a requirement means one or more calls to a large language model; analysing every requirement in an application means dozens of those calls; generating stories, grouping an import, and analysing a mission all take seconds to minutes each. If REQQA tried to do that work inside the web request that triggered it, your browser would sit waiting — and time out long before the work finished.

So REQQA does not do this work in the request. Instead it queues the work as a background job, returns control to you immediately, and lets a pool of worker processes pick the job up and run it. You watch progress on the Job Queue page rather than staring at a frozen browser tab.

This page explains what that machinery is, what gets queued, and how to monitor it. You do not need to understand any of it to use REQQA — but knowing where the work happens makes the occasional wait, and the occasional failure, far easier to reason about.

Why background jobs exist

A single requirement analysis can issue a separate AI call for each analyser you've selected. The Analyse All action on the requirements list fans that out across every selected requirement at once. A mission generation run reads your mission and produces a whole hierarchy of requirements. None of these can complete in the lifetime of an HTTP request.

By moving the work onto a queue, REQQA gets three things:

  • Responsiveness — the page that started the job comes back at once with a "queued" message, not a spinner.
  • Throughput — several jobs run in parallel across multiple workers, so analysing 30 requirements does not mean waiting for them one after another.
  • Resilience — a job that fails (an AI timeout, a malformed response) fails on its own without taking your browser session, or the other jobs, down with it.

Redis Queue and the workers

REQQA's background processing is built on Redis Queue (RQ). There are two halves:

  • The queue. When you trigger a job, the controller writes a tracking row to the database, then places a job on a Redis-backed queue named defospam. The controller returns immediately. The job itself is just a reference to a runner function (for example modules.analysisJobRunner.run_requirement_analysis) plus its arguments.
  • The workers. A pool of long-running worker processes watches that queue. When a job appears, a free worker claims it, imports the runner fresh, executes it, updates the tracking row as it goes, and then waits for the next job. REQQA currently runs five workers, so up to five jobs run at the same time; anything beyond that waits in the queue until a worker frees up.
note

RQ workers and the web application are separate processes. That is by design — it's what lets analysis keep running even while you navigate away. It also means workers import your code freshly for each job, so a job always runs against the current logic.

RQ versus the py4web scheduler

py4web ships with its own built-in task scheduler, and REQQA used it in the past. That scheduler has since been retired: all of REQQA's asynchronous work now goes through RQ. You will not find a separate "scheduled tasks" surface in the application — the Job Queue page is the single place where background work is visible.

What gets queued

Not everything is a background job. Quick operations — saving a requirement, editing the mission, toggling a flag — happen inline in the request and are done before the page reloads. What goes on the queue is the expensive, AI-driven work:

Job typeWhat triggers itWhat it does
AnalysisAnalysing a single requirement, or Analyse All on a selectionRuns the chosen DeFOSPAM analyser steps (for example R-D, R-F) against each requirement and records the issues found
Reqs GenGenerating requirements from a missionReads the mission and produces a requirements hierarchy beneath it
Story GenGenerating stories for a requirementProduces user stories / Gherkin from a requirement
SynthesisSynthesising or cleaning up after analysisConsolidates and reworks requirements across a group
CSV Import (grouped / consolidated)Importing requirements with AI grouping or consolidationImports the rows, then groups or consolidates them with AI
Training GenGenerating demonstration / training dataProduces sample requirements for an organisation

For requirement analysis, the analyser steps you select map directly onto the work the job does. A requirement might be queued with a step code of R-D,R-F — that single job runs the data/definition analyser and the feature analyser in turn. Analyse All simply creates one such job per selected requirement and enqueues them all at once, which is why a bulk run can put many jobs on the queue in one click.

note

When you queue a fresh analysis for a requirement that has already been analysed, REQQA marks the previous run — and its still-open issues — as Superseded before the new job runs. The Job Queue's history reflects this: superseded runs drop out of the active list.

Monitoring on the Job Queue page

The Job Queue page is how you watch background work — and it is the right way to do it. Do not try to infer progress from the page that launched the job, and do not guess. The Job Queue shows you exactly what is queued, what is running, and what recently finished or failed, for your current application.

The page is organised around two ideas:

  • Active jobs — anything queued (waiting for a free worker) or running (a worker is on it now).
  • Recent jobs — the last several runs that have reached a terminal state: finished, Partial (some steps succeeded, some did not), failed, or Superseded.

For each row you can see the job type, its status, how many analyser steps it covers, the issue counts it produced, and — for analyses — a live progress percentage and a "current step" label as the worker moves through the steps. Each row links through to the relevant results: an analysis links to its issues, a generation job to its output, a synthesis run to its results.

tip

After you trigger an analysis or a generation, the launching page tells you the job is queued and invites you to refresh. For anything that takes more than a moment, open the Job Queue page instead — it is purpose-built to show progress and will tell you the moment a job finishes or fails, with a link straight to the result.

Progress tracking

Analysis jobs carry their own progress state, which the worker updates as it runs. The tracking row records the total number of steps, how many are complete, a progress percentage, and the name of the step currently in flight. That is what the Job Queue renders as a progress indicator — it is real progress reported by the worker, not an estimate.

When a job finishes cleanly its status becomes finished. If some steps succeeded but others failed, it ends as Partial — worth opening, because the issues that were found are still valid. A failed job produced no usable result; the most common causes are an AI timeout or an unparseable AI response, and re-running the job is usually the right next step.

What to do when a job fails

A failed job is contained — it does not affect your other jobs or your data. If you see a failed or Partial row:

  1. Open it from the Job Queue to see what, if anything, was produced.
  2. For a single requirement, simply analyse it again — a transient AI error usually clears on a retry.
  3. For a bulk run, re-select the requirements that did not complete and run Analyse All again; REQQA supersedes the earlier attempt automatically.

If failures persist across many jobs, that points at something shared — most often the organisation's AI configuration (a missing or invalid API key, or a model the account cannot reach) rather than any one requirement.