让获取任务按钮支持持续自动运行和安全停止 #45

Closed
opened 2026-08-09 10:43:16 +08:00 by ila · 3 comments
Owner

基本信息

  • 类型:需求
  • 父级大工单:#1
  • 所属 MVP / 版本:#2 / MVP
  • 阶段:任务执行闭环

要解决什么

当前“获取任务”按钮每点击一次只创建一个 Worker,并只调用一次 execute_one()。完成后线程退出、按钮恢复,不会自动处理下一条任务,与页面已有的“开始自动获取 / 停止自动获取”状态设计不一致。

操作人员需要启动一次后持续处理任务;同一设备仍必须保持串行,不能同时执行多个 Worker。

做什么 / 不做什么

  • 做:
    • 复用现有按钮,支持“开始自动获取”和“停止自动获取”切换。
    • 每轮仍只处理一个工作单元,Worker 完成后由 Qt 主线程调度下一轮。
    • 有任务完成时短暂等待后继续;暂无任务时等待较长间隔后重新领取。
    • Admin 可恢复错误使用有限上限的递增退避后继续。
    • 需要人工处理、不可恢复错误、设备或配置问题时停止自动模式并提示。
    • 点击停止时设置停止标志并请求当前 Worker 安全取消,不强杀线程。
    • 关闭页面或应用时取消定时调度,并安全结束当前 Worker。
    • 增加状态切换、串行调度、停止、空队列和错误分类测试。
  • 不做:
    • 不增加第二个“领取一条”按钮。
    • 不并行运行任务,不让一个设备被多个线程控制。
    • 不修改 Admin 接口、SQLite、pdd_data 和任务状态定义。
    • 不新增采购实现,不启用真实下单。
    • 不使用 Worker 内无限循环或 time.sleep() 等待下一轮。

怎么做

主要修改 client/src/pdd_ui_event.py:

  1. 在 PDDTaskPageEvent 保存自动运行状态、停止请求、连续可恢复错误次数和待执行的单次 QTimer。
  2. 点击现有按钮:
    • 停止状态:切换为启动/运行并开始第一轮;
    • 运行状态:切换为停止中,取消下一轮定时器,并调用当前 Worker 的 cancel()。
  3. 每轮只创建一个 ClaimTaskWorker + QThread。线程完成后,根据本轮结果在主线程使用单次 QTimer 安排下一轮,确保上一线程完全结束后才启动。
  4. 调度策略:
    • 成功、已提交或普通可继续结果:短间隔后继续;
    • 暂无任务:默认 5 秒后继续;
    • Admin 可恢复错误:5、10、20、30 秒递增,最高 30 秒;
    • 需要人工处理、不可恢复错误、设备/配置错误:停止自动模式。
  5. Worker 信号增加���够的结果分类信息,不在后台线程访问 QWidget。
  6. 页面统一通过现有 set_auto_fetch_state() 和 set_engine_status() 更新按钮及状态文字。
  7. 测试使用短间隔或直接触发定时器,不真实连接 Admin 和 Android 设备。

预计修改:

  • client/src/pdd_ui_event.py
  • client/test/test_pdd_ui_event.py
  • 必要时更新 docs/client/01-requirements.md、docs/client/02-architecture.md 和 docs/client/05-ui-specification.md 中稳定的自动运行行为。

不改数据库和接口。

验收标准

  • 点击一次“开始自动获取”后,能串行处理多条任务,不需要重复点击。
  • 任意时刻最多只有一个任务 Worker 和一个设备会话。
  • 暂无任务时显示等待状态,并在默认 5 秒后重新领取。
  • 可恢复 Admin 错误按 5、10、20、30 秒退避后继续,成功后清零退避。
  • 需要人工处理、不可恢复错误、配置或设备错误会停止自动运行并明确提示。
  • 点击“停止自动获取”会取消下一轮,并请求当前 Worker 在安全点停止。
  • 页面关闭后不会启动新 Worker,迟到信号不会访问已销毁界面。
  • 按钮正确显示启动、运行、停止中和已停止状态。
  • 不修改 Admin 接口、数据结构和真实下单开关。
  • 相关专项与 Client 全量测试通过。

怎么验证

从 client/ 目录执行:

