Skip to main content

Queue jobs

Walk whole lists, import or sync, off the request, retried on failure.

Cached answers

Read the site once every few minutes, and keep serving if it’s down.

A readiness check

/health/ready fails when the site doesn’t answer.

Queue jobs

A request should answer fast. Walking every page of a list, importing a batch, or a FetchskiAI call that runs for minutes belongs in a job: @adonisjs/queue runs it in a worker and retries it when it fails.
@adonisjs/queue is still marked experimental by AdonisJS: its API may change between minor releases, so read its changelog before you update it.

Add the queue

Terminal
Pick database to keep jobs in the database your app already has (or redis). With database, it writes a migration for the jobs tables: node ace migration:run.

Write the job

Terminal
A job takes the client in its constructor, like a controller:
app/jobs/sync_blog_posts.ts
listBlogsAll() fetches one page at a time as the loop asks (Paging); put your own work where the logger.debug is.

Dispatch it, or schedule it

node ace add registered start/scheduler.ts for you. .cron('0 6 * * *') instead of .every() runs it at a set time. Keep the warmup check: node ace codegen loads this file without starting the queue, and a schedule made then throws and stops it.

Run the worker

Terminal
Jobs and schedules run only while a worker does: keep one running beside the web server in production.
The SDK retries a call that is safe to repeat (a read with no answer, a rate limit) before it throws. The queue’s maxRetries reruns the whole job after that. A write that timed out may have landed, so make a job that writes safe to run twice: check before you create.
AI routes carry their own timeout (up to 615 seconds), which the SDK applies for you. A job has no timeout unless you give it one (its timeout option, or the worker’s): keep any you set above that.
QUEUE_DRIVER=sync in .env.test runs a dispatched job at once, with the fakeAttract() fake: Testing → A queue job.

Cache the answers

Content that changes a few times a day needn’t be read on every request. With @adonisjs/cache, read it once every ten minutes, and keep serving the last answer for six hours if the site is down:

Add the cache

Terminal
It asks for a store (Redis, file, database or DynamoDB) and writes config/cache.ts.
With the file store, that file imports env without using it, which tsc refuses: delete the import env from '#start/env' line.

Cache in a service

app/services/blog_service.ts
The cache keeps plain JSON, so the factory returns the fields you show, not the model (a model’s Dates would come back as strings).

A readiness check

AdonisJS’s health checks answer /health/ready for your load balancer. Add one that asks the site a small read:

Set up health checks

Terminal
It writes start/health.ts and app/controllers/health_checks_controller.ts. Route them:
start/routes.ts
Its live() calls response.ok() without an argument, which tsc refuses: make it response.ok({ status: 'live' }).

Add the site's check

app/health_checks/attract_check.ts
start/health.ts
Pick a read your key’s scopes allow (this one needs content:blog:read). cacheFor keeps a load balancer’s frequent polls from spending the key’s rate limit.

The reference

Back to the overview, or open any method in the sidebar.