Task scheduling system with BullMQ for job queuing, delayed execution, recurring tasks, and retry logic.
Central orchestrator for all scheduling operations:
- Immediate task scheduling
- Delayed task execution
- Recurring task management (cron)
- Job status tracking
- Queue statistics
Redis-backed job queue with:
- Priority-based execution (low, normal, high, critical)
- Exponential backoff retry
- Concurrent processing (5 workers)
- Job persistence
- Event listeners
PostgreSQL storage for recurring tasks:
- Cron expression support
- Enable/disable schedules
- Last run and next run tracking
- User-scoped schedules with RLS
const jobId = await scheduler.scheduleTask(taskId, userId, {
priority: 'high',
maxAttempts: 5
});const jobId = await scheduler.scheduleDelayedTask(
taskId,
userId,
5000, // 5 seconds
{ priority: 'normal' }
);const result = await scheduler.scheduleRecurringTask(
'daily-report',
'Generate daily report',
userId,
'0 0 * * *', // Every day at midnight
{ priority: 'normal' }
);- Default: 3 attempts
- Exponential backoff: 1s, 2s, 4s, 8s...
- Configurable max attempts
- Failed job tracking
POST /api/scheduler/schedule- Schedule immediate taskPOST /api/scheduler/schedule-delayed- Schedule delayed taskPOST /api/scheduler/schedule-recurring- Schedule recurring taskGET /api/scheduler/job/:jobId- Get job statusDELETE /api/scheduler/job/:jobId- Cancel jobGET /api/scheduler/stats- Queue statisticsGET /api/scheduler/cron/:userId- Get user's cron schedulesPOST /api/scheduler/cron/:scheduleId/enable- Enable schedulePOST /api/scheduler/cron/:scheduleId/disable- Disable scheduleDELETE /api/scheduler/cron/:scheduleId- Delete schedulePOST /api/scheduler/pause- Pause schedulerPOST /api/scheduler/resume- Resume scheduler
- id (SERIAL PRIMARY KEY)
- name (VARCHAR)
- task_goal (TEXT)
- cron_expression (VARCHAR)
- user_id (INTEGER)
- enabled (BOOLEAN)
- last_run (TIMESTAMP)
- next_run (TIMESTAMP)
- metadata (JSONB)
- created_at, updated_at- Master can see all schedules
- Users can only see/manage their own schedules
- Full CRUD with user isolation
- Critical (priority: 1) - Highest
- High (priority: 2)
- Normal (priority: 5) - Default
- Low (priority: 10)
- Concurrency: 5 workers
- Default Attempts: 3
- Backoff: Exponential (1s base)
- Retention: 100 completed, 1000 failed
- Auto-cleanup: 24 hours for completed jobs
completed- Job finished successfullyfailed- Job failed after retrieserror- Worker error
All events logged to database for audit trail.
'* * * * *' - Every minute
'0 * * * *' - Every hour
'0 0 * * *' - Every day at midnight
'0 0 * * 0' - Every Sunday at midnight
'0 9 * * 1-5' - Weekdays at 9 AM
'*/15 * * * *' - Every 15 minutes
Environment variables:
REDIS_URL=redis://localhost:6379
49 tests passing:
- Immediate scheduling
- Delayed scheduling
- Recurring tasks
- Job status tracking
- Queue statistics
- Cron schedule management
import { SchedulerCore } from './scheduler/core';
const scheduler = new SchedulerCore();
// Schedule immediate
const jobId = await scheduler.scheduleTask(1, 1);
// Schedule delayed (5 minutes)
const delayedId = await scheduler.scheduleDelayedTask(
1, 1, 300000
);
// Schedule recurring (daily)
const { jobId, scheduleId } = await scheduler.scheduleRecurringTask(
'daily-backup',
'Run daily backup',
1,
'0 2 * * *'
);
// Get stats
const stats = await scheduler.getQueueStats();
console.log(stats);
// { waiting: 5, active: 2, completed: 100, failed: 3, delayed: 1 }
// Cleanup
await scheduler.close();- Connect all modules
- End-to-end workflows
- Integration tests
- Performance optimization