C:/Python310/python.exe -m py_compile src/pdd_ui_event.py test/test_pdd_ui_event.py
C:/Python310/python.exe -m unittest discover -s test -p test_pdd_ui_event.py
C:/Python310/python.exe -m unittest discover -s test -p "test_*.py"

手动验证:

  1. 使用 Mock Admin 准备至少两条采集任务。
  2. 点击一次“开始自动获取”,确认任务严格串行完成。
  3. 队列为空时确认页面显示 5 秒后重试。
  4. 等待期间点击停止,确认不会再次请求。
  5. 任务执行中点击停止,确认在安全点结束且没有第二个 Worker。
  6. 不执行采购或真实下单。

风险和回退

风险主要是重复调度导致同一设备并发、停止时迟到信号访问销毁页面,以及错误分类不当造成无限重试。实现中只在线程 finished 后单次调度下一轮,启动前同时检查运行状态、关闭状态和忙状态;关闭时停止定时器并断开/取消 Worker。若真机发现异常,可回退本工单提交,恢复一次点击只处理一条的行为。

## 基本信息 - 类型:需求 - 父级大工单:#1 - 所属 MVP / 版本:#2 / MVP - 阶段:任务执行闭环 ## 要解决什么 当前“获取任务”按钮每点击一次只创建一个 Worker,并只调用一次 `execute_one()`。完成后线程退出、按钮恢复,不会自动处理下一条任务,与页面已有的“开始自动获取 / 停止自动获取”状态设计不一致。 操作人员需要启动一次后持续处理任务;同一设备仍必须保持串行,不能同时执行多个 Worker。 ## 做什么 / 不做什么 - 做: - 复用现有按钮,支持“开始自动获取”和“停止自动获取”切换。 - 每轮仍只处理一个工作单元,Worker 完成后由 Qt 主线程调度下一轮。 - 有任务完成时短暂等待后继续;暂无任务时等待较长间隔后重新领取。 - Admin 可恢复错误使用有限上限的递增退避后继续。 - 需要人工处理、不可恢复错误、设备或配置问题时停止自动模式并提示。 - 点击停止时设置停止标志并请求当前 Worker 安全取消,不强杀线程。 - 关闭页面或应用时取消定时调度,并安全结束当前 Worker。 - 增加状态切换、串行调度、停止、空队列和错误分类测试。 - 不做: - 不增加第二个“领取一条”按钮。 - 不并行运行任务,不让一个设备被多个线程控制。 - 不修改 Admin 接口、SQLite、`pdd_data` 和任务状态定义。 - 不新增采购实现,不启用真实下单。 - 不使用 Worker 内无限循环或 `time.sleep()` 等待下一轮。 ## 怎么做 主要修改 `client/src/pdd_ui_event.py`: 1. 在 `PDDTaskPageEvent` 保存自动运行状态、停止请求、连续可恢复错误次数和待执行的单次 `QTimer`。 2. 点击现有按钮: - 停止状态:切换为启动/运行并开始第一轮; - 运行状态:切换为停止中,取消下一轮定时器,并调用当前 Worker 的 `cancel()`。 3. 每轮只创建一个 `ClaimTaskWorker + QThread`。线程完成后,根据本轮结果在主线程使用单次 `QTimer` 安排下一轮,确保上一线程完全结束后才启动。 4. 调度策略: - 成功、已提交或普通可继续结果:短间隔后继续; - 暂无任务:默认 5 秒后继续; - Admin 可恢复错误:5、10、20、30 秒递增,最高 30 秒; - 需要人工处理、不可恢复错误、设备/配置错误:停止自动模式。 5. Worker 信号增加���够的结果分类信息,不在后台线程访问 QWidget。 6. 页面统一通过现有 `set_auto_fetch_state()` 和 `set_engine_status()` 更新按钮及状态文字。 7. 测试使用短间隔或直接触发定时器,不真实连接 Admin 和 Android 设备。 预计修改: - `client/src/pdd_ui_event.py` - `client/test/test_pdd_ui_event.py` - 必要时更新 `docs/client/01-requirements.md`、`docs/client/02-architecture.md` 和 `docs/client/05-ui-specification.md` 中稳定的自动运行行为。 不改数据库和接口。 ## 验收标准 - [x] 点击一次“开始自动获取”后,能串行处理多条任务,不需要重复点击。 - [x] 任意时刻最多只有一个任务 Worker 和一个设备会话。 - [x] 暂无任务时显示等待状态,并在默认 5 秒后重新领取。 - [x] 可恢复 Admin 错误按 5、10、20、30 秒退避后继续,成功后清零退避。 - [x] 需要人工处理、不可恢复错误、配置或设备错误会停止自动运行并明确提示。 - [x] 点击“停止自动获取”会取消下一轮,并请求当前 Worker 在安全点停止。 - [x] 页面关闭后不会启动新 Worker,迟到信号不会访问已销毁界面。 - [x] 按钮正确显示启动、运行、停止中和已停止状态。 - [x] 不修改 Admin 接口、数据结构和真实下单开关。 - [x] 相关专项与 Client 全量测试通过。 ## 怎么验证 从 `client/` 目录执行: ```powershell C:/Python310/python.exe -m py_compile src/pdd_ui_event.py test/test_pdd_ui_event.py C:/Python310/python.exe -m unittest discover -s test -p test_pdd_ui_event.py C:/Python310/python.exe -m unittest discover -s test -p "test_*.py" ``` 手动验证: 1. 使用 Mock Admin 准备至少两条采集任务。 2. 点击一次“开始自动获取”,确认任务严格串行完成。 3. 队列为空时确认页面显示 5 秒后重试。 4. 等待期间点击停止,确认不会再次请求。 5. 任务执行中点击停止,确认在安全点结束且没有第二个 Worker。 6. 不执行采购或真实下单。 ## 风险和回退 风险主要是重复调度导致同一设备并发、停止时迟到信号访问销毁页面,以及错误分类不当造成无限重试。实现中只在线程 `finished` 后单次调度下一轮,启动前同时检查运行状态、关闭状态和忙状态;关闭时停止定时器并断开/取消 Worker。若真机发现异常,可回退本工单提交,恢复一次点击只处理一条的行为。
Author
Owner

