ExisJS

exisjs/cron

The exisjs/cron module provides background task scheduling, 5/6-field cron expression parsing, drift-corrected interval timers, retry backoff, and runtime job management.


Module Exports

import {  cron,  defineCron,  CronManager,  CronJob,  CronExpression,  every,} from 'exisjs/cron'
import type {  CronSchedule,  CronJobOptions,  CronContext,  CronJobStats,  CronJobStatus,  OverlapPolicy,  IntervalOptions,  TimeoutOptions,} from 'exisjs/cron'

Decorators for class-based jobs are imported from exisjs/decorators:

import {  Cron,  Interval,  TimeoutTask,  Scheduled,  ScheduledTimeout,} from 'exisjs/decorators'

1. Functional Definition Helpers

cron(scheduleOrOptions, handler?)

Defines a functional cron job for auto-discovery or dynamic registration.

function cron(  scheduleOrOptions: string | CronJobOptions,  handler?: (ctx: CronContext) => any): FunctionalCronDefinition

Overloads

  1. Option Object:

    src/cron/sync.ts
    import { cron, CronExpression } from 'exisjs/cron'
    export default cron({  name: 'sync-users',  schedule: CronExpression.EVERY_10_MINUTES,  timezone: 'UTC',  preventOverlap: true,  retries: 2,  retryDelayMs: 1000,  async run({ app, log, iteration }) {    log.info({ iteration }, 'Running user synchronization')  },})
  2. Schedule Pattern & Handler:

    src/cron/cleanup.ts
    import { cron } from 'exisjs/cron'
    export default cron('0 0 * * *', async ({ log }) => {  log.info('Running nightly purge')})

cron.every(duration, handler, options?)

Shorthand helper accepting natural language English duration strings (e.g., '10 seconds', '5 minutes', '2 hours', '1 day').

cron.every(  duration: string,  handler: (ctx: CronContext) => any,  options?: Omit<CronJobOptions, 'schedule' | 'run' | 'handle'>): FunctionalCronDefinition

Example

src/cron/heartbeat.ts
import { cron } from 'exisjs/cron'
export default cron.every('15 minutes', async ({ log }) => {  log.info('Heartbeat tick')}, {  name: 'health-heartbeat',  timezone: 'UTC',})

cron.interval(ms, handler, options?)

Shorthand helper for millisecond recurring intervals with timer unref and drift management.

cron.interval(  ms: number,  handler: (ctx: CronContext) => any,  options?: Omit<CronJobOptions, 'interval' | 'run' | 'handle'>): FunctionalCronDefinition

Example

src/cron/queue-poll.ts
import { cron } from 'exisjs/cron'
export default cron.interval(30_000, async ({ log }) => {  log.info('Polling background job queue')})

cron.timeout(ms, handler, options?)

Shorthand helper for one-time delayed startup tasks executed once after the server initializes.

cron.timeout(  ms: number,  handler: (ctx: CronContext) => any,  options?: Omit<CronJobOptions, 'timeout' | 'run' | 'handle'>): FunctionalCronDefinition

Example

src/cron/warmup.ts
import { cron } from 'exisjs/cron'
export default cron.timeout(5_000, async ({ app, log }) => {  log.info('Warming up memory cache after application startup')})

2. OOP Decorators (exisjs/decorators)

@Cron(schedule, options?)

Method decorator that marks a class method on an @Injectable() service as a scheduled cron job.

