Files

9.5 KiB
Raw Permalink Blame History

00 术语表

  • 文档状态:基线草案
  • 用途:其他文档里出现的专业词,在这里能查到一句话解释

看文档时遇到不认识的词,先查这里。不要靠猜——这些词大多和数据安全、不重复下单直接相关,猜错会写出真出问题的代码。

1. 最重要的三个

这三个词撑起了整个项目的可靠性设计,先看懂它们。本节最后还解释了一件事: 为什么本项目没有别的任务系统常见的"租约"和"心跳"。

幂等(idempotent)

一句话: 同一个操作做一次和做十次,结果一样。

为什么要有: 网络会超时。你给 Admin 发了"采购成功",但没收到回复——你不知道 Admin 到底收到没有。如果直接重发,Admin 可能记两笔。幂等就是让重发变安全:每次提交都带一个幂等键(Idempotency-Key),Admin 看到相同的键就知道"这条我处理过了",直接返回上次的结果,不会重复记账。

在本项目里: 幂等键存在 outbox_events.idempotency_key,格式见 03 数据模型 §5.2。

Outbox(待发件箱)

一句话: 一张本地表,结果先写进这张表,再由后台慢慢发给 Admin。

为什么要有: 手机上已经下单了,这一步不可撤销。如果这时候网断了,直接把结果丢掉,就等于白下单一次还没人知道。所以流程必须是:先把结果落到本地数据库(连同 Outbox 记录,在同一个事务里),再由后台反复重试发送。发不出去就一直留着,程序重启也还在。

关键区别: Outbox 重试的是**"提交这个结果",不是"重新做一遍这个任务"**。发送失败只会重发消息,绝不会再去手机上点一次下单。

在本项目里: 表 outbox_events,见 03 数据模型 §5。

不可逆阶段标记

一句话: 数据库里的一个时间戳,意思是"这个任务我已经点过下单了,撤不回来了"。

为什么要有: 程序可能在下单那一刻崩溃或断电。重启后它不知道刚才那单到底成没成—— 这时候如果傻乎乎地重跑一遍,就会买两次。所以规则是:点下单之前先把这个标记写进数据库。 重启后只要看到它有值,就只准去"我的订单"里核对,绝不准重新下单。

为什么它现在特别重要: 本项目没有租约和心跳(见下方说明), 防重复下单全靠它。改动相关代码要格外小心。

在本项目里: task_runs.irreversible_action_at,规则见 03 数据模型 §7.3。

为什么没有"租约"和"心跳"

你可能在别的任务系统里见过这两个词——Admin 发一个限时凭证证明"这个任务归你", Client 定期发心跳续期,过期就得停手。本项目故意没有这套东西。

原因:本项目不自动付款,采购止于创建订单。就算两台 Client 撞车各下一单, 产生的也只是重复的未付款订单,人工审核时不付即可。为这点代价引入租约、心跳、 过期判断和一整套中断逻辑,不划算。

Admin 想知道某台 Client 是不是卡死了,用"领取后超时重派"就行,Client 不参与。 完整理由见 04 接口契约 §1.1。

2. 数据和接口

词 一句话解释 在本项目里指
分配 Admin 决定某个任务归哪台 Client 做。分配 ≠ 领取:分配是 Admin 单方面指定,领取是 Client 主动调 claim 去拿 见 04 §5.1
退避 / backoff 重试失败后逐次拉长等待时间(1秒、2秒、4秒……),别把服务端打垮 Outbox 重试和领取轮询,见 04 §8
DTO 只用来在系统之间传数据的简单对象,没有业务逻辑 Admin 接口收发的那些数据结构
Repository 专门放数据库读写代码的一层。别的地方不许直接写 SQL src/infrastructure/db/ 下的类
Gateway 隔离外部系统的一层。换实现(Mock ↔ 真 HTTP)时,上层代码不用改 AdminGateway / MockAdminGateway
状态机 规定"什么状态能变成什么状态"的一张表,不在表里的变化就是 bug 任务状态转换,见 03 §7
便携模式 程序和它的数据放在同一个文件夹里,整个拷走就能用,不往系统目录写东西 data/ 在 launcher.exe 旁边,见 03 §2.1
frozen Python 判断"我现在是不是打包成 exe 在跑"的标志 getattr(sys, "frozen", False),见 03 §2.2
one-dir / one-file PyInstaller 的两种打包形态:one-dir 产出一个文件夹,one-file 挤成单个 exe。本项目用 one-dir,好排查 见 01 需求 §8.1
WAL SQLite 的一种工作模式,好处是"读"和"写"可以同时进行,不互相锁死 建库时 PRAGMA journal_mode = WAL
事务 一组数据库操作,要么全部成功,要么全部不生效 写任务结果 + 写 Outbox 必须在一个事务里
schema_version JSON 数据的版本号。以后结构变了,靠它认出旧数据 pdd_data 和 admin_payload 的第一个字段