实施记录(2026-08-09)

已完成实现,当前状态:待用户真机验收。

  • 实现提交:5fd7198(持续串行调度、安全停止、空队列轮询、Admin 退避)
  • 归档提交:7fb137f
  • 本地归档:docs/task/45-持续自动获取任务与安全停止.md
  • 定向测试:19 项通过
  • Client 全量测试:176 项通过
  • 语法检查和 git diff --check:通过

尚未验证:真实 Admin 连续下发多条任务;真实 Android 采集中点击停止的安全取消时机。未执行采购或真实下单。工单保持开启,等待用户验收。

## 实施记录(2026-08-09) 已完成实现,当前状态:**待用户真机验收**。 - 实现提交:`5fd7198`(持续串行调度、安全停止、空队列轮询、Admin 退避) - 归档提交:`7fb137f` - 本地归档:`docs/task/45-持续自动获取任务与安全停止.md` - 定向测试:19 项通过 - Client 全量测试:176 项通过 - 语法检查和 `git diff --check`:通过 尚未验证:真实 Admin 连续下发多条任务;真实 Android 采集中点击停止的安全取消时机。未执行采购或真实下单。工单保持开启,等待用户验收。
Author
Owner

后续性能工作已拆为 #109(先量化耗时并做低风险去重)和 #110(数据达标后才用持久设备工作线程复用 uiautomator2 会话)。二者属于 MVP 后续性能优化,不改变本工单的持续串行调度验收范围。

后续性能工作已拆为 #109(先量化耗时并做低风险去重)和 #110(数据达标后才用持久设备工作线程复用 uiautomator2 会话)。二者属于 MVP 后续性能优化,不改变本工单的持续串行调度验收范围。
Author
Owner

用户已于 2026-08-11 明确验收通过。

  • 本地归档状态已更新为“已完成,用户验收通过”
  • 验收记录提交:eca9289
  • 本工单按项目流程关闭
用户已于 2026-08-11 明确验收通过。 - 本地归档状态已更新为“已完成,用户验收通过” - 验收记录提交:`eca9289` - 本工单按项目流程关闭
ila closed this issue 2026-08-11 10:58:08 +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#45