问题
AlertEngine 每次检查后把 lastCheckedAt 写成墙上时钟;evaluateNews() 却用它过滤 NewsItem.timestamp(新闻发布时间)。两者不是同一进度:provider 在下次轮询才返回一条此前已发布的文章时,timestamp <= lastCheckedAt,规则永久漏报。多篇新闻共享同一秒发布时间时,单纯改成时间水位仍会漏报。
可复现路径
- 17:00 首次收到文章 a(发布时间 16:59),触发告警;规则写入
lastCheckedAt=17:00。
- 17:01 轮询仍只有 a,规则写入
lastCheckedAt=17:01。
- 随后 provider 返回新文章 b(发布时间 17:00:30);当前过滤条件
b.timestamp > 17:01 为假,且之后的检查时间只会增加,因此 b 永远不会触发。
- 若文章 c 与 b 同秒发布,用发布时间水位去重也会丢 c。
期望
- 用 provider 稳定的文章 ID 去重,并跨进程重启持久化;迟到和同秒新文章各触发一次。
- 旧规则第一次升级时延续
lastCheckedAt 的过滤语义,避免一次性重放全部既有新闻;从此按文章 ID 判断。
- 限制持久化去重状态大小,避免长时间运行无限增长。
- 保留
lastCheckedAt 作为最近检查时间,不再混用它作为已见文章身份。
- 通过真实
AlertEngine.tick()、文件仓库重载、无新消息轮询的回归测试,先在干净 main 上复现失败,再验证修复。
与现有新闻筛选的 news-surge 修复 #219 不重叠:本问题在告警规则的持久化轮询去重路径。
问题
AlertEngine每次检查后把lastCheckedAt写成墙上时钟;evaluateNews()却用它过滤NewsItem.timestamp(新闻发布时间)。两者不是同一进度:provider 在下次轮询才返回一条此前已发布的文章时,timestamp <= lastCheckedAt,规则永久漏报。多篇新闻共享同一秒发布时间时,单纯改成时间水位仍会漏报。可复现路径
lastCheckedAt=17:00。lastCheckedAt=17:01。b.timestamp > 17:01为假,且之后的检查时间只会增加,因此 b 永远不会触发。期望
lastCheckedAt的过滤语义,避免一次性重放全部既有新闻;从此按文章 ID 判断。lastCheckedAt作为最近检查时间,不再混用它作为已见文章身份。AlertEngine.tick()、文件仓库重载、无新消息轮询的回归测试,先在干净 main 上复现失败,再验证修复。与现有新闻筛选的
news-surge修复 #219 不重叠:本问题在告警规则的持久化轮询去重路径。