Skip to content

feat(schedule): 停机错过触发点的记录与补偿(misfire) - #84

Merged
chumingjun merged 1 commit into
mainfrom
feat/schedule-misfire-catchup
Aug 28, 2026
Merged

feat(schedule): 停机错过触发点的记录与补偿(misfire)#84
chumingjun merged 1 commit into
mainfrom
feat/schedule-misfire-catchup

Conversation

@chumingjun

Copy link
Copy Markdown
Owner

Closes #57

背景

调度器重启恢复后从「当下」计算下一次触发(schedule.js 的 armNext),dsh 停机期间错过的触发点静默丢失:凌晨到早上之间的日报永远不发,且统计完全不可见——用户只能从「飞书怎么没收到通知」倒推。

方案(issue 两层设计,全部向后兼容)

记录兜底(必做)

  • 恢复调度链(ensureTriggers)时对比落盘 nextAt 与当下,过期超宽限(60s,避免杀进程瞬间竞态误计)即给 meta 记一次 misfireCount 并立即落盘
  • 调度中心统计行可见:「已触发 N 次(停机错过 M 次)」
  • 停用任务不计(本就无到点义务);一次停机无论错过几个触发点只计 1

补跑策略(per-schedule 可选)

  • meta 新增 misfirePolicy: ignore(默认,升级零感知,旧 triggers.json 自动补默认值)| catchUp
  • 选补跑的任务重启后经 setImmediate 补跑最近一次:source='catch-up',只补一次防雪崩,计入 fireCount
  • 属主关系遵守 fix(orchestrator): 定时统计唯一属主与触发即落盘(#35 自查遗留) #37 教训:detectScheduleMisfire 是 schedule.js 里的纯函数只回传事实 {count, catchUp},计数与补跑属主保持在 index.js

前端

  • SOURCE_LABEL/ICONcatch-up=补跑/⏱;run-start 视图闸门把 catch-up 与 schedule/webhook 同列(不抢占当前画布),仅 toast 提示
  • ScheduleCenter 表单新增「错过触发点」单选段(忽略/补跑一次),统计行展示 misfire 次数与「停机补跑」标记

验证

  • 单测:schedule.test.mjs 17 套全绿(新增 detectScheduleMisfire 9 组断言 + meta 落盘字段)
  • 集成:schedule-api.integration.test.mjs 12 套全绿(新增第二 apply 实例模拟重启恢复:记账落盘 / ignore 不补跑 / catchUp 补跑一条 source=catch-up / 同实例幂等);并修复第二实例挂住事件循环问题
  • 前端:run-event-routing 8 套、run-switcher 7 套全绿
  • 全量回归 npm test + build-web.sh 双构建通过
  • 真实 dsh 实测(临时 profile 源码 link 本分支):catchUp 任务停机 30 分钟 → 重启后 misfireCount+1、自动补跑 success 运行;ignore 任务同样停机 → 只记账不补跑;二次停机再验证 catchUp 继续补跑、计数累计落盘
  • 真实浏览器 E2E(Playwright + CDP):调度中心统计行「停机错过 2 次/1 次」与「停机补跑」标记可见;编辑表单「错过触发点」段存在且 catchUp 任务选中「补跑一次」

验证环境已全部清理(profile / 工作区 / 临时脚本)。

#57 两层实现:
- 记录兜底(必做):恢复调度链时对比落盘 nextAt 与当下,过期超宽限
  (60s,避免杀进程瞬间竞态误计)即计一次 misfireCount 并立即落盘;
  调度中心统计行可见「停机错过 N 次」
- 补跑策略(可选):meta 新增 misfirePolicy=ignore(默认,升级零感知)
  /catchUp;选补跑的任务重启后经 setImmediate 补跑最近一次(source=
  catch-up,只补一次防雪崩),计入 fireCount,前端胶囊/结果面板可区分

约束遵守:计数与补跑属主保持在 index.js(#37 教训),schedule.js 只
回传事实(detectScheduleMisfire 纯函数);补跑走同一 startRun 入口。

前端:SOURCE_LABEL/图标加 catch-up=补跑、run-start 视图闸门放行不抢
占、ScheduleCenter 表单加「错过触发点」单选 + 统计行展示。

测试:schedule.test.mjs 补 detectScheduleMisfire 9 组断言;集成测试
新增第二 apply 实例模拟重启恢复(记账落盘/ignore 不补跑/catchUp 补跑
一条/幂等守卫),并修复第二实例挂住事件循环问题(清理走 ctx2)。
@chumingjun
chumingjun merged commit 1e60647 into main Aug 28, 2026
1 check passed
@chumingjun
chumingjun deleted the feat/schedule-misfire-catchup branch August 28, 2026 08:37
chumingjun added a commit that referenced this pull request Aug 28, 2026
v0.6.0 之后 main 合入一个用户可见改动:
- 定时任务停机错过触发点的记录与补偿(#57/#84)

一个 feat → minor 口径下发 patch 亦可,但取 0.6.1 保持
「一个发版窗口一个 minor」的节奏:源码树 8 包与 dsh-ccpg-one
依赖表同步 bump;升级器测试 npm latest mock 0.6.0 → 0.6.1
(保持 latest 领先已装语义)。npm 渠道仍只发单包
dsh-harness-one(版本取 dsh-ccpg-one)。

验证:全量单测绿;build-web.sh 双构建通过;assemble-one +
publish-npm --dry-run 通过(dsh-harness-one@0.6.1)。
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.

定时任务:停机错过触发点的记录与补偿(misfire)

1 participant