docs: 归档任务 #110
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
# 110 使用持久设备工作线程跨任务复用 uiautomator2 会话
|
||||
|
||||
- 类型:重构
|
||||
- 父级大工单:#1
|
||||
- 所属 MVP / 版本:MVP 后续 / 任务执行性能优化
|
||||
- 状态:已完成(待验收)
|
||||
- 日期:2026-08-10
|
||||
- Gitea 工单:<http://ilaer.eicp.net:8418/chengma/cmautobuy/issues/110>
|
||||
|
||||
## 背景与目标
|
||||
|
||||
Client 原来每轮自动获取都会新建 Worker 和 QThread,正式采集、采购和核单适配器
|
||||
也会重新调用 `uiautomator2.connect()`。目标是让同一 Android 设备由固定工作线程
|
||||
串行控制,并在 90 秒内只复用 Device 连接;页面、控件树、商品、价格、规格和采购
|
||||
安全状态仍必须每个任务重新读取。
|
||||
|
||||
#109 测得连接本身只占端到端约 1.4%,原结论是 No-Go。用户随后明确要求继续实施
|
||||
#110,因此工单已记录该决策变更;性能门槛保留为结果评价和回退依据,不再作为
|
||||
开始实施的阻塞条件。
|
||||
|
||||
## 最终方案
|
||||
|
||||
- `PDDTaskPageEvent` 在首次设备任务时懒创建一个固定 QThread 和长生命周期
|
||||
`ClaimTaskWorker`。自动获取、手动重新采集、采购和不可逆阶段后的只读核单都通过
|
||||
Qt 队列信号串行进入该 Worker;不在 Worker 内运行无限循环。
|
||||
- `PersistentPddDeviceService` 只缓存同一 serial 的 Device 连接。每次 `connect()`
|
||||
都重新调用 `app_current()` 做轻量健康检查,并返回全新的任务会话。旧连接失效时
|
||||
丢弃后最多重连一次,不缓存 XML、Selector、坐标或业务字段。
|
||||
- 官方采集、dry-run 采购、live 采购和核单工厂从当前执行上下文取得同一个持久设备
|
||||
服务;自定义测试工厂和原有每任务服务边界仍可使用,方便整体回退。
|
||||
- 停止自动获取、保存或删除 Android 设备、serial 变化、90 秒空闲到期和窗口关闭时,
|
||||
都把释放命令排入设备线程。窗口关闭先协作停止当前命令,再释放并执行
|
||||
`quit()/wait()`,不使用 `terminate()`。
|
||||
- 设置页保存/删除设备后发出稳定信号,由主窗口装配到任务页的释放入口。
|
||||
- 批量重新上报继续使用原来的独立网络 Worker,不访问 Android 设备。
|
||||
- 未修改数据库、Admin 接口、任务状态或 `pdd_data`;真实下单默认开关和不可逆阶段
|
||||
只核单的硬边界保持不变。
|
||||
|
||||
与建单方案的差异:没有新增单独的执行器文件,而是在现有
|
||||
`ClaimTaskWorker/PDDTaskPageEvent` 边界内改成长生命周期实现,减少初级程序员需要追踪
|
||||
的类和文件。#109 已证明连接复用无法达到原性能目标,因此本次只确认连接复用和
|
||||
线程安全成立,不把端到端性能项写成通过。
|
||||
|
||||
## 改了哪些
|
||||
|
||||
- `client/src/pdd_device_service.py`:持久连接、TTL、每任务健康检查、单次重连和线程归属。
|
||||
- `client/src/pdd_ui_event.py`:固定 QThread、串行命令路由、停止/释放和窗口关闭流程。
|
||||
- `client/src/collect_task_service.py`:正式采集使用当前设备线程绑定的连接服务。
|
||||
- `client/src/pdd_u2_purchase_adapter.py`:dry-run/live 采购使用同一线程内连接服务。
|
||||
- `client/src/pdd_u2_purchase_reconcile_adapter.py`:不可逆阶段核单使用同一线程内连接服务。
|
||||
- `client/src/settings_ui_event.py`、`client/src/ui_main.py`:设备配置变化后通知任务页释放旧连接。
|
||||
- `client/test/test_pdd_device_service.py`:连接复用、TTL、serial 变化、单次重连和跨线程拒绝测试。
|
||||
- `client/test/test_pdd_ui_event.py`:连续自动获取复用同一固定 QThread 测试。
|
||||
- `client/test/test_settings_ui_event.py`:设备配置变化信号测试。
|
||||
- `docs/client/02-architecture.md`:记录持久设备线程、90 秒 TTL 和安全释放规则。
|
||||
|
||||
## 验收结果
|
||||
|
||||
| 验收标准 | 结果 |
|
||||
|---|---|
|
||||
| #109 基线和用户覆盖原 No-Go 门槛的决定已记录 | 通过 |
|
||||
| 同一 serial 在 90 秒内连续任务只调用一次 `uiautomator2.connect()` | 通过,单元测试及真机只读 5 次验证 |
|
||||
| Device 的创建、调用和释放固定在同一线程 | 通过 |
|
||||
| 自动获取、手动重试、采购和核单不会并发控制同一设备 | 通过 |
|
||||
| 每个任务重新读取应用状态,不复用页面和业务数据 | 通过 |
|
||||
| TTL、停止、设备配置变化、serial 变化和窗口关闭安全释放 | 通过 |
|
||||
| 缓存连接健康检查失败后最多重连一次 | 通过 |
|
||||
| 不可逆阶段后只允许核单,不重新下单 | 通过,既有采购恢复测试覆盖 |
|
||||
| 热启动阶段中位耗时降低 30% 或 1.5 秒 | 未通过;主要耗时仍是每任务必须执行的 `app_current()` |
|
||||
| 保留可回退边界,未改变数据库、Admin 和任务数据 | 通过 |
|
||||
| Client 全量测试、语法和离屏冒烟通过 | 通过 |
|
||||
| 真实下单仍默认关闭,未执行下单或付款 | 通过 |
|
||||
|
||||
## 测试
|
||||
|
||||
- 执行的命令:
|
||||
- `C:/Python310/python.exe -m py_compile src/collect_task_service.py src/pdd_device_service.py src/pdd_u2_purchase_adapter.py src/pdd_u2_purchase_reconcile_adapter.py src/pdd_ui_event.py src/settings_ui_event.py src/ui_main.py`
|
||||
- `C:/Python310/python.exe -m unittest discover -s test -p "test_*.py"`
|
||||
- `$env:QT_QPA_PLATFORM="offscreen"; C:/Python310/python.exe -c "from src.ui_main import MainWindow; from PyQt5.QtWidgets import QApplication; app=QApplication([]); w=MainWindow(); print('OK'); w.pddTaskPageEvent.shutdown(); w.settingsPage.eventBinder.shutdown(); app.quit()"`
|
||||
- `adb devices`
|
||||
- 真机只读脚本:同一 Wi-Fi serial 连续创建 5 个 `PersistentPddDeviceService` 任务会话,只读取 `app_current()`。
|
||||
- `git diff --check`
|
||||
- 结果:Client 全量 316 项通过;语法、差异检查和离屏主窗口冒烟通过;ADB 设备
|
||||
`192.168.0.173:5555` 在线;5 个真机会话只有 1 次底层连接,线程 ID 始终为
|
||||
22788。5 次会话健康检查耗时为 11730.6、10756.5、10589.1、10738.6、
|
||||
10826.3 ms,设备均报告当前包名 `com.android.settings`。
|
||||
- **没验证到的部分**:没有领取真实 Admin 任务连续执行完整采集或采购;没有执行
|
||||
真实下单、创建订单或付款;没有在真机等待 90 秒观察 QTimer 到期,而是由单元测试
|
||||
覆盖 TTL;没有在真机主动制造断连、验证码、风控、登录失效或不可逆阶段崩溃。
|
||||
|
||||
## 遗留问题
|
||||
|
||||
连接复用已经成立,但没有达到原性能验收值。当前主要瓶颈是该 OPPO/ColorOS 上
|
||||
`app_current()` 每次约 10.6 秒且可能错误报告系统设置页。不能为了提速删除每任务
|
||||
应用和页面安全校验;若继续优化,应另建应用状态检测诊断工单。
|
||||
|
||||
## 相关提交
|
||||
|
||||
- `70cedc3` refactor: 复用持久设备工作线程 (#110)
|
||||
Reference in New Issue
Block a user