缺陷:统一采集与采购任务的设备心跳、忙碌和离线处理 #54

Closed
opened 2026-08-20 18:19:50 +08:00 by ila · 2 comments
Owner

原始需求摘要

执行 #42 Android 采购演练联调前发现:#34 已实现采购任务领取与运行状态,但设备心跳、设备列表和离线扫描仍只查询 collection_task。Android 若按共享契约上报正在运行的采购任务 ID,会被服务端拒绝为 DEVICE_TASK_MISMATCH;若改为不上报,又会破坏设备忙碌和离线失败事实。

提出时间:2026-08-20。来源:#42 实施中的跨端契约核对。

类型与范围

  • 类型:服务端跨任务域一致性缺陷
  • 交付单元:server、共享 API/Wiki 文档
  • 前置依赖:#34、#53(均已验收)
  • 阻塞:#42 的服务端联调与真机验收
  • 可并行:否;Android 不能通过伪造或省略当前任务绕过心跳契约
  • 不包含:Android 页面动作、地址修改、创建订单、支付、Admin 新页面、数据库迁移

当前事实与证据

  1. device/heartbeat.go:runningTaskForDevice 只查询 models.CollectionTask。
  2. device/list.go 的 Busy / CurrentTaskID 只查询运行中的采集任务。
  3. device/heartbeat.go:MarkStaleDevicesOffline 只把运行中的采集任务置为 DEVICE_OFFLINE,不处理采购任务和采购 attempt。
  4. purchase/lifecycle.go:ensureDeviceFree 已禁止采集与采购在同一设备并行,因此服务端应把两类任务统一视为设备当前任务。
  5. #42 当前 Android 单测和 APK 构建已通过,但在本缺陷修复前不能进行真实采购演练联调。

建议方案(实施前需确认)

  • 增加服务端统一的“设备当前活动任务”查询:同时检查运行中的采集任务和采购任务;正常状态最多一条,两域同时运行时返回明确内部一致性错误,不静默任选。
  • 心跳继续使用现有 currentTaskId 字段,不扩展 API;因为服务端已禁止一台设备跨域并行,当前任务 ID 足以用于本次兼容。
  • 设备列表的 Busy / CurrentTaskID 同时包含运行中的采购任务。
  • 设备离线时:
    • running 的采购任务转为 failed,错误码 DEVICE_OFFLINE,清除设备/账号运行槽和租约;对应运行 attempt 标为失败并记录结束时间。
    • order_submit_started 属于未来高风险不确定状态,不得误报普通失败;按既有安全边界转为 order_result_unknown 或由对应正式下单工单补充明确策略。本单测试必须固定该边界,不能自动重派或再次点击。
  • 保持现有采集任务行为不变,并补充同设备跨域冲突测试。

验收标准

  • 采购任务运行时,携带该任务 ID 的心跳成功且返回 busy=true;空值或错误 ID 返回 DEVICE_TASK_MISMATCH。
  • 设备列表对运行中的采购任务显示忙碌和正确任务 ID。
  • 演练采购任务运行中设备超时离线后,任务和 attempt 明确失败为 DEVICE_OFFLINE,租约及运行槽清理且不自动重试。
  • order_submit_started 离线不会被误标为可自动重试的普通失败。
  • 采集任务原有心跳、列表和离线测试保持通过。
  • 同一设备若异常出现采集与采购同时运行,服务端明确报一致性错误。
  • go test ./... 通过,Wiki-first 更新契约和交付索引。

风险

离线清理若错误处理已经点击创建订单的任务,可能造成重复下单。因此 order_submit_started 必须保留结果未知边界,禁止自动重派。本单不执行任何 PDD 或订单动作。

文档影响

  • Wiki:Android Agent API Contract、Business Rules and Glossary、Delivery Issues
  • Git 镜像:对应 docs/03、docs/08、docs/09
## 原始需求摘要 执行 #42 Android 采购演练联调前发现:#34 已实现采购任务领取与运行状态,但设备心跳、设备列表和离线扫描仍只查询 `collection_task`。Android 若按共享契约上报正在运行的采购任务 ID,会被服务端拒绝为 `DEVICE_TASK_MISMATCH`;若改为不上报,又会破坏设备忙碌和离线失败事实。 提出时间:2026-08-20。来源:#42 实施中的跨端契约核对。 ## 类型与范围 - 类型:服务端跨任务域一致性缺陷 - 交付单元:`server`、共享 API/Wiki 文档 - 前置依赖:#34、#53(均已验收) - 阻塞:#42 的服务端联调与真机验收 - 可并行:否;Android 不能通过伪造或省略当前任务绕过心跳契约 - 不包含:Android 页面动作、地址修改、创建订单、支付、Admin 新页面、数据库迁移 ## 当前事实与证据 1. `device/heartbeat.go:runningTaskForDevice` 只查询 `models.CollectionTask`。 2. `device/list.go` 的 `Busy` / `CurrentTaskID` 只查询运行中的采集任务。 3. `device/heartbeat.go:MarkStaleDevicesOffline` 只把运行中的采集任务置为 `DEVICE_OFFLINE`,不处理采购任务和采购 attempt。 4. `purchase/lifecycle.go:ensureDeviceFree` 已禁止采集与采购在同一设备并行,因此服务端应把两类任务统一视为设备当前任务。 5. #42 当前 Android 单测和 APK 构建已通过,但在本缺陷修复前不能进行真实采购演练联调。 ## 建议方案(实施前需确认) - 增加服务端统一的“设备当前活动任务”查询:同时检查运行中的采集任务和采购任务;正常状态最多一条,两域同时运行时返回明确内部一致性错误,不静默任选。 - 心跳继续使用现有 `currentTaskId` 字段,不扩展 API;因为服务端已禁止一台设备跨域并行,当前任务 ID 足以用于本次兼容。 - 设备列表的 `Busy` / `CurrentTaskID` 同时包含运行中的采购任务。 - 设备离线时: - `running` 的采购任务转为 `failed`,错误码 `DEVICE_OFFLINE`,清除设备/账号运行槽和租约;对应运行 attempt 标为失败并记录结束时间。 - `order_submit_started` 属于未来高风险不确定状态,不得误报普通失败;按既有安全边界转为 `order_result_unknown` 或由对应正式下单工单补充明确策略。本单测试必须固定该边界,不能自动重派或再次点击。 - 保持现有采集任务行为不变,并补充同设备跨域冲突测试。 ## 验收标准 - [ ] 采购任务运行时,携带该任务 ID 的心跳成功且返回 `busy=true`;空值或错误 ID 返回 `DEVICE_TASK_MISMATCH`。 - [ ] 设备列表对运行中的采购任务显示忙碌和正确任务 ID。 - [ ] 演练采购任务运行中设备超时离线后,任务和 attempt 明确失败为 `DEVICE_OFFLINE`,租约及运行槽清理且不自动重试。 - [ ] `order_submit_started` 离线不会被误标为可自动重试的普通失败。 - [ ] 采集任务原有心跳、列表和离线测试保持通过。 - [ ] 同一设备若异常出现采集与采购同时运行,服务端明确报一致性错误。 - [ ] `go test ./...` 通过,Wiki-first 更新契约和交付索引。 ## 风险 离线清理若错误处理已经点击创建订单的任务,可能造成重复下单。因此 `order_submit_started` 必须保留结果未知边界,禁止自动重派。本单不执行任何 PDD 或订单动作。 ## 文档影响 - Wiki:Android Agent API Contract、Business Rules and Glossary、Delivery Issues - Git 镜像:对应 `docs/03`、`docs/08`、`docs/09`
Author
Owner

