@aws-blocks/bb-cron-job

中文文档
0.4.0发布于 2026/11/02Apache-2.0TypeScriptES Module构建来源已验证近 30 天下载 6.3万

Scheduled task execution backed by EventBridge Scheduler and Lambda.

原始使用文档
文档目录21 节
  1. Quick Reference
  2. Quick Start
  3. When to Use
  4. When NOT to Use
  5. Options
  6. Running on Its Own Compute
  7. Schedule Expressions
  8. Rate Expressions
  9. Cron Expressions
  10. Handler Event
  11. Error Constants
  12. Examples
  13. Cron Schedule with Timezone
  14. Typed Input
  15. Disabled Job (Manual-Only in Dev)
  16. Handler Accessing Other Building Blocks
  17. Multiple Schedules for One Handler
  18. Best Practices
  19. Local Development
  20. AWS Deployment
  21. Key Distinction from AsyncJob

@aws-blocks/bb-cron-job

Scheduled task execution backed by EventBridge Scheduler and Lambda.

Design & mock parity details: DESIGN.md

Quick Reference

Common Operations → Configuration

What you wantHow to configure
Run every N minutesschedule: 'rate(5 minutes)'
Run every hourschedule: 'rate(1 hour)'
Run daily at 9 AM UTCschedule: 'cron(0 9 * * ? *)'
Run daily at 9 AM Pacificschedule: 'cron(0 9 * * ? *)', timezone: 'America/Los_Angeles'
Pass data to handlerinput: { mode: 'full' }
Disable until manually triggeredenabled: false

Keywords: cron, schedule, timer, periodic, recurring, rate, EventBridge, background, interval

Quick Start

import { Scope } from '@aws-blocks/core';
import { CronJob } from '@aws-blocks/bb-cron-job';

const scope = new Scope('my-app');

const cleanup = new CronJob(scope, 'cleanup', {
  schedule: 'rate(1 hour)',
  handler: async (event) => {
    console.log(`Running cleanup at ${event.scheduledTime}`);
    await deleteExpiredRecords();
  },
});

When to Use

  • Running periodic cleanup tasks (expired sessions, stale data)
  • Generating scheduled reports
  • Cache warming on a timer
  • Data synchronization between systems
  • Periodic health checks or monitoring

When NOT to Use

  • One-off async tasks triggered by events or user actions → use AsyncJob
  • Reacting to data changes → use event subscriptions on the relevant Building Block

Options

OptionTypeDefaultDescription
schedulestring(required)Cron or rate expression (see Schedule Expressions below)
handler(event: CronJobEvent<T>) => Promise<void>(required)Function to execute on each invocation. Must be idempotent.
enabledbooleantrueWhether the schedule is active
descriptionstring—Human-readable description of the job
timezonestring'UTC'IANA timezone for cron expressions (e.g., 'America/Los_Angeles')
inputT—Static payload passed to the handler on every invocation
computeComputeProvider<'serverless'>the scope's computeA serverless Compute to run the handler on (see Running on Its Own Compute)

Running on Its Own Compute

By default the handler runs on its scope's compute, which is the app's default compute unless the scope sets one (new Scope(id, { parent, compute })). Pass a serverless Compute to give the job its own function, for example more memory or a longer timeout than the API's:

import { Compute, CronJob } from '@aws-blocks/blocks';

const reports = new Compute(scope, 'reports', { type: 'serverless', memory: 2048, maxTimeoutSeconds: 900 });

new CronJob(scope, 'monthly-report', {
  schedule: 'cron(0 3 1 * ? *)',
  compute: reports,
  handler: async () => { /* … */ },
});

Only a serverless compute can run a CronJob for now, because the schedule invokes the compute's function directly. Passing a container compute is a type error, and a container compute inherited from the scope fails synth. Locally, every job runs in the dev server whatever its compute.

Schedule Expressions

Rate Expressions

Simple interval-based schedules:

rate(1 minute)
rate(5 minutes)
rate(1 hour)
rate(12 hours)
rate(1 day)
rate(7 days)

Cron Expressions

AWS EventBridge cron format (6 fields): cron(minute hour day-of-month month day-of-week year)

cron(0 9 * * ? *)       → daily at 9:00 AM
cron(0 */2 * * ? *)     → every 2 hours
cron(30 9 ? * MON-FRI *) → weekdays at 9:30 AM
cron(0 0 1 * ? *)       → first day of every month at midnight

Use ? for either day-of-month or day-of-week (one must be ?).

Handler Event

The handler receives a CronJobEvent<T> with:

FieldTypeDescription
scheduledTimestringISO 8601 timestamp of the scheduled invocation time
jobNamestringThe CronJob's fully-qualified id
inputTStatic input configured on the CronJob (undefined when no input is provided)

Error Constants

import { CronJobErrors } from '@aws-blocks/bb-cron-job';

CronJobErrors.InvalidSchedule  // schedule expression is not a valid cron or rate format
CronJobErrors.InvalidTimezone  // timezone string is not a valid IANA timezone

Both errors are thrown at construction time (fail-fast validation).

Examples

Cron Schedule with Timezone

