缺陷:采购重试响应断流后误报失败并可能诱导重复创建 #153

Open
opened 2026-08-29 14:49:20 +08:00 by ila · 0 comments
Owner

来源与现场事实

用户于 2026-08-29 在 Agent 0.9.23 重试正式采购失败任务时,界面先提示“无法重试采购”,异常包含 unexpected end of stream on;数秒后前台服务仍启动浏览器、打开 PDD 并开始执行采购。

数据库只读核对确认服务端实际已创建并调度 CG-18、CG-19、CG-20。相关任务均在后续地址保存阶段失败,且 irreversible_at、order_submitted_at 为空。本缺陷与 #152 地址保存证据问题关联,但必须独立修复,避免把网络结果对账混入地址自动化。

Gitea MCP 当前会话不可用,本工单按仓库规则回退项目配置的 Gitea API 创建。

根因判断

Agent 每次点击重试都会临时生成一个 requestId,调用重试接口后只按当前 HTTP 响应决定成功或失败。服务端已经按该 requestId 提交并创建新任务,但响应体读取期间连接异常结束;客户端捕获异常后丢失该 requestId,直接显示“无法重试采购”。既有前台调度器稍后仍能领取真实存在的新任务,造成提示与服务端事实冲突。

如果用户根据失败提示再次点击,客户端会生成新的 requestId,可能继续创建新的后继任务,因此不能简单自动用新 ID 重试 POST。

目标

  1. 一次用户确认只生成并持有一个重试 requestId。
  2. 遇到超时、EOF、连接重置等“提交结果未知”异常时,不显示“服务端拒绝/无法重试”。
  3. 使用同一个 requestId 进行有限次幂等重放或结果对账,识别服务端已创建的任务。
  4. 确认创建成功后只启动一次既有前台调度器,并展示源任务与新任务编号。
  5. 服务端明确拒绝时仍展示准确失败原因;无法在有限时间内确认时展示“结果确认中/请刷新任务记录”,不得用新 ID 重复提交。
  6. App/进程状态变化不得造成同一次用户操作生成多个重试请求。

