# 91 修复重新上报导致任务状态与 Outbox 不一致 - 类型:缺陷 - 父级大工单:#1 - 所属 MVP / 版本:#2 - 状态:已完成,用户验收通过 - 日期:2026-08-10 - Gitea 工单:http://ilaer.eicp.net:8418/chengma/cmautobuy/issues/91 ## 背景与目标 已完成任务在后续重新采集失败后,如果重新上报旧结果,旧代码会把任务主状态重新改成“已完成”。任务实际上仍有待发送的失败事件,因此再次点击“重新执行”又会被未发送 Outbox 拦截。 本次修复重新上报的事件选择和状态更新规则,保证历史事件不能覆盖最新一次执行状态,并让现有“假完成”记录在最新失败信息上报成功后恢复正确状态。 ## 最终方案 - 重新上报优先选择任务最早一条尚未发送的 Outbox,包括 `task_failure`;全部事件已发送时才重发最新结果。 - Worker 根据事件类型分别调用 Admin 的结果提交接口或失败提交接口,继续使用原始幂等键和负载。 - 事件首次发送和历史重发通过 `sent_at` 区分。历史结果重发成功只更新 Outbox,不再修改任务主状态。 - 只有事件的 `attempt_id` 与最新执行记录一致时,事件才能更新任务状态。 - 最新失败事件上报成功后,使用原始失败负载恢复 `failed`、`retry_wait`、`manual_review` 或 `cancelled` 状态;旧失败事件不能覆盖新成功。 - 重新执行的拦截提示区分“结果”和“失败信息”,并提示勾选任务点击“重新上报”。 - 没有修改数据库表结构、Admin 接口或 Android 自动化代码。 实现与建单方案一致。 ## 改了哪些 - `client/src/task_repository.py`:增加重新上报事件选择,并按最新执行安全更新任务状态。 - `client/src/pdd_ui_event.py`:失败事件改用失败提交接口,更新确认和进度文案。 - `client/test/test_task_repository.py`:覆盖旧结果、新失败、旧失败和新成功的状态顺序。 - `client/test/test_pdd_ui_event.py`:覆盖失败事件优先上报、状态修复和不调用 Android。 - `client/AGENTS.md`:明确重新上报优先处理未发送 Outbox。 - `docs/client/03-data-model.md`:记录重新上报的状态一致性规则。 - `docs/client/05-ui-specification.md`:更新重新上报范围和交互说明。 ## 验收结果 | 验收标准 | 结果 | |---|---| | 重发旧结果不会隐藏最新失败状态 | 通过 | | 存在待发送失败事件时优先上报该事件 | 通过 | | 最新失败事件上报后恢复对应失败状态 | 通过 | | 旧失败事件不会覆盖新成功状态 | 通过 | | 全部事件已发送时仍可重发最新结果 | 通过 | | 重新执行提示准确区分结果和失败信息 | 通过 | | 不创建新 Outbox、不改 Admin 接口、不调用 Android | 通过 | | Client 完整自动测试通过 | 通过,共 235 项 | ## 测试 - 执行的命令:在 `client/` 目录执行 `C:/Python310/python.exe -m unittest discover -s test -p "test_task_repository.py"`。 - 结果:17 项通过。 - 执行的命令:在 `client/` 目录执行 `C:/Python310/python.exe -m unittest discover -s test -p "test_pdd_ui_event.py"`。 - 结果:37 项通过。 - 执行的命令:在 `client/` 目录执行 `C:/Python310/python.exe -m unittest discover -s test -p "test_*.py"`。 - 结果:`Ran 235 tests in 9.777s`,`OK`。 - 执行的命令:PyQt5 离屏创建并关闭 `MainWindow`。 - 结果:输出 `OK`。 - **没验证到的部分**:没有用真实 Admin 上报现场任务 `COL-3dec8b1e10f28954`,因此没有修改用户现有数据库中的这条记录;没有操作 Android 手机。 ## 相关提交 - `077cba6` 修复重新上报任务状态不一致