const dailyReport = new CronJob(scope, 'daily-report', {
  schedule: 'cron(0 9 * * ? *)',
  timezone: 'America/Los_Angeles',
  description: 'Generate and email daily analytics report at 9 AM Pacific',
  handler: async (event) => {
    const data = await analytics.query({ date: event.scheduledTime });
    await email.send('[email protected]', 'Daily Report', formatReport(data));
  },
});

Typed Input

new CronJob<{ keys: string[] }>(scope, 'cache-warmer', {
  schedule: 'rate(5 minutes)',
  input: { keys: ['top-products', 'featured'] },
  handler: async (event) => {
    for (const key of event.input.keys) {
      await warmCache(key);
    }
  },
});

Disabled Job (Manual-Only in Dev)

const migration = new CronJob(scope, 'data-migration', {
  schedule: 'rate(1 day)',
  enabled: false,
  handler: async () => {
    await migrateRecords();
  },
});

Handler Accessing Other Building Blocks

const store = new KVStore(scope, 'sessions');

const sessionCleanup = new CronJob(scope, 'session-cleanup', {
  schedule: 'rate(1 hour)',
  handler: async () => {
    const now = Date.now();
    for await (const session of store.scan()) {
      if (session.expiresAt < now) {
        await store.delete(session.key);
      }
    }
  },
});

Multiple Schedules for One Handler

const syncHandler = async (event: CronJobEvent<{ mode: string }>) => {
  if (event.input.mode === 'incremental') await syncIncremental();
  else await syncFull();
};

new CronJob<{ mode: string }>(scope, 'sync-hourly', {
  schedule: 'rate(1 hour)',
  input: { mode: 'incremental' },
  handler: syncHandler,
});

new CronJob<{ mode: string }>(scope, 'sync-daily', {
  schedule: 'cron(0 9 * * ? *)',
  input: { mode: 'full' },
  handler: syncHandler,
});

Best Practices

  • Idempotency: EventBridge provides at-least-once delivery. Design handlers to tolerate duplicate invocations.
  • Rate expressions for simple intervals; cron expressions for precise timing.
  • Concurrent executions: If a handler runs longer than the schedule interval, the next invocation starts while the previous is still running. Design for overlap or implement application-level locking with KVStore.
  • Failure handling: Handler exceptions are retried by Lambda's built-in async invoke retry policy (2 retries with exponential backoff). After retries exhaust, the error is logged to CloudWatch.

Local Development

In local dev mode, CronJob runs schedules in-process:

  • Rate schedules use setInterval
  • Cron schedules calculate the next fire time with timezone support and use setTimeout
  • Console logs when the job fires: [CronJob:{id}] triggered at {timestamp}
  • When enabled: false, the schedule does not run automatically
  • Failed handlers are logged with a warning that AWS would retry

AWS Deployment

Automatically provisions:

  • EventBridge Schedule: One AWS::Scheduler::Schedule per CronJob instance
  • Shared Lambda: Targets the shared Lambda (same as API handlers and AsyncJob). No dedicated Lambda per job.
  • IAM role: Per-stack EventBridge Scheduler role with lambda:InvokeFunction permission. Its trust policy is limited to schedules in the stack's account and region (aws:SourceAccount + aws:SourceArn matching schedule-group/*).
  • Schedule name: Derived from the CronJob's fullId (truncated to 64 chars)

Key Distinction from AsyncJob

CronJob is a pure infrastructure declaration — the constructor defines the schedule and handler. There are no runtime methods like submit() or submitBatch(). The handler runs on the schedule automatically.

CronJobAsyncJob
TriggerTime-based (cron/rate)Programmatic (submit())
Runtime methodsNonesubmit(), submitBatch()
Use casePeriodic recurring tasksOne-off event-driven work
AWS serviceEventBridge SchedulerSQS + Lambda

版本与发布记录

@aws-blocks/bb-cron-job 共发布 14 个版本,首次发布于 2026/06/16;过去 12 个月发布了 14 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.4.0latest2026/11/025 天前
0.3.02026/10/1622 天前
0.0.0-canary.esql-canary.c93c81b.1791235863canary-esql-canary2026/10/061 个月前
0.2.22026/10/051 个月前
0.0.0-canary.esql-canary.f7f39ac.17909891272026/10/031 个月前
0.0.0-canary.ci-publish-canary-npm.f53dfdc.1790988617canary-ci-publish-canary-npm2026/10/031 个月前

关于 @aws-blocks/bb-cron-job 的常见问题

@aws-blocks/bb-cron-job 是什么?

Scheduled task execution backed by EventBridge Scheduler and Lambda.

如何安装 @aws-blocks/bb-cron-job?

在项目目录运行 npm install @aws-blocks/bb-cron-job,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:constructs(^10.0.0)、aws-cdk-lib(^2.257.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@aws-blocks/bb-cron-job 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@aws-blocks/bb-cron-job 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@aws-blocks/bb-cron-job 可以商用吗?

@aws-blocks/bb-cron-job 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@aws-blocks/bb-cron-job 的下载量有多少?

根据 npm 官方下载统计,@aws-blocks/bb-cron-job 在 2026/10/07 – 2026/11/05 这 30 天内被下载 63,155 次,日均约 2,105 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@aws-blocks/bb-cron-job 还在维护吗?

最新版本 0.4.0 发布于 2026/11/02(5 天前);至今共发布 14 个版本,其中过去 12 个月发布了 14 个;首次发布于 2026/06/16。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。