← All @molecule/* packages · App templates
@molecule/api-cronCore interface · cron · API (Node) · v1.0.1 · Apache-2.0
Cron scheduling core interface for molecule.dev — schedule, pause, resume, and manage recurring jobs
npm install @molecule/api-cron@molecule/api-cron is the cron core interface on the API (Node) side: the API your app calls, with no vendor inside.
Choose the implementation by bonding one of its 2 providers: @molecule/api-cron-bullmq, @molecule/api-cron-node-cron.
import { setProvider, schedule, list, close } from '@molecule/api-cron'
import { provider as nodeCron } from '@molecule/api-cron-node-cron'
setProvider(nodeCron)
const jobId = await schedule('cleanup', '0 3 * * *', async () => {
console.log('Running nightly cleanup...')
})
const jobs = await list()
// On graceful shutdown / test teardown:
await close()Providers (2): @molecule/api-cron-bullmq, @molecule/api-cron-node-cron
Works with: @molecule/api-bond, @molecule/api-i18n
Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit
src/index.tsJSDoc, not this file.
Provider-agnostic cron scheduling interface for molecule.dev.
Defines the CronProvider interface for scheduling, pausing, resuming,
cancelling, and manually triggering cron jobs. Bond packages (node-cron,
BullMQ, etc.) implement this interface. Application code uses the convenience
functions (schedule, cancel, list, pause, resume, runNow, close)
which delegate to the bonded provider.
import { setProvider, schedule, list, close } from '@molecule/api-cron'
import { provider as nodeCron } from '@molecule/api-cron-node-cron'
setProvider(nodeCron)
const jobId = await schedule('cleanup', '0 3 * * *', async () => {
console.log('Running nightly cleanup...')
})
const jobs = await list()
// On graceful shutdown / test teardown:
await close()
core
npm install @molecule/api-cron @molecule/api-bond @molecule/api-i18n
CronConfigConfiguration options for cron providers.
interface CronConfig {
/** Default timezone for all jobs. */
timezone?: string
}
CronJobA scheduled cron job.
interface CronJob {
/** Unique job identifier. */
id: string
/** Human-readable job name. */
name: string
/** The cron expression (e.g., `'0 * * * *'` for every hour). */
cron: string
/** Current job status. */
status: CronJobStatus
/** Timestamp of the last execution, if any. */
lastRun?: Date
/** Timestamp of the next scheduled execution, if any. */
nextRun?: Date
/** Total number of times the job has been executed. */
runCount: number
}
CronOptionsOptions for scheduling a cron job.
interface CronOptions {
/** IANA timezone for the cron schedule (e.g., `'America/New_York'`). */
timezone?: string
/** Whether to run the job immediately on creation. Defaults to `false`. */
runOnInit?: boolean
/** Maximum number of times the job should run. `undefined` means unlimited. */
maxRuns?: number
/** Start date — the job will not run before this date. */
startDate?: Date | string
/** End date — the job will not run after this date. */
endDate?: Date | string
/**
* When `true`, a tick that arrives while the previous execution of this
* job is still running is skipped instead of running concurrently.
* Defaults to `false` (current behavior: overlapping executions are
* allowed) to avoid changing existing deployments' concurrency.
* Support is provider-specific: node-cron enforces it natively (skips the
* tick and logs a warning); the BullMQ bond emulates it per-process by
* skipping a tick while a previous invocation on the same worker process
* hasn't finished — it does NOT coordinate across multiple distributed
* worker processes.
*/
noOverlap?: boolean
}
CronProviderCron provider interface.
All cron providers must implement this interface. Bond packages (node-cron, BullMQ, etc.) provide concrete implementations.
interface CronProvider {
/**
* Schedules a new cron job.
*
* @param name - Human-readable name for the job.
* @param cron - A cron expression defining the schedule.
* @param handler - The async function to execute on each tick.
* @param options - Optional scheduling configuration.
* @returns The unique job identifier.
*/
schedule(
name: string,
cron: string,
handler: () => Promise<void>,
options?: CronOptions,
): Promise<string>
/**
* Cancels and removes a scheduled job.
*
* @param jobId - The job identifier.
*/
cancel(jobId: string): Promise<void>
/**
* Lists all registered cron jobs.
*
* @returns An array of cron job descriptors.
*/
list(): Promise<CronJob[]>
/**
* Pauses a running cron job without removing it.
*
* @param jobId - The job identifier.
*/
pause(jobId: string): Promise<void>
/**
* Resumes a previously paused cron job.
*
* @param jobId - The job identifier.
*/
resume(jobId: string): Promise<void>
/**
* Triggers immediate execution of a job regardless of its schedule.
*
* @param jobId - The job identifier.
*/
runNow(jobId: string): Promise<void>
/**
* Releases the provider's resources (timers, queue/worker connections) so
* the process can exit cleanly — required for graceful shutdown and tests.
* Optional: in-process providers with no persistent resources may omit it.
*/
close?(): Promise<void>
}
CronJobStatusStatus of a cron job.
type CronJobStatus = 'active' | 'paused' | 'completed' | 'failed'
cancel(jobId)Cancels and removes a scheduled job.
function cancel(jobId: string): Promise<void>
jobId — The job identifier.Returns: Resolves when the job is cancelled.
close()Releases the bonded provider's resources (timers, queue/worker
connections) so the process can exit cleanly. Call during graceful
shutdown and in test teardown. A no-op when the bonded provider does not
implement close() (in-process providers with no persistent resources
may omit it).
function close(): Promise<void>
Returns: Resolves when cleanup completes.
getProvider()Retrieves the bonded cron provider, throwing if none is configured.
function getProvider(): CronProvider
Returns: The bonded cron provider.
hasProvider()Checks whether a cron provider is currently bonded.
function hasProvider(): boolean
Returns: true if a cron provider is bonded.
list()Lists all registered cron jobs.
function list(): Promise<CronJob[]>
Returns: An array of cron job descriptors.
pause(jobId)Pauses a running cron job without removing it.
function pause(jobId: string): Promise<void>
jobId — The job identifier.Returns: Resolves when the job is paused.
resume(jobId)Resumes a previously paused cron job.
function resume(jobId: string): Promise<void>
jobId — The job identifier.Returns: Resolves when the job is resumed.
runNow(jobId)Triggers immediate execution of a job regardless of its schedule.
function runNow(jobId: string): Promise<void>
jobId — The job identifier.Returns: Resolves when the job execution completes.
schedule(name, cron, handler, options)Schedules a new cron job.
function schedule(
name: string,
cron: string,
handler: () => Promise<void>,
options?: CronOptions,
): Promise<string>
name — Human-readable name for the job.cron — A cron expression defining the schedule.handler — The async function to execute on each tick.options — Optional scheduling configuration.Returns: The unique job identifier.
setProvider(provider)Registers a cron provider as the active singleton. Called by bond packages during application startup.
function setProvider(provider: CronProvider): void
provider — The cron provider implementation to bond.| Provider | Package |
|---|---|
| Cron | @molecule/api-cron-bullmq |
| Cron | @molecule/api-cron-node-cron |
Peer dependencies:
@molecule/api-bond ^1.0.1@molecule/api-i18n ^1.0.1@molecule/api-bond@molecule/api-i18nclose() releases the bonded provider's resources (timers, queue/worker
connections) and is a no-op if the provider doesn't implement it — call
it during shutdown instead of reaching for getProvider().close?.()
directly. CronOptions.noOverlap (per-job, default false) skips a tick
that arrives while the previous run of the same job is still executing;
support and cross-process coordination are provider-specific — see each
bond's module docs.
Integration checklist — drive the real flow (no mocks), adapt each item to this app's actual scheduled jobs, and check every box off one by one. A box you can't check is an integration bug to fix — not a skip:
list() returns each one (or its schedule() call ran without error) — a
job that never registers never fires.runNow(jobId) (or invoke the handler directly) and assert the effect;
never stub the body. COUNTERPARTY: the sandbox process is short-lived, so a
real timed tick may never arrive — that is expected. Verify by direct
invocation, not by waiting minutes for the schedule to fire.status reflects it.cron expression and confirm it
matches the intended schedule (nightly, hourly, …) — verify by reading it,
not by waiting for a tick.