Client:执行采集任务并通过 Outbox 回传 Admin #33

Closed
opened 2026-08-07 16:57:48 +08:00 by ila · 1 comment
Owner

基本信息

  • 类型:需求
  • 父级大工单:#1
  • 所属 MVP / 版本:#2 / MVP
  • 前置:#28、#30、#31
  • 关联:Admin Client API 契约与本地 SQLite / Outbox

要解决什么

Client 现在可以从 Admin 领取采集任务并保存到 SQLite,也已经有独立的 uiautomator2 商品采集服务,但两部分尚未连接:

  • 已领取任务停在“待执行”;
  • 没有把任务交给设置页保存的 Android 设备;
  • 采集结果没有可靠写入本地并提交 Admin;
  • 程序或网络中断后没有恢复和重试闭环。

本工单把“领取 → Android 采集 → 本地持久化 → Admin 提交”串成一个安全、可恢复的采集任务闭环。

做什么

  1. 增加采集任务执行协调服务,只处理 collect,不处理采购。
  2. 优先执行本地已领取但未执行的任务;没有本地待执行任务时,才向 Admin 领取一条新任务。
  3. 使用设置页已保存的 Android 设备号创建 PddDeviceService 会话。
  4. 调用 #28 的 PddCollectService.collect(),禁止复制第二套采集逻辑。
  5. 明确维护本地状态:
    • claimed → running
    • 采集成功:running → result_pending
    • Admin 接收成功:result_pending → succeeded
    • 可恢复失败:进入等待重试
    • 登录失效、验证码、数据不完整等需要人工处理的错误:进入 manual_review
  6. 采集成功时,在同一个 SQLite 事务中保存 pdd_data、执行记录和 Outbox 成功结果事件。
  7. 采集失败时,在同一个 SQLite 事务中保存结构化失败信息和 Outbox 失败事件。
  8. 为 HttpAdminGateway 实现成功结果与失败结果提交接口,使用持久化的 Idempotency-Key。
  9. 实现 Outbox 发送、重试和启动恢复:
    • 提交成功后标记事件已发送,并将任务改为“已完成”;
    • 网络失败保留待提交数据,不能重复采集;
    • 启动时把遗留的 sending 恢复成 pending;
    • 相同事件重试必须复用原幂等键。
  10. PDD 任务页显示当前阶段和错误提示;执行、HTTP、SQLite 长操作和 XML 解析全部放在后台工作线程。
  11. 窗口关闭时停止领取新任务,在安全检查点取消采集;已生成的结果必须先落库,不得因关闭窗口丢失。

交互规则

点击“获取任务”时:

  1. 先检查当前设备和 Android 设备是否已保存;
  2. 若本地已有 claimed 任务,直接执行最早的一条,不再领取;
  3. 否则向 Admin 最多领取一条并先保存 SQLite;
  4. 保存成功后立即交给已选 Android 设备采集;
  5. 采集完成后写入 Outbox并尝试提交 Admin;
  6. 界面刷新显示“待执行 / 执行中 / 结果待提交 / 已完成 / 需要人工处理”。

关闭后重新启动,已领取任务和待提交结果仍能继续处理。

不做什么

  • 不领取或执行采购任务;
  • 不下单、不付款;
  • 不绕过登录、验证码或平台风控;
  • 不在 Qt 主线程调用 uiautomator2、HTTP 或长时间 SQLite 操作;
  • 不修改 #28 的页面识别策略,除非真机联调证明存在阻断性问题;此类变化须先更新本工单;
  • 不定时无限领取任务,本工单仍保持一次操作最多处理一条任务。

数据与接口要求

  • 提交结构遵守 docs/client/04-admin-api-contract.md 及 #31 的最终契约。
  • 成功结果包含 goods_id、标题、店铺、销量、评价、规格、价格和价格采样说明。
  • 原始 Admin 任务和完整 pdd_data 保存在本地,不只保存表格摘要。
  • 金额使用人民币分整数。
  • Outbox 幂等键创建后持久化,任何重试不得重新生成。
  • 不记录 Admin Token、手机号、验证码、完整控件树等敏感信息。

