Files
junhong_cmp_fiber/openspec/changes/archive/2026-08-21-fix-daily-retention-pending-cleanup/design.md
2026-08-26 14:54:26 +08:00

3.5 KiB
Raw Blame History

Context

见 proposal.md。现有实现以 Audit 和 Integration 归档对作为原子清理单元,且在生成 Integration 最终 revision 前要求整日不存在 pending。2026-08-18 的 458 条 Gateway 同步轮询遗留 pending 因而阻断约 314 万条 Integration Log 和后续日期的清理。

Goals / Non-Goals

Goals:

  • 只保留 pending Integration Log 在线,尽快释放已终态日志和审计数据。
  • 保持删除前可恢复归档和逐批续跑语义。
  • 防止旧 Gateway 轮询处理器静默制造新的永久 pending。

Non-Goals:

  • 不直接修改历史 pending 的结果或删除它们。
  • 不改变 Integration Log 的写入频率、JSONL 格式、对象存储格式或数据库 Schema。
  • 不在 Worker 内执行 VACUUM 或表重写。

Decisions

归档覆盖全日,删除只匹配终态

仍按创建日生成包含全部记录的归档 revision移除“存在 pending 即不得最终归档”的门禁。留存校验确认当前在线集合与该 revision 一致后,删除条件限定为 result <> 'pending'。这样每条已删除数据都在对象存储中存在恢复副本,而 pending 永不被删除。

不按结果分别创建归档文件:会改变既有归档格式和恢复语义,且没有必要。

Audit 与 Integration 分来源推进

Audit 归档校验成功后独立完成 Audit 资源和事件删除Integration 的 pending 或残留不再使 Audit 退化为未清理。每个来源仍按自身失败日阻断该来源后续日期,避免跨越该来源的归档或校验故障。

不继续要求两来源同日原子清理:该设计正是容量积压的根因,且两类数据已有独立的归档账本和清理断点。

以剩余可删除记录决定 Integration 续跑

已经删除过终态记录的日期不因只剩 pending 而反复阻断日期扫描。若旧 pending 后续进入终态,则该日期重新生成 revision、验证当前在线集合并删除新增终态记录。查询仅检查可删除终态记录和对应清理断点避免对只含 pending 的大历史范围反复做全表工作。

Gateway 失败分支不吞终结错误

三个旧轮询 Handler 对已创建的尝试使用受控收口:终结写入失败返回任务错误并保留重试信号;不再使用 _ = completeGatewayAttempt(...) 静默丢弃错误。任务取消时仍尝试使用不受取消影响的短生命周期上下文终结该条日志。

Risks / Trade-offs

  • [终态日志在归档和删除间新增或变化] → 归档后重新统计和校验;不一致时不删除并在下次重建 revision。
  • [pending 永久不终结] → 仅保留这些记录,不能阻止终态数据和审计数据释放;通过调查接口和留存日志排查。
  • [PostgreSQL 文件空间不立即缩小] → DELETE 回收空间供后续写入复用;维护者按运行手册评估 VACUUM不由 Worker 自动执行。
  • [旧 pending 终结后遗漏清理] → 续跑选择条件识别清理后进入终态的记录,并重建该日 revision。

Migration Plan

  1. 发布 Worker 二进制,保持既有物理清理开关状态。
  2. 若当前开关关闭,维护者在低峰期启用后重启调度 Worker。
  3. 观察 logs/audit-retention.logtb_log_archive_run 清理断点和数据库磁盘指标8 月 18 日的已终态记录应先被清理458 条 pending 保留。
  4. 若归档或删除异常,关闭清理开关并重启 Worker已删除记录通过对应归档 revision 恢复,未删除记录仍在线。