function Cron(  schedule: string,  options?: Omit<CronJobOptions, 'schedule' | 'run' | 'handle'>): MethodDecorator
ParameterTypeDescription
schedulestringStandard 5 or 6 field cron expression or CronExpression constant.
optionsCronJobOptionsOptional job configuration (name, timezone, preventOverlap, retries, retryDelayMs).
src/services/report.service.ts
import { Injectable } from 'exisjs/di'import { Cron, CronExpression } from 'exisjs/decorators'
@Injectable()export class ReportService {  @Cron(CronExpression.EVERY_DAY_AT_MIDNIGHT, {    name: 'nightly-report',    timezone: 'UTC',    preventOverlap: true,  })  async generateDailyReport() {    // Executes every day at 00:00 UTC  }}

@Interval(ms, options?)

Method decorator that schedules a method to run at recurring millisecond intervals.

function Interval(  ms: number,  options?: Omit<CronJobOptions, 'interval' | 'run' | 'handle'>): MethodDecorator
src/services/monitor.service.ts
import { Injectable } from 'exisjs/di'import { Interval } from 'exisjs/decorators'
@Injectable()export class MonitorService {  @Interval(60_000, { name: 'health-monitor' })  async pingExternalServices() {    // Runs every 60 seconds  }}

@TimeoutTask(ms, options?)

Method decorator for one-time startup tasks executed after the specified millisecond delay. Also aliased as @ScheduledTimeout.

function TimeoutTask(  ms: number,  options?: Omit<CronJobOptions, 'timeout' | 'run' | 'handle'>): MethodDecorator
src/services/bootstrap.service.ts
import { Injectable } from 'exisjs/di'import { TimeoutTask } from 'exisjs/decorators'
@Injectable()export class BootstrapService {  @TimeoutTask(3_000, { name: 'seed-cache' })  async seedCache() {    // Runs once 3s after server boot  }}

3. Configuration Interfaces

CronJobOptions

Configuration object accepted by cron(), app.cron.schedule(), and cron decorators:

OptionTypeDefaultDescription
namestringjob_<random>Unique identifier for the job. Used in logging, statistics, and runtime triggers.
schedulestringundefined5 or 6 field cron expression (e.g. '0 0 * * *').
intervalnumberundefinedInterval in milliseconds for recurring execution.
timeoutnumberundefinedDelay in milliseconds for one-time execution.
timezonestring'UTC'IANA timezone string (e.g. 'America/New_York', 'Asia/Kolkata').
preventOverlapbooleantrueWhen true, skips execution if the previous execution is still running.
onOverlap'skip' | 'queue''skip'Overlap policy when a job is triggered while already running.
autoStartbooleantrueWhether the job begins scheduling automatically upon registration.
retriesnumber0Number of retry attempts if the handler throws an unhandled error.
retryDelayMsnumber1000Delay between retry attempts in milliseconds.
run / handle(ctx: CronContext) => anyundefinedMain execution callback function.
onError(err: Error, ctx: CronContext) => voidundefinedError hook executed if the handler fails all retry attempts.

CronContext

Context object passed to cron execution handlers:

PropertyTypeDescription
appAppThe active ExisJS application instance.
logLoggerStructured application logger instance.
jobNamestringThe unique name of the currently executing job.
startedAtDateTimestamp when the current execution began.
iterationnumberMonotonically increasing execution counter for this job instance.
signalAbortSignalAbortSignal triggered during application graceful shutdown.

CronJobStats

Statistics descriptor returned by job.getStats() and app.cron.getStats():

FieldTypeDescription
namestringUnique job identifier.
status'idle' | 'running' | 'paused' | 'stopped'Current job execution status.
schedulestring | undefinedConfigured cron schedule expression.
intervalMsnumber | undefinedConfigured interval in milliseconds.
timezonestring | undefinedConfigured IANA timezone.
preventOverlapbooleanOverlap prevention status.
lastRunDate | undefinedTimestamp of the most recent execution.
nextRunDate | undefinedCalculated timestamp for the upcoming scheduled run.
executionCountnumberTotal number of executions attempted.
failureCountnumberTotal number of failed executions.
lastDurationMsnumber | undefinedDuration in milliseconds of the last execution.
lastErrorstring | undefinedLast error message if execution failed.

4. CronExpression Constants

ExisJS exports pre-compiled cron patterns:

ConstantValueDescription
CronExpression.EVERY_SECOND* * * * * *Every second (6-field)
CronExpression.EVERY_5_SECONDS*/5 * * * * *Every 5 seconds (6-field)
CronExpression.EVERY_10_SECONDS*/10 * * * * *Every 10 seconds (6-field)
CronExpression.EVERY_30_SECONDS*/30 * * * * *Every 30 seconds (6-field)
CronExpression.EVERY_MINUTE* * * * *Every minute
CronExpression.EVERY_2_MINUTES*/2 * * * *Every 2 minutes
CronExpression.EVERY_3_MINUTES*/3 * * * *Every 3 minutes
CronExpression.EVERY_5_MINUTES*/5 * * * *Every 5 minutes
CronExpression.EVERY_10_MINUTES*/10 * * * *Every 10 minutes
CronExpression.EVERY_15_MINUTES*/15 * * * *Every 15 minutes
CronExpression.EVERY_30_MINUTES*/30 * * * *Every 30 minutes
CronExpression.EVERY_HOUR0 * * * *At minute 0 of every hour
CronExpression.EVERY_2_HOURS0 */2 * * *Every 2 hours
CronExpression.EVERY_3_HOURS0 */3 * * *Every 3 hours
CronExpression.EVERY_6_HOURS0 */6 * * *Every 6 hours
CronExpression.EVERY_12_HOURS0 */12 * * *Every 12 hours
CronExpression.EVERY_DAY_AT_MIDNIGHT0 0 * * *Daily at 00:00 (Midnight)
CronExpression.EVERY_DAY_AT_1AM0 1 * * *Daily at 01:00 AM
CronExpression.EVERY_DAY_AT_2AM0 2 * * *Daily at 02:00 AM
CronExpression.EVERY_DAY_AT_NOON0 12 * * *Daily at 12:00 PM
CronExpression.EVERY_WEEK0 0 * * 0Every Sunday at 00:00
CronExpression.EVERY_WEEKDAY0 0 * * 1-5Monday through Friday at 00:00
CronExpression.EVERY_WEEKEND0 0 * * 6,0Saturday and Sunday at 00:00
CronExpression.EVERY_MONTH0 0 1 * *First day of every month at 00:00
CronExpression.EVERY_QUARTER0 0 1 1,4,7,10 *First day of every quarter at 00:00
CronExpression.EVERY_YEAR0 0 1 1 *January 1st at 00:00

5. every(duration) Helper

Converts human-readable duration strings into standard 5 or 6 field cron patterns.

function every(duration: string): string
Input ExampleGenerated Cron Pattern
every('10 seconds')*/10 * * * * *
every('5 minutes')*/5 * * * *
every('2 hours')0 */2 * * *
every('1 day')0 0 * * *
every('1 week')0 0 * * 0
every('1 month')0 0 1 * *

6. Runtime Management (CronManager)

Access the application cron manager instance via app.cron:

export class CronManager {  has(name: string): boolean  schedule(nameOrOptions: string | CronJobOptions, schedule?: string, handler?: (ctx: CronContext) => any, options?: Partial<CronJobOptions>): CronJob  interval(name: string, ms: number, handler: (ctx: CronContext) => any, options?: Partial<CronJobOptions>): CronJob  timeout(name: string, ms: number, handler: (ctx: CronContext) => any, options?: Partial<CronJobOptions>): CronJob  getJob(name: string): CronJob | undefined  getJobs(): Map<string, CronJob>  getStats(): CronJobStats[]  startAll(): void  pauseAll(): void  stopAll(): void  trigger(name: string): Promise<any>  drain(timeoutMs?: number): Promise<void>}

Examples

// Check if a job existsif (app.cron.has('sync-users')) {  // Retrieve execution metrics  const job = app.cron.getJob('sync-users')  console.log(job?.getStats())}
// Manually trigger immediate executionawait app.cron.trigger('sync-users')
// Pause all jobs during maintenanceapp.cron.pauseAll()
// Resume schedulingapp.cron.startAll()
// Gracefully drain in-flight jobs during shutdownawait app.cron.drain(5000)