fix(automation): 巡检区分「查不到」与「失效」,并在大面积失败时自动暂停

P1a 原本把「检测没通过」一律写成 invalid。但 check_douyu_cookie 的失败分两类:
斗鱼明确回「未登录/登陆异常」(CK 真失效),以及请求超时/响应异常(我们查不到)。
一视同仁的后果是:斗鱼接口抖动或被风控时,每 5 分钟 200 个、一小时就能把两千多个
好账号标成失效,客服会误判成「CK 大面积挂掉」。规划里的失败率熔断只给了 P1b,
P1a 漏了。

改动:
- 新增 classify_result():valid / invalid(命中斗鱼鉴权类说法)/ error(其余);
- error 时**不覆盖该行原来的 ck_check_status**,只更新 ck_check_result(带
  verdict 字段)与 ck_checked_at,并计入本轮 skipped;
- 一轮 error 占比 > 30% 且条数 >= 20 时自动把作业 enabled 置 false,message 与
  detail.paused 写明原因,避免继续污染;
- 真实死号占比高**不触发**暂停 —— 首轮 100% invalid 是预期情况(选行「从没检测过
  的优先」,积压的是两个月前批量导入、attempt_status 为空、从未登录的陈旧账号,
  生产实测 200 条错误信息一致为斗鱼侧「用户未登录」)。

新增 6 条测试:分类正确性、error 保留原结论、异常不再标失效、大面积失败自动暂停、
真实死号不暂停。全量 271 条通过。
This commit is contained in:
yml2213
2026-10-02 20:35:30 +08:00
parent 60f1a8d542
commit f8c5e896d4
3 changed files with 197 additions and 14 deletions
+12 -1
View File
@@ -416,6 +416,16 @@ lookup_order(order_no) -> {
如果误把作业周期设成 `interval_seconds`,就变成「200 条/6 小时 = 800 条/天」,全库 12,881 条要 16 天才能过一轮 —— 等于没巡检(P1a 实现时踩过一次,已修);
- **排除**:`auto_managed = false`;`attempt_status in (pending, running)`(正在被批次处理);最近 10 分钟内刚检测过(防重入);
- **动作**:调用现有 `check_douyu_cookie()`(两个只读接口,直连),写回 `ck_check_status / ck_check_result / ck_checked_at`;
- **⚠️ 三类判定(关键防护)**:检测失败不等于 CK 失效,结果必须分三类处理,否则斗鱼接口抖动一小时就能把上千个好账号标成失效、让客服误判成「CK 大面积挂掉」:
| 判定 | 依据 | 处理 |
| --- | --- | --- |
| `valid` | 两个接口都通过 | 写 `ck_check_status='valid'` |
| `invalid` | 斗鱼**明确**回「未登录 / 登陆异常 / 请重新登陆」 | 写 `ck_check_status='invalid'` |
| `error` | 其余失败(`请求失败:` 超时、`响应异常`、未知结构、走异常兜底) | **不覆盖该行原结论**,只更新 `ck_check_result`(带 `verdict`)与 `ck_checked_at`,计入 `skipped` |
- **自动暂停**:一轮里 `error` 占比 > 30% 且条数 ≥ 20 时,作业把自己 `enabled` 置 false 并在 `message` 写明原因(`detail.paused=true`)—— 大面积「查不到」通常是接口抖动或被风控,继续跑只会污染更多账号;
> 注意:**真实死号占比高不触发暂停**。首轮 100% `invalid` 是合法且预期的情况(选行是「从没检测过的优先」,积压的多是两个月前批量导入、从未登录的陈旧账号)。
- **并发**:默认 5,沿用现有 `ThreadPoolExecutor` 模式;
- **不做**:不改 CK、不建重登批次、不动 `login_tasks.status`。
@@ -991,7 +1001,8 @@ P0 ──┬──> P2 ────┤
| --- | --- | --- | --- |
| 只读查 order_site 打慢对方生产库 | 影响自动发货 | `statement_timeout=3s`、单行索引查询、2 条连接、本地缓存 | 关 `ORDER_SITE_LOOKUP_ENABLED` |
| order_site 改表结构 | 适配层报错 | 只读 4 列且 88 个迁移零变更;SQL 集中在一个文件 | 同上(降级为手工) |
| **巡检本身触发斗鱼风控** | 检测接口被限流/封禁,误判大面积 invalid | 巡检走**只读接口**且不并发过高;失败率超阈值自动暂停;必要时给请求加随机抖动、降 `concurrency` | 关 `ck_health` 作业(回到人工检测) |
| **巡检把「查不到」当成「失效」** | 接口抖动/被风控时批量误标失效,客服误判 | 已做三类判定:只有斗鱼明确回「未登录」才写 invalid,其余只记 `error`、保留原结论;`error` 占比 > 30% 自动暂停作业 | 恢复接口后重新打开作业开关 |
| 巡检本身触发斗鱼风控 | 检测接口被限流/封禁,误判大面积 invalid | 巡检走**只读接口**且不并发过高;失败率超阈值自动暂停;必要时给请求加随机抖动、降 `concurrency` | 关 `ck_health` 作业(回到人工检测) |
| 冷启动一次性全量扫 | 短时高并发被风控 | 首轮小批量(50)观察后再放量 | 调小 `batch_size` |
| 自动重登烧掉邮箱配额 | 该账号当天无法登录 | 单账号退避到次日 + 每日上限 + 失败率熔断 | 关 `ck_relogin` 作业 |
| 自动重登与人工操作撞车 | 状态互相覆盖 | `attempt_status` 在途判断 + 作业锁 | 关作业 |