CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-bull

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.

Pending
This version of the tile failed moderation
Malicious code detected in tile.json: This tile claims to describe 'pkg:npm/bull@4.16.5' but the tile itself is named 'tessl/npm-bull' with version '4.16.2'. This is a potential supply chain attack pattern (typosquatting/dependency confusion). The legitimate 'bull' package is maintained by OptimalBits, not 'tessl'. The version mismatch (tile 4.16.2 claiming to describe 4.16.5) and the unofficial namespace suggest this could be an attempt to impersonate the legitimate bull package to intercept installations or inject malicious code.
Overview
Eval results
Files

repeatable-jobs.mddocs/

Repeatable Jobs

Advanced job scheduling with cron syntax, repeatable patterns, and time-based execution control.

Capabilities

Repeatable Job Creation

Create jobs that execute on recurring schedules using cron expressions or intervals.

// Repeatable jobs are created using the repeat option in add() method
interface RepeatOptions {
  /** Cron expression for scheduling */
  cron?: string;
  /** Repeat every N milliseconds */
  every?: number;
  /** Timezone for cron expressions */
  tz?: string;
  /** End date to stop repetition */
  endDate?: Date | string | number;
  /** Maximum number of repetitions */
  limit?: number;
  /** Starting count for iteration tracking */
  count?: number;
  /** Start date for cron-based jobs */
  startDate?: Date | string | number;
}

interface CronRepeatOptions extends RepeatOptions {
  cron: string;
  startDate?: Date | string | number;
}

interface EveryRepeatOptions extends RepeatOptions {
  every: number;
}

Usage Examples:

const Queue = require('bull');
const taskQueue = new Queue('scheduled tasks');

// Cron-based repeatable job - daily at 9 AM
const dailyReport = await taskQueue.add('daily-report', 
  { reportType: 'sales' },
  {
    repeat: {
      cron: '0 9 * * *',  // 9 AM every day
      tz: 'America/New_York'
    }
  }
);

// Interval-based repeatable job - every 5 minutes
const healthCheck = await taskQueue.add('health-check',
  { service: 'api' },
  {
    repeat: {
      every: 5 * 60 * 1000  // 5 minutes in milliseconds
    }
  }
);

// Weekly job with end date
const weeklyCleanup = await taskQueue.add('cleanup',
  { type: 'temp-files' },
  {
    repeat: {
      cron: '0 2 * * 0',  // 2 AM every Sunday
      endDate: new Date('2024-12-31'),
      tz: 'UTC'
    }
  }
);

// Limited repetition - run 10 times
const limitedJob = await taskQueue.add('backup',
  { database: 'users' },
  {
    repeat: {
      cron: '0 0 * * *',  // Daily at midnight
      limit: 10           // Stop after 10 executions
    }
  }
);

Cron Expression Examples

Common cron patterns for scheduling repeatable jobs.

// Cron expression format: second minute hour day month dayOfWeek
// Note: Bull uses 6-field cron (includes seconds), but 5-field also supported

const cronExamples = {
  // Every minute
  everyMinute: '* * * * *',
  
  // Every 5 minutes
  every5Minutes: '*/5 * * * *',
  
  // Every hour at minute 30
  everyHourAt30: '30 * * * *',  
  
  // Daily at 8:30 AM
  dailyAt830AM: '30 8 * * *',
  
  // Every weekday at 9 AM
  weekdaysAt9AM: '0 9 * * 1-5',
  
  // Every Monday at 10 AM
  mondaysAt10AM: '0 10 * * 1',
  
  // First day of every month at midnight
  monthlyFirstDay: '0 0 1 * *',
  
  // Every 15 minutes during business hours (9 AM - 5 PM)
  businessHours: '*/15 9-17 * * 1-5',
  
  // Twice daily at 8 AM and 8 PM
  twiceDaily: '0 8,20 * * *'
};

// Use in repeatable jobs
await taskQueue.add('business-hours-check', { type: 'status' }, {
  repeat: { cron: cronExamples.businessHours }
});

Repeatable Job Management

Retrieve and manage existing repeatable jobs.

/**
 * Get information about all repeatable jobs
 * @param start - Start index (default: 0)
 * @param end - End index (default: -1 for all)
 * @param asc - Sort ascending by next execution time (default: false)
 * @returns Promise that resolves to array of repeatable job information
 */
getRepeatableJobs(start?: number, end?: number, asc?: boolean): Promise<JobInformation[]>;