预计修改范围

  • client/src/pdd_ui_event.py:触发后台执行并更新界面状态。
  • client/src/http_admin_gateway.py:实现成功/失败提交。
  • client/src/task_repository.py:补充状态迁移、执行结果和 Outbox 原子写入。
  • 新增一个简单的采集执行协调服务和必要的 Outbox 发送服务。
  • client/test/:服务、Repository、Gateway、线程与恢复测试。
  • 完成验收后归档到 docs/task/。

实际文件以实现时的最小改动为准。

验收标准

  • 本地已有待执行采集任务时,不再向 Admin 重复领取,直接使用已保存 Android 设备执行
  • 没有本地待执行任务时,能领取一条、先持久化、再执行
  • 全流程不阻塞 Qt 主线程,重复点击不会启动第二个执行器
  • 采集成功后完整 pdd_data 和 Outbox 事件原子落库
  • 成功结果能提交 Admin,Admin 商品页能看到标题、店铺、规格及价格数据
  • 失败结果能按契约提交,结构化错误码和提示可追踪
  • 网络中断时结果保留为待提交,恢复后不重新操作手机即可重试
  • 程序重启后能恢复 claimed、result_pending 和遗留 sending 状态
  • 相同 Outbox 事件重试使用相同幂等键,Admin 不产生重复结果
  • 登录失效、验证码和关键数据缺失不会被当作成功结果
  • 只支持采集任务;采购、下单和付款路径保持关闭
  • Mock 自动测试覆盖成功、无任务、设备不可用、采集失败、提交超时、幂等重试和重启恢复
  • 真机完成一次“Admin 建任务 → Client 领取 → Android 采集 → Admin 展示结果”的端到端验收
  • Client 全量测试、语法编译和差异检查通过

风险与回退

  • PDD 页面结构变化:使用 #28 的结构化错误停止,不提交不完整成功结果。
  • 网络中断:依靠 SQLite Outbox 保留结果并重试,不重复操作手机。
  • 线程退出:只在安全检查点取消,所有界面更新通过 Qt 信号返回主线程。
  • 回退:本工单独立提交,可用 git revert 回退;数据库迁移如有新增只能追加,不能改写旧迁移。
