feat: add safe agent purchase retry (#95)
This commit is contained in:
@@ -2,8 +2,8 @@
|
||||
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
|
||||
wiki_page: Architecture-and-Code-Map
|
||||
wiki_url: https://git.ilapage.cn/OPC/goauto/wiki/Architecture-and-Code-Map.-
|
||||
wiki_revision: 9a52b45dc154e741ee2abcd9e74b947fa3745a28
|
||||
synchronized_at: 2026-08-26T02:11:15Z
|
||||
wiki_revision: 293ee8c705efbc41d4ce7d4a6f6631652cef9f83
|
||||
synchronized_at: 2026-08-26T06:26:15Z
|
||||
<!-- gitea-wiki-mirror:end -->
|
||||
|
||||
# 架构与代码地图
|
||||
@@ -179,3 +179,9 @@ Android Portal/Agent
|
||||
- 服务端 `task/lifecycle_service.go` 的同一 Reset 事务同时服务管理端和设备端;设备端入口使用显式 Device Token 模式,不能用空 Token 退化为管理端路径。
|
||||
- `POST /api/agent/v1/collection-tasks/{taskId}/reset` 只返回最小状态,设备归属、忙碌和商品冲突在事务内检查。
|
||||
- Android `TaskHistoryFragment` 只在采集终态详情显示“重新采集”,确认成功后调用 `AgentForegroundService.start` 唤醒现有轮询,任务执行仍由 `next/claim/start` 完成。
|
||||
|
||||
## Agent 受控采购重试(#95)
|
||||
|
||||
- 服务端 `server/app/goauto/purchase/retry.go` 的 `AgentRetry` 使用 Device Token 校验任务归属,并复用 Admin `BatchRetry` 的当前档案、不可逆边界、设备能力/忙碌和幂等创建逻辑;旧失败任务不修改,新任务固定原设备。
|
||||
- `GET /api/agent/v1/purchase-tasks` 与详情通过 `retryable` / `retryDisabledReason` 返回服务端资格结论;`POST /api/agent/v1/purchase-tasks/{taskId}/retry` 只接受 `requestId`,不接受客户端指定设备、规格或规则。
|
||||
- Android `TaskHistoryFragment` 在采购失败列表和详情按服务端资格显示单任务“重试采购”,二次确认后调用新接口;成功后唤醒既有 `AgentForegroundService` 队列,实际执行仍只走 `next → claim → start`。Agent 不实现批量重试、取消订单、修改既有订单或支付。
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
|
||||
wiki_page: Business-Rules-and-Glossary
|
||||
wiki_url: https://git.ilapage.cn/OPC/goauto/wiki/Business-Rules-and-Glossary.-
|
||||
wiki_revision: e83a27ca331f23a9219fbf4bde9020104192762a
|
||||
synchronized_at: 2026-08-26T02:11:24Z
|
||||
wiki_revision: 143cb9d565a297cf19e31b89e6d4a1fc809913dd
|
||||
synchronized_at: 2026-08-26T06:26:37Z
|
||||
<!-- gitea-wiki-mirror:end -->
|
||||
|
||||
# 业务规则与术语
|
||||
@@ -228,13 +228,20 @@ synchronized_at: 2026-08-26T02:11:24Z
|
||||
## Agent 当前设备历史
|
||||
|
||||
- Agent 只可查看当前 Device Token 对应设备最近 30 天的采集和采购任务,不能跨设备查看。
|
||||
- 采集历史可以查看结构化采集结果和错误;采购历史可以查看结构化采购数据和错误,但全部为只读。
|
||||
- 采集历史可以查看结构化采集结果和错误;采购历史可以查看结构化采购数据和错误。采购记录不提供取消订单、修改订单或支付入口;只有服务端明确标记可重试的当前设备失败任务,才提供受控“重试采购”。
|
||||
- 历史接口遵循数据最小化:不下发 Device Token、规则快照、PDD URL、收货地址、原始控件树或截图。
|
||||
- 实际采购单价只在 Agent 确实观察到时保存;旧任务或未观察到价格时显示“未记录”,不推算、不回填。
|
||||
|
||||
## Agent 受控重新采集
|
||||
|
||||
- 当前设备可以从自身采集任务详情重新采集已完成、部分完成或失败任务;采购任务始终只读,不能在 Agent 重新采购。
|
||||
- 当前设备可以从自身采集任务详情重新采集已完成、部分完成或失败任务。
|
||||
|
||||
## Agent 受控重试采购
|
||||
|
||||
- 当前设备只可重试自身最近 30 天内、服务端标记 `retryable=true` 的正式采购失败任务;列表和详情都只能发起单任务重试,不支持多选或批量。
|
||||
- 重试保留旧失败任务、错误、attempt 和审计事实,使用当前 SYB/PDD 档案、规格映射、价格保护和最新内置采购规则创建新的 `pending` 任务、新任务编号和新地址后缀;新任务固定分派给当前 Device Token 对应设备,不自动换机。
|
||||
- 只有未进入不可逆边界、没有 PDD 订单号和下单时间、不是结果未知、同一 SYB 商品没有更新任务,且当前设备在线、空闲和能力满足时才允许;服务端是最终资格判定方,Agent 不得自行猜测。
|
||||
- 请求按 `requestId` 幂等。确认界面必须说明可能创建新的 PDD 待付款订单且系统不会支付;取消订单、修改既有订单和支付仍禁止。真机验证前必须再次获得人工授权。
|
||||
- 重新采集属于破坏性状态操作,必须先显示确认框并明确提示会清除当前结构化结果和错误;用户取消时不得请求服务端。
|
||||
- 服务端是最终事实来源:校验 Device Token、设备归属、在线/空闲、任务终态和同商品活动任务冲突,Android 不得本地绕过。
|
||||
- 重置成功后复用原任务,保留 URL、goods_id、设备与规则快照,清除旧结果后恢复 `pending`;执行仍走正常租约和串行调度。
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
|
||||
wiki_page: Local-Development-and-Verification
|
||||
wiki_url: https://git.ilapage.cn/OPC/goauto/wiki/Local-Development-and-Verification.-
|
||||
wiki_revision: dc484e1aa48172d502939e8ebe0ad0e6bd83c7ea
|
||||
synchronized_at: 2026-08-25T09:44:34Z
|
||||
wiki_revision: 07ed2f2d05ad058406b7402304fd44b001bad198
|
||||
synchronized_at: 2026-08-26T06:26:58Z
|
||||
<!-- gitea-wiki-mirror:end -->
|
||||
|
||||
# 本地开发与验证
|
||||
@@ -200,6 +200,12 @@ adb shell am start -n cn.ilapage.goauto.agent/.MainActivity
|
||||
- 采集/采购 Tab 在 #90 前只显示明确占位,不应出现采购写操作、PDD 凭据或支付入口。
|
||||
- Release 仍只接受 HTTPS;Debug 可使用 HTTP 进行局域网联调。安装前必须确认设备空闲,避免重启 Agent 中断任务。
|
||||
|
||||
### Android Agent 0.6.0 采购失败重试检查
|
||||
|
||||
- 无真机授权时只运行 `cd android && .\\gradlew.bat testDebugUnitTest assembleDebug`,以及服务端采购包测试;不要调用采购重试接口,因为成功后新任务会进入正式采购队列。
|
||||
- 获得独立授权后,使用一条确认未进入不可逆边界、无 PDD 订单号的当前设备失败任务检查列表和详情入口、二次确认、旧任务保留、新任务编号/地址后缀、固定原设备与幂等反馈。
|
||||
- 取消确认不得发请求;成功后只能由既有队列执行,验证停止在创建待付款订单并读取订单号,永久禁止支付。
|
||||
|
||||
### Android Agent 0.3.1 空闲返回与亮屏检查
|
||||
|
||||
#89 起 Debug APK 版本为 0.3.1(versionCode 4)。先确认设备空闲,再覆盖安装;安装后系统可能关闭无障碍服务,需要人工重新开启。
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
|
||||
wiki_page: Android-Agent-API-Contract
|
||||
wiki_url: https://git.ilapage.cn/OPC/goauto/wiki/Android-Agent-API-Contract.-
|
||||
wiki_revision: 7f48742d36b23e7d2c01d83f714812b810bfc34f
|
||||
synchronized_at: 2026-08-26T02:12:04Z
|
||||
wiki_revision: 4d953447be50aca5abbef5f208d024a516c8b60b
|
||||
synchronized_at: 2026-08-26T06:30:08Z
|
||||
<!-- gitea-wiki-mirror:end -->
|
||||
|
||||
# MVP 共享 API 契约
|
||||
@@ -546,7 +546,7 @@ GET /api/agent/v1/purchase-tasks/{taskId}
|
||||
|
||||
- `pageSize` 最大为 50;`status` 与 `taskNo` 可以组合过滤。
|
||||
- 采集任务编号允许 `35` 或 `#35`,采购任务编号允许 `12` 或不区分大小写的 `CG-12`;服务端按精确编号匹配。
|
||||
- 列表和详情不返回 Device Token、URL、收货地址、规则快照或原始控件树;采购详情只读,不提供重试、取消、创建订单或支付入口。
|
||||
- 列表和详情不返回 Device Token、URL、收货地址、规则快照或原始控件树。采购项额外返回服务端计算的 `retryable` 和可选 `retryDisabledReason`;除受控失败重试外,不提供取消、修改既有订单或支付入口。
|
||||
- 采集详情返回标题、店铺、销量、评价数、规格维度、颜色价格、SKU、缺失项和结构化错误。
|
||||
- 采购详情返回蝦皮订单号、PDD 商品、已匹配颜色/尺码、数量、实际单价、PDD 订单号、下单时间和结构化错误。
|
||||
- Agent 提交采购结果时可携带 `actualUnitPriceCent`(人民币分,非负)。服务端只保存 Agent 实际观察到的值;历史任务或未观察到价格的结果保持 `null`,客户端显示“未记录”。
|
||||
@@ -565,5 +565,22 @@ Content-Type: application/json
|
||||
- `requestId` 必须为 UUID。同一请求重复提交不会再次清空结果,响应中的 `replayed` 为 `true`。
|
||||
- 服务端在事务内锁定设备和任务,重新校验设备在线、同商品无其他 `pending/running` 采集任务,并确认该设备没有正在执行或持有有效租约的其他采集/采购任务。
|
||||
- 成功后保留 URL、goods_id、设备和规则快照,事务删除旧结构化结果及错误,把原任务恢复为 `pending`;Agent 随后只能通过既有 `next → claim → start` 调度执行。
|
||||
|
||||
- 响应只返回 `taskId`、`status` 和可选的 `replayed`,不返回规则快照、URL、Token、控件树或截图。
|
||||
- 设备离线、任务非终态、设备忙或同商品存在活动任务时返回明确冲突,不支持离线排队。
|
||||
|
||||
## Agent 受控采购重试(#95)
|
||||
|
||||
```text
|
||||
POST /api/agent/v1/purchase-tasks/{taskId}/retry
|
||||
Authorization: Bearer <device-token>
|
||||
Content-Type: application/json
|
||||
|
||||
{"requestId":"<uuid>"}
|
||||
```
|
||||
|
||||
- 原任务必须属于当前 Device Token,且在最近 30 天历史范围内;跨设备或超期按任务不存在处理。
|
||||
- 服务端复用正式采购失败重试校验:状态为 `failed`、未进入不可逆边界、无 PDD 订单号和下单时间、非结果未知、同一 SYB 商品无更新任务,当前设备在线/空闲/能力满足,并重新校验档案、规格映射、价格保护和采购规则。
|
||||
- 成功响应 `data` 返回 `sourceTaskId`、`sourceTaskNo`、新 `taskId`、新 `taskNo` 和 `replayed`。旧任务不清空;新任务为固定当前设备的 `pending`,并使用新地址后缀。
|
||||
- `requestId` 必须是 UUID;相同请求重放返回同一新任务,不重复创建。请求体不得指定设备、规格、规则、地址、订单或支付参数。
|
||||
- Android 必须使用服务端 `retryable` 决定是否展示入口,提交前明确提示可能产生新的待付款订单且系统不会支付。真机调用属于可能创建订单的高风险验证,必须先取得人工授权。
|
||||
|
||||
Reference in New Issue
Block a user