非目标

  • 不自动重试采购自动化步骤。
  • 不修改地址保存逻辑(由 #152 处理)。
  • 不绕过服务端资格、设备互斥、最新任务、不可逆边界或幂等校验。
  • 不创建订单、不支付。
  • 不把 Token、地址、响应正文或个人数据写入日志。

建议方案

  • 将本次 requestId 提升为重试操作上下文,在响应明确前保持不变。
  • 对明确可判定为“响应结果未知”的 I/O 异常,使用同一个 requestId 做一次或有限次安全幂等重放;服务端 BatchRetry 既有 requestId 幂等结果应原样返回。
  • UI 区分:服务端明确拒绝、网络结果未知正在确认、已确认创建成功。
  • 按生命周期保护回调,防止旧请求覆盖新页面;成功后唤醒调度器保持幂等。
  • 增加服务端已提交但首个响应 EOF、同 requestId 重放返回同一任务、明确 4xx 不重放、持续无法确认不生成新 ID、快速重复点击只产生一个操作的测试。

依赖与并行

  • 关联 #152,但代码和验收可独立进行。
  • 可与 #152 v2 分析并行;提交应分离。
  • 若需要新增查询接口或改变共享契约,实施前必须更新本工单方案并补充 API 设计;优先复用既有 requestId 幂等重放,避免新增接口。

设计证据

恢复既有重试交互的真实反馈,不新增页面或主要流程。若仅调整现有加载/失败文案,可用明确状态清单作为小范围设计证据;如新增独立恢复入口则需先提供标注截图。

验收

  • 首次响应 unexpected end of stream、服务端实际已创建任务时,Agent 最终显示同一个新任务成功,不先误报“无法重试”。
  • 对账/重放始终复用原 requestId,不会产生第二个采购任务。
  • 服务端明确拒绝时不重放,准确显示原因。
  • 持续网络异常时显示结果未知提示,不启动第二次重试操作。
  • 成功只唤醒一次既有调度器,不绕过串行租约。
  • Android 定向与全量测试、Debug/Release 构建通过。
  • 不执行 live 重试,不修改地址,不创建订单,不支付。
  • 提交推送并回写证据,保持待用户验收。

风险

采购任务创建属于高风险状态变化。实现前需核对并保持服务端 requestId 幂等;真机发起重试前必须再次获得用户明确授权。

文档影响

若只恢复既有 requestId 幂等和真实反馈,无长期文档影响;如共享 API 或长期状态规则变化,则更新 Android Agent API Contract、业务规则及架构页面,并完成 Wiki-first 同步。

## 来源与现场事实 用户于 2026-08-29 在 Agent 0.9.23 重试正式采购失败任务时,界面先提示“无法重试采购”,异常包含 `unexpected end of stream on`;数秒后前台服务仍启动浏览器、打开 PDD 并开始执行采购。 数据库只读核对确认服务端实际已创建并调度 CG-18、CG-19、CG-20。相关任务均在后续地址保存阶段失败,且 `irreversible_at`、`order_submitted_at` 为空。本缺陷与 #152 地址保存证据问题关联,但必须独立修复,避免把网络结果对账混入地址自动化。 Gitea MCP 当前会话不可用,本工单按仓库规则回退项目配置的 Gitea API 创建。 ## 根因判断 Agent 每次点击重试都会临时生成一个 `requestId`,调用重试接口后只按当前 HTTP 响应决定成功或失败。服务端已经按该 `requestId` 提交并创建新任务,但响应体读取期间连接异常结束;客户端捕获异常后丢失该 `requestId`,直接显示“无法重试采购”。既有前台调度器稍后仍能领取真实存在的新任务,造成提示与服务端事实冲突。 如果用户根据失败提示再次点击,客户端会生成新的 `requestId`,可能继续创建新的后继任务,因此不能简单自动用新 ID 重试 POST。 ## 目标 1. 一次用户确认只生成并持有一个重试 `requestId`。 2. 遇到超时、EOF、连接重置等“提交结果未知”异常时,不显示“服务端拒绝/无法重试”。 3. 使用同一个 `requestId` 进行有限次幂等重放或结果对账,识别服务端已创建的任务。 4. 确认创建成功后只启动一次既有前台调度器,并展示源任务与新任务编号。 5. 服务端明确拒绝时仍展示准确失败原因;无法在有限时间内确认时展示“结果确认中/请刷新任务记录”,不得用新 ID 重复提交。 6. App/进程状态变化不得造成同一次用户操作生成多个重试请求。 ## 非目标 - 不自动重试采购自动化步骤。 - 不修改地址保存逻辑(由 #152 处理)。 - 不绕过服务端资格、设备互斥、最新任务、不可逆边界或幂等校验。 - 不创建订单、不支付。 - 不把 Token、地址、响应正文或个人数据写入日志。 ## 建议方案 - 将本次 `requestId` 提升为重试操作上下文,在响应明确前保持不变。 - 对明确可判定为“响应结果未知”的 I/O 异常,使用同一个 `requestId` 做一次或有限次安全幂等重放;服务端 `BatchRetry` 既有 requestId 幂等结果应原样返回。 - UI 区分:服务端明确拒绝、网络结果未知正在确认、已确认创建成功。 - 按生命周期保护回调,防止旧请求覆盖新页面;成功后唤醒调度器保持幂等。 - 增加服务端已提交但首个响应 EOF、同 requestId 重放返回同一任务、明确 4xx 不重放、持续无法确认不生成新 ID、快速重复点击只产生一个操作的测试。 ## 依赖与并行 - 关联 #152,但代码和验收可独立进行。 - 可与 #152 v2 分析并行;提交应分离。 - 若需要新增查询接口或改变共享契约,实施前必须更新本工单方案并补充 API 设计;优先复用既有 requestId 幂等重放,避免新增接口。 ## 设计证据 恢复既有重试交互的真实反馈,不新增页面或主要流程。若仅调整现有加载/失败文案,可用明确状态清单作为小范围设计证据;如新增独立恢复入口则需先提供标注截图。 ## 验收 - [ ] 首次响应 `unexpected end of stream`、服务端实际已创建任务时,Agent 最终显示同一个新任务成功,不先误报“无法重试”。 - [ ] 对账/重放始终复用原 `requestId`,不会产生第二个采购任务。 - [ ] 服务端明确拒绝时不重放,准确显示原因。 - [ ] 持续网络异常时显示结果未知提示,不启动第二次重试操作。 - [ ] 成功只唤醒一次既有调度器,不绕过串行租约。 - [ ] Android 定向与全量测试、Debug/Release 构建通过。 - [ ] 不执行 live 重试,不修改地址,不创建订单,不支付。 - [ ] 提交推送并回写证据,保持待用户验收。 ## 风险 采购任务创建属于高风险状态变化。实现前需核对并保持服务端 requestId 幂等;真机发起重试前必须再次获得用户明确授权。 ## 文档影响 若只恢复既有 requestId 幂等和真实反馈,无长期文档影响;如共享 API 或长期状态规则变化,则更新 Android Agent API Contract、业务规则及架构页面,并完成 Wiki-first 同步。
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: OPC/goauto#153