实施完成,等待验收

实现提交:b0f33bf (fix(#54): unify device state across task domains),已推送 main。

实际方案:

  • 心跳和设备列表统一查询采集 running 与采购 running / order_submit_started。
  • 跨任务域异常同时运行返回内部一致性错误,不静默选择。
  • 设备离线时,普通运行采购任务及 attempt 以 DEVICE_OFFLINE 失败,清除租约和运行槽。
  • 已进入 order_submit_started 的任务转为 order_result_unknown,禁止自动重派或再次点击创建订单。
  • 未改变 currentTaskId 接口字段,没有数据库迁移,没有执行 PDD、创建订单或支付动作。

验证:

  • go test ./app/goauto/device:通过。
  • go test ./...:通过。
  • python dev_scripts/harness.py sync --verify:Wiki 镜像同步与 DevHarness 严格校验通过。
  • 未验证:Android 真机采购演练,归 #42。

Wiki-first:

  • Business-Rules-and-Glossary revision 39297e8886ddcd441c9cb874f399b3962055a3a1
  • Android-Agent-API-Contract revision 60e8cebb504e23f1a42076977d8d99b486909594
  • Delivery-Issues revision 7c3027260213a9b4dc969349f41cdd25d8337e13
  • 任务归档,revision 8ea157416a700450159e8f38443724c53d27b997

工单保持打开,等待用户验收。

## 实施完成,等待验收 实现提交:b0f33bf (`fix(#54): unify device state across task domains`),已推送 main。 实际方案: - 心跳和设备列表统一查询采集 `running` 与采购 `running` / `order_submit_started`。 - 跨任务域异常同时运行返回内部一致性错误,不静默选择。 - 设备离线时,普通运行采购任务及 attempt 以 `DEVICE_OFFLINE` 失败,清除租约和运行槽。 - 已进入 `order_submit_started` 的任务转为 `order_result_unknown`,禁止自动重派或再次点击创建订单。 - 未改变 `currentTaskId` 接口字段,没有数据库迁移,没有执行 PDD、创建订单或支付动作。 验证: - `go test ./app/goauto/device`:通过。 - `go test ./...`:通过。 - `python dev_scripts/harness.py sync --verify`:Wiki 镜像同步与 DevHarness 严格校验通过。 - 未验证:Android 真机采购演练,归 #42。 Wiki-first: - Business-Rules-and-Glossary revision `39297e8886ddcd441c9cb874f399b3962055a3a1` - Android-Agent-API-Contract revision `60e8cebb504e23f1a42076977d8d99b486909594` - Delivery-Issues revision `7c3027260213a9b4dc969349f41cdd25d8337e13` - [任务归档](https://git.ilapage.cn/OPC/goauto/wiki/Task-54-%E7%BB%9F%E4%B8%80%E9%87%87%E9%9B%86%E4%B8%8E%E9%87%87%E8%B4%AD%E4%BB%BB%E5%8A%A1%E8%AE%BE%E5%A4%87%E7%8A%B6%E6%80%81.-),revision `8ea157416a700450159e8f38443724c53d27b997` 工单保持打开,等待用户验收。
Author
Owner

用户于 2026-08-20 明确验收 #54。验收文档提交:e5b8d48;实现提交:b0f33bf。Delivery-Issues revision:9dca116d826e7c6a6f471363dc1a4114a18f7a12;任务归档 revision:4706314606de4614283157cc4e71af1747e029ad。Wiki 镜像同步与严格校验通过。

用户于 2026-08-20 明确验收 #54。验收文档提交:e5b8d48;实现提交:b0f33bf。Delivery-Issues revision:9dca116d826e7c6a6f471363dc1a4114a18f7a12;任务归档 revision:4706314606de4614283157cc4e71af1747e029ad。Wiki 镜像同步与严格校验通过。
ila closed this issue 2026-08-20 23:23:04 +08:00
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: OPC/goauto#54