定时任务

了解项目内置的三项 Cloudflare Cron 任务,以及新增定时任务时需要同步维护的配置和入口。

Saavo 使用 Cloudflare Workers Cron Triggers 定期启动系统维护工作。当前项目注册了三条定时规则,分别负责权益周期检查、过期数据清理和统计数据保留期清理。

Cron 只负责“按时触发”。实际工作可能在当前定时请求中完成,也可能转换为 Reaction 事件后交给后台队列处理。排查问题时,需要继续确认后续执行链,而不能只看 Cloudflare 是否触发过 Cron。

内置定时任务

Cloudflare Cron 按 UTC 时区运行。当前配置如下:

Cron 表达式入口常量触发时间实际工作
0 0 * * *ENTITLEMENT_CYCLE_CRON每天 00:00 UTC发出权益周期到期事件,并由后台任务处理到期记录
0 1 * * *DATA_CLEANUP_CRON每天 01:00 UTC发出每日数据清理事件
30 */6 * * *ANALYTICS_RETENTION_CRON每 6 小时的第 30 分钟直接清理超过保留期的原始统计事件

Cron 表达式同时存在于两个位置:

  • wrangler.jsonc 的 triggers.crons,决定 Cloudflare 何时调用 Worker;
  • src/entry/index.ts 的常量和 scheduledEntry 分支,决定触发后执行哪项工作。

两处字符串必须完全一致。当前入口对未知表达式没有专门的错误或告警;如果只改了其中一处,Cloudflare 仍可能显示触发成功,但不会进入任何业务分支。

各项任务如何执行

处理权益周期

每天的 Cron 会查找下一条到期记录并发出 EntitlementCycleDueEvent。后续的 process-due-entitlement-cycles 是异步 Command,默认每批最多处理 30 条到期记录。

权益系统还会通过 Timer Durable Object 安排下一次精确重置,并预留 10 秒缓冲。因此,每日 Cron 主要承担定期检查和恢复作用,不是权益重置唯一依赖的计时器。

清理过期业务数据

数据清理任务以 UTC 日期生成稳定的幂等键,同一天重复触发只会产生一次有效事件。后台 Command 会清理过期的登录会话、邮箱验证会话、密码重置会话、OAuth 授权会话、失效的 OAuth 令牌和授权码,以及符合条件的已软删除 OAuth 客户端。

多数数据按“一天前”作为清理边界;已过期的双重验证设置会话会直接清理。不要通过提高 Cron 频率来改变保留策略,应在数据所有者所在的服务中调整规则。

清理过期统计数据

统计清理直接在 scheduled 运行时操作 ANALYTICS_DB,不进入 async-policy-task。它按批次和运行预算删除过期原始事件,一次未清完的部分会留给后续 Cron 继续处理。

保留天数由 config/deploy.ts 中的 analytics.retention.rawDays 管理。调整 rawDays 不需要修改 Cron 表达式。具体行为见访问统计。

添加定时任务

新增一项 Cron 时,应完成以下改动:

  1. 在 wrangler.jsonc 的 triggers.crons 中添加表达式;
  2. 在 src/entry/index.ts 中定义对应常量;
  3. 在 scheduledEntry 中增加精确匹配的分支;
  4. 复用入口已经创建的 scheduled WorkerCtx,把业务规则交给所属 service;
  5. 工作耗时较长、需要可靠重试或会调用外部服务时,用 Reaction Event / Command 进入现有后台任务管道;
  6. 为新分支补充触发、重复执行和失败场景测试。

不要在 scheduledEntry 中直接写 SQL,也不要从非 HTTP 入口调用 resolveFetchWorkerCtx。需要异步执行的业务可以通过 Reaction 入队,后续执行方式见后台任务。

定时触发不等于执行完成

权益周期和数据清理在触发后还要经过 Reaction 与队列。Cloudflare 的 Cron 记录成功,只能证明 scheduled 入口被调用;最终结果应结合 Reaction 执行记录、日志和数据状态判断。

部署与排查

部署后可在 Cloudflare 仪表盘确认 Cron 是否按时触发。对于进入 Reaction 的任务,还应检查:

/dashboard/reaction/events
/dashboard/reaction/commands

统计数据清理不走 Reaction,应查看 scheduled 日志、告警以及 ANALYTICS_DB 中超过保留期的数据是否持续减少。

如果任务没有运行,按以下顺序排查:

  1. 对比 wrangler.jsonc 与入口常量,确认字符串和空格完全一致;
  2. 确认部署环境使用的是最新 Worker 配置;
  3. 确认 Cloudflare 已产生 Cron 触发记录;
  4. 检查入口日志是否进入预期分支;
  5. 对进入 Reaction 的任务检查事件、Command 和队列消费者;
  6. 对直接执行的统计清理检查数据库绑定、保留配置和积压告警。

上线检查

  • wrangler.jsonc 中的三条表达式与入口常量完全一致。
  • 已按 UTC 时区核对预期执行时间。
  • 三项内置任务均在部署环境成功跑过至少一次。
  • 权益周期和数据清理的 Reaction 事件、Command 均有正常记录。
  • 统计清理没有持续出现新增速度高于清理速度的积压告警。
  • 新增任务已覆盖重复触发、部分失败和安全重试场景。
  • 定时入口只负责调度,没有越过 service 或 repository 直接操作业务数据库。

常见问题

接下来