From 5995f16c39b158047ecec347a389a0506a6919f6 Mon Sep 17 00:00:00 2001 From: yml2213 Date: Fri, 2 Oct 2026 22:54:36 +0800 Subject: [PATCH] =?UTF-8?q?docs(plan):=20=E8=A1=A5=E7=BB=AD=E4=BD=9C?= =?UTF-8?q?=E5=85=A5=E5=8F=A3=E4=B8=8E=20P0=20=E8=B8=A9=E5=9D=91=E7=95=99?= =?UTF-8?q?=E6=A1=A3=EF=BC=88=E5=A4=96=E9=83=A8=E8=A1=A8=E7=BB=93=E6=9E=84?= =?UTF-8?q?=E6=A0=B8=E5=AE=9E=E3=80=81uv.lock=E3=80=81=E5=AE=B9=E5=99=A8?= =?UTF-8?q?=E9=AA=8C=E8=AF=81=E5=A7=BF=E5=8A=BF=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/自动化与资料收集规划.md | 47 ++++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/docs/自动化与资料收集规划.md b/docs/自动化与资料收集规划.md index 48d17a9..684443b 100644 --- a/docs/自动化与资料收集规划.md +++ b/docs/自动化与资料收集规划.md @@ -1,7 +1,16 @@ # 自动化与资料收集规划 更新时间:2026-10-02 -状态:**P1a(CK 自动巡检)已落地**,P0/P2/P3/P4/P1b 待排期。产品决策已确认(见 §4),施工单见附录 C。 +状态:**P1a(CK 巡检)+ P1b(CK 自动重登)已上线**;**P0 适配层已完成并真机验证(无接口/页面、开关仍关、生产未跑迁移)**;下一步 P2。产品决策已确认(见 §4),施工单见附录 C。 + +> ### 🔜 续作入口(下一个会话先看这里) +> +> 1. **当前该做 P2(资料收集链接 + OSS 上传)**,施工顺序见 **§C.5**,下一个迁移编号 **`20261002_0040`**; +> 2. P0 的适配层已就绪(`services/external_order_source.py`,`lookup_order()` 直接可用), +> P2 做「用户填订单号后回显商品」时**直接调它**,不要重写跨库 SQL; +> 3. P0 遗留三件事(要真正启用时才做):生产跑迁移 0039 建表、`.env` 开 `ORDER_SITE_LOOKUP_ENABLED`、补查询接口/页面(见 §C.4-bis); +> 4. 上手前必读 **§C.2 通用约定**(方言、时区、环境变量三处同步、迁移编号取号规则、 +> 「动手前先核实外部库真实表结构」)与 **§C.3 已核实的环境事实**。 --- @@ -1095,6 +1104,10 @@ pending_material(待用户补资料) ← 模板有必填字段时的 **建议顺序:P1a → P1b → P0 → P2 → P3 → P4。** - **P1a 已上线**(2026-10-02),只做「帮你把失效 CK 找出来」,零风险; +- **P1b 已上线**(2026-10-02):20 个失效账号实测 20/20 重登成功、零极验;当前 30 条/轮、约 97% 成功率,待重登积压约 3.6k 正在消化; +- **P0 已过半**(2026-10-02):适配层 + 迁移 0039 已完成并真机验证(三桶判定全对、3.3ms、540 个重复订单号正确拦下), + **但只有底层适配层:无接口、无页面,且生产开关仍是 `false`、迁移未在生产跑**。 + 接口与页面按 §6.4 的调用点(用户填订单号时)随 P2 一起上; - **P1b 提到 P1a 之后**:原计划等一到两周观察期,但线上数据已把三个前提验证完了 —— 检测结果与人工/直连逐条一致、误判路径已封(三类判定 + 自动暂停)、失效性质查清(会话过期而非凭证问题)。不联动的话,巡检每天翻出失效清单却没人兑现修复,1,356 个账号只会越积越多; - **P0 随时可做**:只动本系统,order_site 侧代码改动量为 0; - **P1b 开关仍默认关闭**,按 §7.4.7 三段上线:小规模实测 → 限量开 → 全量; @@ -1298,8 +1311,9 @@ OSS_PREFIX=collect | 阶段 | revision | 说明 | | --- | --- | --- | | P1a(已落地) | `20261002_0037` | `automation_jobs` / `automation_runs` / `login_tasks` +3 / `accounts.auto_managed` | -| P0 | 落地时取下一个 | `external_order_cache` | -| P2 / P3 / P4 | 各自落地时依次取号 | 见附录 A 的表清单 | +| P1b(已落地) | `20261002_0038` | `login_tasks` + `relogin_failure_kind` | +| P0(已落地) | `20261002_0039` | `external_order_cache` | +| P2 / P3 / P4 | 各自落地时依次取号(**下一个是 `20261002_0040`**) | 见附录 A 的表清单 | > **为什么不能预留编号**:Alembic 的 `down_revision` 必须形成单链。若先给 P1 占 0038、 > 把 0037 留给 P0,等 P0 真落地时它的 `down_revision` 只能指向 0038(否则与 0038 平级, @@ -1340,7 +1354,24 @@ OSS_PREFIX=collect `TypeError: can't compare offset-naive and offset-aware`(P1a 踩过一次)。比较前一律用 `_as_utc()`(`services/yyb_service.py` 与 `services/automation/scheduler.py` 各有一份)补时区。 SQL 里用绑定参数比较不受影响,只有 Python 侧比较需要注意 —— P0 判缓存过期时会再遇到; -- **每个阶段独立可发布**,新作业/新功能一律**开关默认关闭**。 +- **每个阶段独立可发布**,新作业/新功能一律**开关默认关闭**; +- **⚠️ 动手前先核实外部库的真实表结构,别信文档和早期分析**(P0 踩过一次,差点白干): + 规划 §6.2 写的 `orders.order_no`(PK) 在真实库里**根本不存在**,实际是 + `platform_order_id`(且**非唯一**,541 组重复)。同一订单号下还有「发货方内部行 + + 真实店铺行」的成对结构,**按单行判 route 会放行 540 个已发货订单**。 + 做法:先用只读账号 `SELECT column_name FROM information_schema.columns` 核对一遍, + 再把结论写进文档(§6.5.1 就是这么留档的)。**跨系统的字段假设一律当作待验证**; +- **加依赖后必须重锁 `uv.lock`**:Dockerfile 用的是 `uv sync --frozen`(见 §C.3), + 只改 `pyproject.toml` 不重锁,生产构建会直接失败。P0 加 `psycopg[binary]` 时走过一遍: + 本地 `uv lock` + `uv sync`,提交时带上 `uv.lock`; +- **验证容器里的代码要 `docker cp`,挂载只有 logs/data**:compose 只 bind 了 + `/root/live-hub-py/logs` 与 `/data`,**代码在镜像里**。改完宿主机文件不会自动生效; + 临时验证用 `docker cp` 进 `/app`,之后**记得删掉**,别污染生产工作区(会让 `git pull` 起冲突); +- **容器里装包要用 `uv pip` 且指定 `VIRTUAL_ENV`**:容器的 `/app/.venv` 里**没有 pip**, + 系统 `pip` 装的东西 venv 里的 python 看不见(P0 验证时白装过一次)。正确姿势: + `docker exec -w /app <容器> env VIRTUAL_ENV=/app/.venv uv pip install <包>`; + 另:`docker exec -e` 覆盖不了 compose 已注入的同名变量,验证时改用容器自带的 env + 或在脚本里 `os.environ[...] = ...`。 ### C.3 已核实的环境事实 @@ -1349,10 +1380,10 @@ OSS_PREFIX=collect | uvicorn worker 数 | **`--workers 1`**(单容器单进程) | 进程内调度线程安全,**不需要分布式锁**;调度器在 lifespan 里启停 | | 生产路径 | `/root/live-hub-py`,容器 `live-hub-py-douyu-login-1` | 部署 = `git pull` + `./deploy.sh` | | 鉴权 | **无全局中间件**,逐路由 `Depends(get_current_user)` | 公开路由只要不挂依赖;新路由要在 `main.py` 注册 | -| PG 驱动 | 容器内**没有**,需新增 `psycopg[binary]`(已定) | P0 第一步就是加依赖 + 重建镜像 | -| 只读 PG | `livehub_ro` @ `order_site-postgres-1:5432`,`.env` 已配 | 适配层直接用 `ORDER_SITE_DATABASE_URL` | -| OSS | 桶 `live-hub-assets`(私有+版本控制)、RAM `live-hub-oss`、`.env` 已配 | `oss2`;**不要用 HeadBucket** | -| 迁移 head / 测试基线 | `20261001_0036` / 235 条 | 见 C.1 | +| PG 驱动 | `psycopg[binary]` 已加入 `pyproject.toml` + `uv.lock`(2026-10-02);**生产镜像尚未重建** | 部署 P0 时会随镜像重建装上;临时验证已在容器里手工装过 | +| 只读 PG | `livehub_ro` @ `order_site-postgres-1:5432`,`.env` 已配(容器内 3 个 `ORDER_SITE_*` 均可见) | 适配层直接用 `ORDER_SITE_DATABASE_URL`;**`LOOKUP_ENABLED` 仍是 `false`** | +| OSS | 桶 `live-hub-assets`(私有+版本控制)、RAM `live-hub-oss`、`.env` 已配 | P2 用 `oss2`;**不要用 HeadBucket** | +| 迁移 head / 测试基线 | `20261002_0039` / 328 条(2026-10-02) | 见 C.1;生产库**尚未**跑 0039 | ### C.4 P1a 施工单(✅ 已按此完成,8 步)