nuxt-queuekit
v2.0.4
Published
Background job queue for Nuxt applications powered by BullMQ and Redis
Downloads
30
Maintainers
Readme
Nuxt Queue
Background job queue for Nuxt applications, powered by BullMQ and Redis.
Table of Contents
- What You Get
- Quick Start
- Core Workflow
- Monitor and Control Jobs
- Configuration
- Production
- API Reference
- Troubleshooting
What You Get
- File-based jobs (
server/jobs/**) with auto-discovery - Separate worker process for background execution
- Redis-backed queues via BullMQ
- Real-time progress/status updates
- Job lifecycle hooks (
onCompleted,onFailed) - Queue stats + cancel/retry endpoints
- Full TypeScript support
Quick Start
1. Prerequisite
Run Redis:
docker run -d -p 6379:6379 redis2. Install
npx nuxi@latest module add nuxt-queuekitOr manually:
npm install nuxt-queuekit// nuxt.config.ts
export default defineNuxtConfig({
modules: ['nuxt-queuekit'],
})3. Start app + worker
# terminal 1
npm run dev
# terminal 2
npx nuxt-queuekit workerThat is enough to run jobs using default Redis (127.0.0.1:6379).
Core Workflow
Step 1: Define a job
Create a file in server/jobs:
// server/jobs/SendWelcomeEmail.ts
interface WelcomeEmailData {
userId: string
email: string
name: string
}
export default defineJob<WelcomeEmailData>({
async handle(data) {
await sendEmail({
to: data.email,
subject: 'Welcome!',
template: 'welcome',
data: { name: data.name },
})
return { success: true }
},
})defineJob is auto-imported in job files.
Step 2: Dispatch from server runtime
Use dispatch() in server runtime code (API routes, server plugins, server utilities):
// server/api/register.post.ts
export default defineEventHandler(async (event) => {
const { email, name } = await readBody(event)
const user = await createUser({ email, name })
const { jobId } = await dispatch('SendWelcomeEmail', {
userId: user.id,
email: user.email,
name: user.name,
})
return { success: true, jobId }
})Step 3: Dispatch from client components
Use useQueue() on the client:
<script setup lang="ts">
const queue = useQueue('default')
async function start() {
const { jobId, progress, status, result, error } = await queue.add('SendWelcomeEmail', {
userId: '1',
email: '[email protected]',
name: 'User',
})
}
</script>Organize jobs in folders
Nested files map to dot notation:
server/jobs/
emails/NewsletterEmail.ts
media/ProcessImage.tsawait dispatch('emails.NewsletterEmail', { ... })
await dispatch('media.ProcessImage', { ... })Job options and retries
export default defineJob({
queue: 'payments',
options: {
attempts: 3,
backoff: { type: 'exponential', delay: 2000 },
},
async handle(data) {
return processPayment(data)
},
})Lifecycle hooks
export default defineJob({
async handle(data, job) {
await job.updateProgress(50)
const output = await generateReport(data)
await job.updateProgress(100)
return output
},
async onCompleted(job, result) {
await notifyUser(job.data.userId, result)
},
async onFailed(job, error) {
await alertAdmin(job?.data?.userId, error.message)
},
})Monitor and Control Jobs
Check one job
const status = await $fetch(`/api/queue/${queueName}/${jobId}`)
// status.state -> waiting | active | completed | failed | delayedStream live events (SSE)
const es = new EventSource(`/api/queue/${queueName}/${jobId}/events`)Cancel waiting/delayed job
await $fetch(`/api/queue/${queueName}/${jobId}/cancel`, { method: 'POST' })Retry failed job
await $fetch(`/api/queue/${queueName}/${jobId}/retry`, { method: 'POST' })Queue statistics
const { stats, loading, error, refresh } = useQueueStats('default')
await refresh()Configuration
Environment variables
NUXT_REDIS_HOST=127.0.0.1
NUXT_REDIS_PORT=6379
NUXT_REDIS_PASSWORD=
NUXT_REDIS_USERNAME=
NUXT_REDIS_DB=0Module options
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['nuxt-queuekit'],
queue: {
redis: {
host: process.env.REDIS_HOST || '127.0.0.1',
port: Number(process.env.REDIS_PORT) || 6379,
password: process.env.REDIS_PASSWORD,
username: process.env.REDIS_USERNAME,
db: Number(process.env.REDIS_DB) || 0,
},
// default: server/jobs
jobsDir: 'server/jobs',
// optional extra jobs
jobs: {
SendNotification: './server/custom-jobs/SendNotification.ts',
},
},
})jobs entries are appended to auto-discovered jobs from jobsDir.
Production
Run web server and workers as separate processes:
npm run build
npm run start
npx nuxt-queuekit worker --concurrency 10Worker CLI
npx nuxt-queuekit worker [options]
Options:
--cwd <path> Working directory (default: current directory)
--queue <name> Single queue name (legacy flag)
--queues <names> Comma-separated queues in priority order
--worker <path> Path to custom worker script
--concurrency <number> Concurrent jobs per worker (default: 5)Examples:
npx nuxt-queuekit worker
npx nuxt-queuekit worker --queue emails --concurrency 10
npx nuxt-queuekit worker --queues critical,default,low --concurrency 5
npx nuxt-queuekit worker --queue processing --worker ./workers/custom.tsAPI Reference
defineJob<T, R>(definition)
export default defineJob<{ userId: string }, { ok: true }>({
queue: 'default',
options: { attempts: 3 },
async handle(data, job) {
await job.updateProgress(100)
return { ok: true }
},
async onCompleted(job, result) {},
async onFailed(job, error) {},
})dispatch(jobName, data, options?)
Server runtime helper that creates a job and returns reactive refs:
const { jobId, queueName, progress, status, result, error, refresh, cancel, retry } =
await dispatch('SendEmail', { to: '[email protected]' })useQueue(queueName?)
const queue = useQueue('default')
const job = await queue.add('SendEmail', { to: '[email protected]' })useServerQueue(queueName?)
Returns BullMQ Queue directly (advanced/non-reactive):
const queue = useServerQueue('emails')
await queue.add('send-email', { to: '[email protected]' })useQueueStats(queueName = 'default')
const { stats, loading, error, refresh } = useQueueStats()
await refresh()REST endpoints
POST /api/queue/addGET /api/queue/:queueName/:jobIdGET /api/queue/:queueName/:jobId/eventsPOST /api/queue/:queueName/:jobId/cancelPOST /api/queue/:queueName/:jobId/retryGET /api/queue/:queueName/stats
Troubleshooting
Job not registered
- Ensure file is under configured
jobsDir - Ensure default export is
defineJob({ ... }) - Restart dev server and worker after adding new files
Worker is running but jobs do not process
- Confirm Redis is reachable from worker process
- Confirm queue names match (
job.queuevs worker--queue/--queues)
No real-time updates
- Ensure worker is running (worker publishes events)
- Check network/proxy supports SSE