interface JobInformation {
  /** Unique key for the repeatable job */
  key: string;
  /** Job name */
  name: string;
  /** Job ID if specified */
  id?: string;
  /** End date timestamp */
  endDate?: number;
  /** Timezone */
  tz?: string;
  /** Cron expression */
  cron: string;
  /** Interval in milliseconds */
  every: number;
  /** Next execution timestamp */
  next: number;
}

Usage Examples:

// Get all repeatable jobs
const repeatableJobs = await taskQueue.getRepeatableJobs();
console.log(`Found ${repeatableJobs.length} repeatable jobs`);

repeatableJobs.forEach(job => {
  const nextRun = new Date(job.next);
  console.log(`${job.name}: next run at ${nextRun.toISOString()}`);
  if (job.cron) {
    console.log(`  Cron: ${job.cron}`);
  }
  if (job.every) {
    console.log(`  Interval: ${job.every}ms`);
  }
});

// Get upcoming repeatable jobs (sorted by next execution)
const upcoming = await taskQueue.getRepeatableJobs(0, 10, true);
console.log('Next 10 jobs to run:');
upcoming.forEach(job => {
  const nextRun = new Date(job.next);
  const timeUntil = job.next - Date.now();
  console.log(`  ${job.name} in ${Math.round(timeUntil / 1000)}s`);
});

Removing Repeatable Jobs

Remove repeatable jobs by configuration or key.

/**
 * Remove a repeatable job by repeat configuration
 * @param repeat - Repeat options that match the original job
 * @returns Promise that resolves when repeatable job is removed
 */
removeRepeatable(repeat: (CronRepeatOptions | EveryRepeatOptions) & { jobId?: string | number }): Promise<void>;

/**
 * Remove a repeatable job by name and repeat configuration  
 * @param name - Job name
 * @param repeat - Repeat options that match the original job
 * @returns Promise that resolves when repeatable job is removed
 */
removeRepeatable(name: string, repeat: (CronRepeatOptions | EveryRepeatOptions) & { jobId?: string | number }): Promise<void>;

/**
 * Remove a repeatable job by its unique key
 * @param key - Repeatable job key from getRepeatableJobs()
 * @returns Promise that resolves when repeatable job is removed
 */
removeRepeatableByKey(key: string): Promise<void>;

Usage Examples:

// Remove repeatable job by matching original configuration
await taskQueue.removeRepeatable({
  cron: '0 9 * * *',
  tz: 'America/New_York'
});

// Remove named repeatable job
await taskQueue.removeRepeatable('daily-report', {
  cron: '0 9 * * *',
  tz: 'America/New_York'
});

// Remove by key (easier method)
const repeatableJobs = await taskQueue.getRepeatableJobs();
const reportJob = repeatableJobs.find(job => job.name === 'daily-report');
if (reportJob) {
  await taskQueue.removeRepeatableByKey(reportJob.key);
  console.log('Removed daily report job');
}

// Remove all repeatable jobs
const allRepeatable = await taskQueue.getRepeatableJobs();
for (const job of allRepeatable) {
  await taskQueue.removeRepeatableByKey(job.key);
}
console.log('Removed all repeatable jobs');

Advanced Repeatable Job Management

Get next instance and count repeatable jobs.

/**
 * Get the next job instance for a repeatable job
 * @param name - Job name
 * @param data - Job data
 * @param opts - Job options with repeat configuration
 * @returns Promise that resolves to next job instance
 */
nextRepeatableJob(name: string, data: any, opts: JobOptions): Promise<Job>;

/**
 * Get count of repeatable job definitions
 * @returns Promise that resolves to number of repeatable jobs
 */
getRepeatableCount(): Promise<number>;

Usage Examples:

// Get count of repeatable jobs
const repeatableCount = await taskQueue.getRepeatableCount();
console.log(`Total repeatable jobs defined: ${repeatableCount}`);

// Get next instance of a repeatable job (advanced usage)
const nextJob = await taskQueue.nextRepeatableJob('daily-report', 
  { reportType: 'sales' },
  { 
    repeat: { cron: '0 9 * * *' }
  }
);
console.log(`Next job will run at: ${new Date(nextJob.timestamp)}`);

Repeatable Job Processing

Process repeatable jobs like regular jobs.

// Repeatable jobs are processed by regular processors
taskQueue.process('daily-report', async (job) => {
  console.log(`Running daily report at ${new Date()}`);
  console.log('Job data:', job.data);
  
  // Generate report
  const report = await generateDailyReport(job.data.reportType);
  
  return {
    reportGenerated: true,
    reportId: report.id,
    timestamp: Date.now()
  };
});