3. 界面和线程

词 一句话解释 在本项目里指
Qt 主线程 唯一允许创建和修改界面控件的线程。在这个线程里做耗时的事,界面就会卡死转圈 见 02 架构 §5
Worker 放在后台线程里干耗时活儿(联网、点手机、读大文件)的对象 TaskWorker,模板见 02 §5.1
信号 / signal Qt 里跨线程传消息的机制。后台线程算完了,用信号通知主线程去更新界面 后台结果回主线程的唯一正规途径
模型/视图 表格分成两半:数据在"模型"里,显示在"视图"里。好处是几万行也不卡 TaskTableModel + TableView
增量加载 表格先只加载 50 行,用户滚到底了再去数据库拿下一批 canFetchMore / fetchMore,见 05 §5.3
委托 / delegate 控制表格单元格怎样绘制或编辑的对象。比给每个格子塞一个真控件省资源得多 将来需要特殊绘制的表格列
InfoBar Fluent 风格的横条提示。可以停着不消失,还能带按钮 可恢复错误的标准提示方式
模态对话框 弹出来必须先处理它、否则动不了主窗口的窗口。很打断人,只在必须做决定时用 高危确认
DPI / 显示缩放 Windows 里"文字和应用的大小"那个百分比设置 需验证 100%~200%
高对比度 Windows 的一种无障碍主题,颜色极简 需验证界面不能只靠颜色区分状态
Windows 凭据管理器 Windows 专门保存密码等秘密的系统存储,普通 SQLite 和日志不应代替它 保存在线更新密码,界面不回填明文

4. 自动化和安全

词 一句话解释 在本项目里指
uiautomator2 用 Python 控制安卓手机点击、滑动、读屏幕的库 采集和采购的执行手段
控件树 / hierarchy 手机当前这一屏所有元素的结构化描述(XML),能看到每个元素的文字和坐标 device.dump_hierarchy() 的返回值
adb 电脑和安卓手机通信的命令行工具 连设备用
SKU 一个具体的、可以单独下单的商品组合。比如"黑色 + L 码"是一个 SKU,"黑色 + M 码"是另一个 pdd_data.skus,每个 SKU 有自己的价格
规格维度 选择商品时的一类选项,比如"颜色"是一个维度,"尺码"是另一个维度 pdd_data.dimensions
不可逆阶段 一旦跨过去就撤不回来的操作阶段(真的把订单提交出去了) 进入前必须先写 irreversible_action_at,见本文 §1
演练模式 / dry_run 前面步骤全做(选规格、选数量、算价格),就是不点最后那个下单按钮 默认模式,见 01 §8
人工处理 / manual_review 程序判断不了,停下来等人看。绝不自己猜着往下做 任务状态之一,比如查到多个可能的订单时
订单核对 / reconcile 程序崩了、不确定到底下单成功没有,去"我的订单"里找证据 崩溃恢复的唯一正确做法,不是重新下单
Artifact / 诊断产物 出错时留下的截图、控件树 XML、步骤日志,用来事后查原因 存在文件里,数据库只存路径
脱敏 把敏感信息(token、Cookie、手机号、地址)从日志和截图里抹掉再保存 写 Artifact 前必做
门禁 一组必须全部满足才允许做某事的条件清单 真实下单门禁,见 06 §3
契约测试 用同一套测试去考 Mock 和真实 HTTP 两种实现,确保它们行为一致 AdminGateway 的两个实现都要过

5. 流程相关

词 一句话解释
大工单 / Epic 一个完整产品目标的总纲,下面挂很多小工单
MVP 最小可用版本。先做出来能用的一小块,而不是一次做完所有功能
单元任务工单 实际干活的最小单位,一个人一次能做完、能单独测、能单独回退
归档 任务做完后,把结论写成 docs/task/<工单号>-<名称>.md 存起来
基线文档 docs/client/ 下这几份,记录长期稳定的规则。改它们要谨慎

流程细节见仓库根目录 AGENTS.md。