Skip to content

fix(engine): 错过任务检测漏查时间规则,00:00 任务永远触发不到 - #46

Open
AmberCXX wants to merge 1 commit into
LinekForge:mainfrom
AmberCXX:fix/engine-missed-task-detection
Open

fix(engine): 错过任务检测漏查时间规则,00:00 任务永远触发不到#46
AmberCXX wants to merge 1 commit into
LinekForge:mainfrom
AmberCXX:fix/engine-missed-task-detection

Conversation

@AmberCXX

Copy link
Copy Markdown
Contributor

动机

生产环境观察到两个现象:

  1. 「每周日 22:00」的任务在周六被报成「今天错过」——收到 [错过的任务] 通知,但该任务当天根本不该跑
  2. 排在 00:00 的任务从未按时触发过——翻 engine-trigger-log,某个 00:00 任务历史上 4 次触发全在下午(16:29 / 17:11 / 17:27),都是被别的 reload 顺带唤醒的,没有一次在 00:00

根因是同一处:scheduleOrigin() 建定时器时走 canScheduleToday(),而它只查 start_date / end_date;完整时间规则在 shouldFire() 里,只在 fire() 时才调用(scheduler.ts:241)。

于是排期阶段:

  • weekdays/days/months 不参与 → 非当天的任务也会进 missed 列表
  • delay <= 0 一律进 missed → 午夜重排在 00:00 跑时,target - now 恰为负,00:00 的格子被自己判成已过去

改动概要

forge-engine/scheduler.ts

  • 新增 FIRE_GRACE_MS = 90 * 1000
  • scheduleOrigin() 增加宽限支:delay 落在 (-FIRE_GRACE_MS, 0] 且通过 shouldFire() → 立即补触发(1s 后),计入 count,不报错过
  • missed 支补 && shouldFire(entry)
  • shouldFire 改为 export(仅为可测性,无行为变化)

forge-engine/scheduler.test.ts

  • 新增 3 个回归测试覆盖 weekdays / days / 无条件默认

影响范围

  • forge-engine 排期路径,不涉及 hub-server / 通道 / 审批
  • 行为变化有二:① 刚过点 90s 内的任务会被补触发(此前静默丢失)② 不该在今天跑的任务不再出现在「错过的任务」通知里
  • FIRE_GRACE_MS 取 90s 是保守值:足以覆盖午夜重排与冷启动的秒级偏差,又远小于最密的任务间隔(本地为 1 小时)。如需可配我可以改成常量导出或读 config

self-test 结果

$ bun hub-test-harness/harness.ts
📊 8/8 通过

$ fh hub self-test
📊 8/8 通过

$ bun test          # forge-engine
22 pass, 0 fail, 76 expect() calls

安全自检

$ grep -rE '@im\.wechat|ou_[a-f0-9]{16,}|sk-ant-[a-zA-Z0-9_-]{20,}|sk-[a-zA-Z0-9_-]{20,}|[0-9]{9,10}:[A-Za-z0-9_-]{35}' forge-engine/scheduler.ts forge-engine/scheduler.test.ts
(无输出)

无私人 ID / 密钥;测试用例不含真实 sender_id。

未覆盖

FIRE_GRACE_MS 那条宽限支没有专门的单元测试——它在 scheduleOrigin() 内,需要 mock Server 才能测。本地是通过日志验证的:把某任务从 00:00 改到 22:00 后重排显示 排定 1,而同一任务在 00:00 时显示 排定 0。如果你希望补这个测试,告诉我要不要把 scheduleOrigin 拆得更可测,我再提一版。

🤖 Generated with Claude Code

https://claude.ai/code/session_016fd3qWDATPyaLxwM8s1Ag9

scheduleOrigin 建定时器时只过 canScheduleToday(仅查 start_date/end_date),
未过 shouldFire,导致两个问题:

1. weekdays/days/months 不参与判定——「每周日」的任务会在周六被
   报成「今天错过」
2. delay <= 0 一律落进 missed 分支——午夜重排本身发生在 00:00,
   重排那一刻就把 00:00 的格子算成已过去,该时段任务永远跑不到

修法:
- 新增 FIRE_GRACE_MS(90s)宽限支,刚过点的任务立即补触发而非报错过
- missed 与宽限两支都补 shouldFire(entry)

shouldFire 改为 export 以便测试,并补 3 个回归测试。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016fd3qWDATPyaLxwM8s1Ag9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant