Redis-based job queue library for Node.js that provides reliable job processing with features including job scheduling, delayed execution, repeatable jobs, priority handling, and automatic retries.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Add jobs to queues with various options, bulk operations, and lifecycle management.
Add jobs to the queue with data and optional configuration.
/**
* Add an anonymous job to the queue
* @param data - Job payload data
* @param opts - Job configuration options
* @returns Promise that resolves to the created Job instance
*/
add(data: any, opts?: JobOptions): Promise<Job>;
/**
* Add a named job to the queue
* @param name - Job name/type identifier
* @param data - Job payload data
* @param opts - Job configuration options
* @returns Promise that resolves to the created Job instance
*/
add(name: string, data: any, opts?: JobOptions): Promise<Job>;Usage Examples:
const Queue = require('bull');
const emailQueue = new Queue('email processing');
// Add anonymous job
const job1 = await emailQueue.add({
email: 'user@example.com',
subject: 'Welcome!',
body: 'Welcome to our service'
});
// Add named job
const job2 = await emailQueue.add('welcome-email', {
email: 'user@example.com',
name: 'John Doe'
});
console.log(`Created job ${job1.id}`);
console.log(`Created job ${job2.id} with name: ${job2.name}`);Configure job behavior with comprehensive options.
interface JobOptions {
/** Job priority (1 = highest, higher numbers = lower priority) */
priority?: number;
/** Delay before job becomes available for processing (milliseconds) */
delay?: number;
/** Number of attempts before job fails permanently */
attempts?: number;
/** Repeat job according to schedule */
repeat?: RepeatOptions;
/** Backoff strategy for retries */
backoff?: number | BackoffOptions;
/** Add job to front of queue (LIFO) instead of back (FIFO) */
lifo?: boolean;
/** Job timeout in milliseconds */
timeout?: number;
/** Custom job ID (must be unique) */
jobId?: string | number;
/** Remove job when completed (boolean, number of jobs to keep, or options) */
removeOnComplete?: boolean | number | KeepJobsOptions;
/** Remove job when failed (boolean, number of jobs to keep, or options) */
removeOnFail?: boolean | number | KeepJobsOptions;
/** Debounce options to prevent duplicate jobs */
debounce?: DebounceOptions;
/** Limit stack trace lines recorded on failure */
stackTraceLimit?: number;
/** Prevent JSON parsing of job data */
preventParsingData?: boolean;
}
interface KeepJobsOptions {
/** Maximum age in seconds for jobs to keep */
age?: number;
/** Maximum number of jobs to keep */
count?: number;
}
interface DebounceOptions {
/** Debounce identifier */
id: string;
/** Time to live in milliseconds */
ttl?: number;
}
interface BackoffOptions {
/** Backoff type ('fixed' or 'exponential') */
type: string;
/** Base delay in milliseconds */
delay?: number;
/** Additional options for custom strategies */
options?: any;
}Usage Examples:
// Job with priority and retry configuration
const importantJob = await emailQueue.add('urgent-email', {
email: 'ceo@company.com',
subject: 'Critical Alert'
}, {
priority: 1, // High priority
attempts: 5, // Retry up to 5 times
backoff: {
type: 'exponential',
delay: 2000
}
});
// Delayed job
const delayedJob = await emailQueue.add('scheduled-email', {
email: 'user@example.com',
subject: 'Reminder'
}, {
delay: 60000, // Execute in 1 minute
attempts: 3
});
// Job with cleanup settings
const tempJob = await emailQueue.add('temp-task', { data: 'temp' }, {
removeOnComplete: 5, // Keep only 5 completed jobs
removeOnFail: 3, // Keep only 3 failed jobs
timeout: 30000 // 30 second timeout
});
// Job with custom ID and debouncing
const uniqueJob = await emailQueue.add('user-notification', {
userId: 123,
message: 'Update available'
}, {
jobId: 'user-123-notification',
debounce: {
id: 'user-123-notifications',
ttl: 5000 // Prevent duplicate notifications for 5 seconds
}
});Add multiple jobs efficiently in a single operation.
/**
* Add multiple jobs to the queue in bulk
* @param jobs - Array of job definitions
* @returns Promise that resolves to array of created Job instances
*/
addBulk(jobs: Array<{
name?: string;
data: any;
opts?: Omit<JobOptions, 'repeat'>; // repeat not supported in bulk
}>): Promise<Job[]>;Usage Examples:
// Add multiple jobs at once
const users = [
{ id: 1, email: 'user1@example.com', name: 'Alice' },
{ id: 2, email: 'user2@example.com', name: 'Bob' },
{ id: 3, email: 'user3@example.com', name: 'Charlie' }
];
const bulkJobs = await emailQueue.addBulk(
users.map(user => ({
name: 'welcome-email',
data: user,
opts: {
attempts: 3,
removeOnComplete: 10
}
}))
);
console.log(`Created ${bulkJobs.length} jobs`);
// Mixed job types in bulk
const mixedJobs = await taskQueue.addBulk([
{
name: 'send-email',
data: { email: 'user@example.com' },
opts: { priority: 1 }
},
{
name: 'generate-report',
data: { reportId: 'R123' },
opts: { attempts: 5 }
},
{
data: { task: 'cleanup' }, // Anonymous job
opts: { delay: 5000 }
}
]);Get jobs from the queue by ID or retrieve jobs in different states.
/**
* Get a specific job by ID
* @param jobId - Job identifier
* @returns Promise that resolves to Job instance or null if not found
*/
getJob(jobId: string | number): Promise<Job | null>;
/**
* Get next job to be processed (internal use)
* @returns Promise that resolves to next Job or undefined
*/
getNextJob(): Promise<Job | undefined>;Usage Examples:
// Get job by ID
const job = await emailQueue.getJob(123);
if (job) {
console.log(`Job ${job.id} status:`, await job.getState());
console.log('Job data:', job.data);
} else {
console.log('Job not found');
}
// Check job after creation
const newJob = await emailQueue.add('test', { message: 'hello' });
const retrievedJob = await emailQueue.getJob(newJob.id);
console.log('Jobs match:', newJob.id === retrievedJob.id);Remove jobs matching specific patterns.
/**
* Remove all jobs matching a Redis glob pattern
* @param pattern - Redis glob pattern to match job IDs
* @returns Promise that resolves when matching jobs are removed
*/
removeJobs(pattern: string): Promise<void>;Usage Examples:
// Remove jobs with IDs matching pattern
await emailQueue.removeJobs('user-123-*'); // Remove all jobs for user 123
await emailQueue.removeJobs('temp-*'); // Remove all temporary jobs
await emailQueue.removeJobs('*-failed'); // Remove jobs ending with '-failed'
// Remove specific job types (if using job IDs with patterns)
await emailQueue.removeJobs('email-*'); // Remove all email jobsGet counts of jobs in various states.
/**
* Get total number of jobs waiting or paused
* @returns Promise that resolves to job count
*/
count(): Promise<number>;
/**
* Get counts by priority levels
* @param priorities - Array of priority numbers to count
* @returns Promise that resolves to object with priority counts
*/
getCountsPerPriority(priorities: number[]): Promise<{ [priority: string]: number }>;Usage Examples:
// Get total waiting job count
const waitingCount = await emailQueue.count();
console.log(`Jobs waiting: ${waitingCount}`);
// Get counts by priority
const priorityCounts = await emailQueue.getCountsPerPriority([1, 2, 3, 4, 5]);
console.log('Priority counts:', priorityCounts);
// Output: { '1': 5, '2': 12, '3': 8, '4': 20, '5': 3 }// Example of robust job creation with best practices
async function createEmailJob(emailData, options = {}) {
// Validate required data
if (!emailData.email || !emailData.subject) {
throw new Error('Email and subject are required');
}
// Set sensible defaults
const jobOptions = {
attempts: 3,
backoff: {
type: 'exponential',
delay: 1000
},
removeOnComplete: 100, // Keep last 100 completed jobs
removeOnFail: 50, // Keep last 50 failed jobs
timeout: 30000, // 30 second timeout
...options
};
// Create job with error handling
try {
const job = await emailQueue.add('send-email', emailData, jobOptions);
console.log(`Created email job ${job.id} for ${emailData.email}`);
return job;
} catch (error) {
console.error('Failed to create email job:', error);
throw error;
}
}
// Usage
const job = await createEmailJob({
email: 'user@example.com',
subject: 'Welcome',
body: 'Welcome to our service!'
}, {
priority: 2,
delay: 5000 // Send in 5 seconds
});// High-priority job with custom backoff
const criticalJob = await taskQueue.add('critical-task', {
action: 'process_payment',
paymentId: 'pay_123'
}, {
priority: 1,
attempts: 10,
backoff: {
type: 'custom',
delay: 1000,
options: {
multiplier: 1.5,
maxDelay: 30000
}
},
timeout: 60000,
removeOnComplete: false, // Never remove completed critical jobs
removeOnFail: false // Never remove failed critical jobs
});
// Batch processing job
const batchJob = await taskQueue.add('batch-process', {
items: largeDataSet,
batchSize: 100
}, {
attempts: 1, // Don't retry batch jobs
timeout: 300000, // 5 minute timeout
removeOnComplete: 1, // Remove immediately after completion
lifo: false // Process in order (FIFO)
});
// Temporary job with auto-cleanup
const tempJob = await taskQueue.add('temp-analysis', {
data: temporaryData
}, {
attempts: 2,
removeOnComplete: true, // Remove immediately when done
removeOnFail: true, // Remove immediately if failed
stackTraceLimit: 5 // Limit error stack trace
});Install with Tessl CLI
npx tessl i tessl/npm-bull