Repository navigation
Async Jobs
Reference for the background job queue in eagle-api. It runs long sysadmin operations off the request path. One job type exists: CSV export of a project's documents.
No API route creates a job. The API only reads jobs that already exist in the queue. To export a project's
documents, run tools/export-project-docs.js (see Files below).
Agenda (MongoDB-backed queue, agendaJobs collection)
│
▼
One pod claims the job atomically (findOneAndUpdate on lockedAt)
│
▼
exportProjectDocs() → result stored in job.attrs.data.result
│
▼
GET /api/jobs/:id/download → streams CSV
eagle-api runs several load-balanced pods, so the queue has to be shared. Agenda.js
v5 stores jobs in the existing MongoDB connection and claims each one with a single
findOneAndUpdate({lockedAt: null}), so exactly one pod runs it. No Redis or SQS to operate.
Agenda polls every 5 seconds. A pod that dies mid-job releases its claim after defaultLockLifetime
(5 minutes), and the next pod to poll retries the job.
The job type is the Agenda job name. Job data holds projectId, includeAll (default false, Published documents only), requestedBy and requestedAt. The CSV is stored inline at job.attrs.data.result.csv. Project CSVs run 50–500 KB, well under
MongoDB's 16 MB document limit.
All require a sysadmin Bearer token. A sysadmin may read any job regardless of owner; other users
only their own (api/controllers/job.js).
| Method | Path | Returns |
|---|---|---|
GET |
/api/jobs |
200 — the caller's 20 most recent jobs |
GET |
/api/jobs/{jobId} |
200 — status record |
GET |
/api/jobs/{jobId}/download |
200 text/csv; 202 if still queued or running; 422 if failed |
{
"jobId": "683f1a2b3c4d5e6f7a8b9c0d",
"type": "project-doc-export",
"status": "running",
"projectId": "588511ffaaecd9001b8291b7",
"requestedBy": "someone@example.com",
"createdAt": "2026-06-15T14:30:00.000Z",
"completedAt": null,
"progress": null,
"hasResult": false,
"filename": null
}Status is derived from the Agenda record, not stored: failed if failedAt is set, else
completed if lastFinishedAt is set, else running if lockedAt is set, else queued.
Clients poll /api/jobs/{jobId} every few seconds until status is completed or failed, then
call the download path.
Exports a project's documents to CSV. Columns:
Document Name, Legislation, Document Type, Author, Milestone, Project Phase, Document Date, Upload Date, Description, Labels
Runs in roughly 2–30 seconds depending on document count.
| File | Purpose |
|---|---|
api/helpers/jobQueue.js |
Agenda setup and job definitions |
api/controllers/job.js |
Controller: protectedOptions, listJobs, getJobStatus, downloadJobResult
|
api/helpers/export-docs-helper.js |
CSV generation, shared with the CLI tool |
api/swagger/swagger.yaml |
Route definitions under /jobs
|
tools/export-project-docs.js |
CLI wrapper |
Each document carries:
-
name— job type -
data— parameters, result, andrequestedBy -
lockedAt— when a pod claimed it; null means unclaimed -
lastFinishedAt— completion timestamp -
failedAt/failReason— error detail
Finished records stay in the collection. No route deletes them.
- Bulk Document Download — a proposed second job type
- API Architecture
Eagle Documentation
Operations
- Deployment Pipeline
- Helm Charts
- Reverse Proxy
- Rollback Procedures
- Eagle Public Release Lines
- Eagle Search Archive
- Azure Migration Strategy
- Azure Hosting
- Front Door Per-App Split
- Front Door Ban Ladder
- Error Logging
- Secrets Management
Architecture
- Architecture Overview
- API Architecture
- Analytics Architecture
- Angular Patterns
- Eagle Public Page Layout
- Eagle Public Adding A Page
- Extended Project Pages
- ENGAGE–EAGLE Integration
- BCGW Project Export
- Eagle Search
- Document Content Search
- Eagle DEMI
- Eagle DEMI Push Sweep
- Eagle DEMI Re-Push and Backfill
- Eagle Notify
- Project Data Models
- Async Jobs API
- Bulk Document Download
Configuration
Help
Repositories
Environments