## 基本信息 - 类型:需求 - 父级大工单:#1 - 所属 MVP / 版本:#2 / MVP - 前置:#28、#30、#31 - 关联:Admin Client API 契约与本地 SQLite / Outbox ## 要解决什么 Client 现在可以从 Admin 领取采集任务并保存到 SQLite,也已经有独立的 uiautomator2 商品采集服务,但两部分尚未连接: - 已领取任务停在“待执行”; - 没有把任务交给设置页保存的 Android 设备; - 采集结果没有可靠写入本地并提交 Admin; - 程序或网络中断后没有恢复和重试闭环。 本工单把“领取 → Android 采集 → 本地持久化 → Admin 提交”串成一个安全、可恢复的采集任务闭环。 ## 做什么 1. 增加采集任务执行协调服务,只处理 `collect`,不处理采购。 2. 优先执行本地已领取但未执行的任务;没有本地待执行任务时,才向 Admin 领取一条新任务。 3. 使用设置页已保存的 Android 设备号创建 `PddDeviceService` 会话。 4. 调用 #28 的 `PddCollectService.collect()`,禁止复制第二套采集逻辑。 5. 明确维护本地状态: - `claimed → running` - 采集成功:`running → result_pending` - Admin 接收成功:`result_pending → succeeded` - 可恢复失败:进入等待重试 - 登录失效、验证码、数据不完整等需要人工处理的错误:进入 `manual_review` 6. 采集成功时,在同一个 SQLite 事务中保存 `pdd_data`、执行记录和 Outbox 成功结果事件。 7. 采集失败时,在同一个 SQLite 事务中保存结构化失败信息和 Outbox 失败事件。 8. 为 `HttpAdminGateway` 实现成功结果与失败结果提交接口,使用持久化的 `Idempotency-Key`。 9. 实现 Outbox 发送、重试和启动恢复: - 提交成功后标记事件已发送,并将任务改为“已完成”; - 网络失败保留待提交数据,不能重复采集; - 启动时把遗留的 `sending` 恢复成 `pending`; - 相同事件重试必须复用原幂等键。 10. PDD 任务页显示当前阶段和错误提示;执行、HTTP、SQLite 长操作和 XML 解析全部放在后台工作线程。 11. 窗口关闭时停止领取新任务,在安全检查点取消采集;已生成的结果必须先落库,不得因关闭窗口丢失。 ## 交互规则 点击“获取任务”时: 1. 先检查当前设备和 Android 设备是否已保存; 2. 若本地已有 `claimed` 任务,直接执行最早的一条,不再领取; 3. 否则向 Admin 最多领取一条并先保存 SQLite; 4. 保存成功后立即交给已选 Android 设备采集; 5. 采集完成后写入 Outbox并尝试提交 Admin; 6. 界面刷新显示“待执行 / 执行中 / 结果待提交 / 已完成 / 需要人工处理”。 关闭后重新启动,已领取任务和待提交结果仍能继续处理。 ## 不做什么 - 不领取或执行采购任务; - 不下单、不付款; - 不绕过登录、验证码或平台风控; - 不在 Qt 主线程调用 uiautomator2、HTTP 或长时间 SQLite 操作; - 不修改 #28 的页面识别策略,除非真机联调证明存在阻断性问题;此类变化须先更新本工单; - 不定时无限领取任务,本工单仍保持一次操作最多处理一条任务。 ## 数据与接口要求 - 提交结构遵守 `docs/client/04-admin-api-contract.md` 及 #31 的最终契约。 - 成功结果包含 `goods_id`、标题、店铺、销量、评价、规格、价格和价格采样说明。 - 原始 Admin 任务和完整 `pdd_data` 保存在本地,不只保存表格摘要。 - 金额使用人民币分整数。 - Outbox 幂等键创建后持久化,任何重试不得重新生成。 - 不记录 Admin Token、手机号、验证码、完整控件树等敏感信息。 ## 预计修改范围 - `client/src/pdd_ui_event.py`:触发后台执行并更新界面状态。 - `client/src/http_admin_gateway.py`:实现成功/失败提交。 - `client/src/task_repository.py`:补充状态迁移、执行结果和 Outbox 原子写入。 - 新增一个简单的采集执行协调服务和必要的 Outbox 发送服务。 - `client/test/`:服务、Repository、Gateway、线程与恢复测试。 - 完成验收后归档到 `docs/task/`。 实际文件以实现时的最小改动为准。 ## 验收标准 - [ ] 本地已有待执行采集任务时,不再向 Admin 重复领取,直接使用已保存 Android 设备执行 - [ ] 没有本地待执行任务时,能领取一条、先持久化、再执行 - [ ] 全流程不阻塞 Qt 主线程,重复点击不会启动第二个执行器 - [ ] 采集成功后完整 `pdd_data` 和 Outbox 事件原子落库 - [ ] 成功结果能提交 Admin,Admin 商品页能看到标题、店铺、规格及价格数据 - [ ] 失败结果能按契约提交,结构化错误码和提示可追踪 - [ ] 网络中断时结果保留为待提交,恢复后不重新操作手机即可重试 - [ ] 程序重启后能恢复 `claimed`、`result_pending` 和遗留 `sending` 状态 - [ ] 相同 Outbox 事件重试使用相同幂等键,Admin 不产生重复结果 - [ ] 登录失效、验证码和关键数据缺失不会被当作成功结果 - [ ] 只支持采集任务;采购、下单和付款路径保持关闭 - [ ] Mock 自动测试覆盖成功、无任务、设备不可用、采集失败、提交超时、幂等重试和重启恢复 - [ ] 真机完成一次“Admin 建任务 → Client 领取 → Android 采集 → Admin 展示结果”的端到端验收 - [ ] Client 全量测试、语法编译和差异检查通过 ## 风险与回退 - PDD 页面结构变化:使用 #28 的结构化错误停止,不提交不完整成功结果。 - 网络中断:依靠 SQLite Outbox 保留结果并重试,不重复操作手机。 - 线程退出:只在安全检查点取消,所有界面更新通过 Qt 信号返回主线程。 - 回退:本工单独立提交,可用 `git revert` 回退;数据库迁移如有新增只能追加,不能改写旧迁移。
Author
Owner

与先创建的 #32 范围重复。有效的执行恢复与 Outbox 要求已补充到 #32,本工单关闭,后续统一按 #32 实施和跟踪。

与先创建的 #32 范围重复。有效的执行恢复与 Outbox 要求已补充到 #32,本工单关闭,后续统一按 #32 实施和跟踪。
ila closed this issue 2026-08-07 17:00:38 +08:00
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: chengma/cmautobuy#33