taskQueue.process('health-check', async (job) => {
  console.log(`Health check for ${job.data.service}`);
  
  const status = await checkServiceHealth(job.data.service);
  
  if (!status.healthy) {
    // Alert on health issues
    await sendAlert(`Service ${job.data.service} is unhealthy`);
  }
  
  return status;
});

Timezone Handling

Work with timezones in repeatable jobs.

// Different timezone examples
const timezoneJobs = [
  // New York time
  {
    name: 'ny-market-open',
    data: { market: 'NYSE' },
    repeat: {
      cron: '30 9 * * 1-5',  // 9:30 AM weekdays
      tz: 'America/New_York'
    }
  },
  
  // London time
  {
    name: 'london-report',
    data: { region: 'Europe' },
    repeat: {
      cron: '0 17 * * 1-5',  // 5 PM weekdays
      tz: 'Europe/London'
    }
  },
  
  // Tokyo time
  {
    name: 'tokyo-backup',
    data: { system: 'trading' },
    repeat: {
      cron: '0 2 * * *',  // 2 AM daily
      tz: 'Asia/Tokyo'
    }
  },
  
  // UTC (default)
  {
    name: 'global-sync',
    data: { type: 'sync' },
    repeat: {
      cron: '0 0 * * *'  // Midnight UTC
    }
  }
];

// Add all timezone-aware jobs
for (const jobDef of timezoneJobs) {
  await taskQueue.add(jobDef.name, jobDef.data, { repeat: jobDef.repeat });
}

Complex Scheduling Examples

Advanced scheduling patterns and use cases.

// Business day only job (excluding weekends and holidays)
await taskQueue.add('business-day-task', { type: 'report' }, {
  repeat: {
    cron: '0 9 * * 1-5',  // Weekdays only
    tz: 'America/New_York'
  }
});

// Quarterly job (first Monday of quarter at 8 AM)
await taskQueue.add('quarterly-review', { quarter: 'Q1' }, {
  repeat: {
    cron: '0 8 1-7 1,4,7,10 1',  // First Monday of Jan, Apr, Jul, Oct
    tz: 'UTC'
  }
});

// End-of-month job (last day of month at 11 PM)  
await taskQueue.add('month-end-close', { type: 'accounting' }, {
  repeat: {
    cron: '0 23 28-31 * *',  // Run on days 28-31 of month
    tz: 'America/New_York'
  }
});

// High-frequency job with limit (every 30 seconds for 1 hour)
await taskQueue.add('burst-monitoring', { duration: '1hour' }, {
  repeat: {
    every: 30000,        // Every 30 seconds
    limit: 120,          // Stop after 2 hours (120 * 30sec = 1 hour)
    endDate: new Date(Date.now() + 60 * 60 * 1000)  // Also set end date
  }
});

// Seasonal job (summer months only)
await taskQueue.add('summer-maintenance', { season: 'summer' }, {
  repeat: {
    cron: '0 2 1 6-8 *',  // 1st of June, July, August at 2 AM
    tz: 'UTC'
  }
});

Monitoring Repeatable Jobs

Monitor repeatable job execution and health.

// Monitor repeatable job execution
taskQueue.on('completed', (job, result) => {
  if (job.opts.repeat) {
    console.log(`Repeatable job ${job.name} completed:`, result);
    
    // Log execution time for performance monitoring
    const executionTime = job.finishedOn - job.processedOn;
    console.log(`Execution time: ${executionTime}ms`);
  }
});

taskQueue.on('failed', (job, err) => {
  if (job.opts.repeat) {
    console.error(`Repeatable job ${job.name} failed:`, err.message);
    
    // Alert on repeatable job failures
    sendAlert(`Repeatable job ${job.name} failed: ${err.message}`);
  }
});

// Periodic health check for repeatable jobs
async function checkRepeatableJobHealth() {
  const repeatableJobs = await taskQueue.getRepeatableJobs();
  const now = Date.now();
  
  for (const job of repeatableJobs) {
    const timeSinceNext = now - job.next;
    
    // Alert if job is overdue by more than 5 minutes
    if (timeSinceNext > 5 * 60 * 1000) {
      console.warn(`Repeatable job ${job.name} is overdue by ${Math.round(timeSinceNext / 1000)}s`);
    }
  }
}

// Run health check every 10 minutes
setInterval(checkRepeatableJobHealth, 10 * 60 * 1000);

Install with Tessl CLI

npx tessl i tessl/npm-bull@4.16.2

docs

event-system.md

index.md

job-creation.md

job-processing.md

job-state.md

queue-management.md

queue-monitoring.md

repeatable-jobs.md

utils.md

tile.json