每日定时扫描
不必等人点按钮:每天定时检查所有已注册的程序,只对产生了新提交的程序发起分析。
为什么需要它
跨程序影响最容易漏在”没人主动去看”的时候。上游服务改了接口,下游团队往往在联调甚至上线后才发现。 定时扫描把这件事变成后台自动完成的例行检查。
判定逻辑
对每个已注册程序:
① 有分析正在进行? → 跳过(避免重复)
② 位置不可访问? → 跳过(报告一次,不反复重试)
③ 解析当前提交
④ 与"上次成功分析记录的提交"比较
相同 → 跳过(没有新提交)
不同 → 发起分析
⑤ 没有其他程序可比较? → 跳过
第 ④ 步依赖一个容易被忽略的细节:分析实际比较的提交必须落库。 否则调度无法区分”已分析过这个提交”和”从未分析”,每天都会把全部程序重扫一遍。
配置
code-association:
schedule:
enabled: true # 总开关
cron: "0 30 2 * * *" # 每天 02:30
run-on-startup: false # 启动后补跑一次
max-programs-per-run: 20 # 单次扫描的程序上限
directory-rescan-minutes: 1440 # 无提交可比的普通目录,按时间间隔重扫
| 配置项 | 默认值 | 说明 |
|---|---|---|
enabled |
true |
关闭后 cron 不再触发 |
cron |
0 30 2 * * * |
Spring cron 六段式:秒 分 时 日 月 周 |
run-on-startup |
false |
补跑停机期间错过的扫描;默认关,避免重启循环触发 |
max-programs-per-run |
20 |
程序很多时限制单次开销 |
directory-rescan-minutes |
1440 |
普通目录没有 commit 可比,改按时间间隔判断 |
运维接口
查看状态
curl http://127.0.0.1:9996/api/schedule
{
"enabled": true,
"cron": "0 30 2 * * *",
"running": false,
"last": {
"status": "DONE",
"registered": 4,
"scanned": 0,
"skipped": 4,
"failed": 0,
"durationMs": 69706,
"details": [
{ "sourceName": "AI-Worksplace", "outcome": "SKIPPED", "reason": "没有新提交" },
{ "sourceName": "web-router", "outcome": "SKIPPED", "reason": "没有新提交" },
{ "sourceName": "demo-platform", "outcome": "SKIPPED", "reason": "位置不可访问:/tmp/ca-demo-repo" }
]
}
}
details 是排查的关键:它告诉你每个程序为什么被扫描或跳过,不用翻日志。
立即执行一次
curl -X POST http://127.0.0.1:9996/api/schedule/run
异步返回。完整扫描要 fetch 远程仓库并索引代码,可能几分钟,超过任何合理的 HTTP 超时。
调用后轮询 GET /api/schedule 看结果。
两个可靠性细节
孤儿任务恢复
进程被杀死(或部署重启)时,正在运行的分析会永远停在 RUNNING。
后续每次扫描都会把它当作”忙碌”而跳过——这个程序再也不会被扫描。
启动时会把这类记录标记为失败:
WARN recovered 2 analysis run(s) left RUNNING by a previous process
判定依据是”本进程刚启动,不可能有任何存活任务”,所以不需要宽限期。
提交要落库
finishAnalysis 会把实际比较的 base/head commit 写回 analysis 表。
没有这一步,调度永远认为”没分析过”,每天全量重扫——实测过:scanned=4 / skipped=0,
修复后 scanned=0 / skipped=4。
扫描范围
定时扫描和手动分析遵循同一规则:每次都以其余所有程序为对比对象, 只报告对其他程序的影响。不存在”定时扫描只看自己”的模式。