JianFeeeee
56ea269f98
feat(channels): reap_orphan_sources —— 清理 v2.0.28 事故留下的存量孤儿源
## 发现路径:查"功能都正常了吗",逐源核对时发现的
生产 `config.yaml` 里有 21 个源,其中 `channels-buddy-585b335b64cf`
的账号 `585b335b64cf` **早已删除**(v2.0.23/24 的无凭据账号清理),
但它的源**仍在对外服务**:
- 独占提供 `hy4-preview-x` ⇒ 实测报 `404 Route Not Found`;
- 对 **6 个共享模型**则排在新源**前面**先被尝试(config 文件序即注册序)
⇒ 每次都撞 404 再回退,**每次白付一次上游往返**(实测 hy4-preview
稳定 3.1~3.5s);
- 它的 base_url 还是 v2.0.30 之前的旧口径
(`https://copilot.tencent.com/v2/chat/completions`,侵占了 endpoint 路径)。
**根因**:这正是 v2.0.28(`remove_source` 漏声明 ⇒ 撤源全被拒)日记里
那句"账号删了、它的源还在对外服务"的**存量残骸**。
v2.0.28 修了声明,**只防新增、不清理存量**。
**发现的一个助力**:v2.0.38 刚修好的错误文案让它暴露得更清楚 ——
客户端拿到的是 `404 Route Not Found`(APISIX 原文)而不是 `unknown error`。
## 修法
1. **立即清理**:走内核正式 API `DELETE /api/sources/<name>` 删掉该孤儿源
(不手工改配置)。清理前备份配置,三重确认它确无对应账号。
2. **结构性修复**:新增 `reap_orphan_sources` 正式入口
(`POST channels/reap_orphan_sources`,admin),识别
`channels-<已知平台>-<账号id>` 且账号**不在**池中的源。
### 安全性(破坏性操作两条纪律,照 `reap_loopbacks` 先例)
- **只删该删的**:按**已知平台 id 前缀**逐个匹配。
⚠️ **不能用** `name:match("^channels%-(.+)-(.+)$")` —— Lua 的 `-` 是**贪婪**的,
会把 `channels-buddy-buddy-main` 切成 plat="buddy-buddy"/acct="main"
(账号 id 含 `-` 就错,而 `buddy-main` 就含)⇒ **孤儿漏杀**。
运维手工配的源、旧版单账号源 `channels-<平台>` 一律不碰。
- **`dry_run` 默认开启**:不带 `dry_run=false` 只报告不删。
## 判据(`channels_orphan_source_test.go`,变异 2/2)
- 造出**真实形态**:`account_add` 建账号 → hidden 探针摘池(保留源),
模拟"源留下"这个状态(不走 `account_delete`:那条路径会把源一并撤掉,
而我们要的恰恰是它留下的形态)。
- 断言三件事:dry_run 只报告不删、真删后孤儿消失、**手工源全程存活**。
- **判别性用例**:第二个孤儿的账号 id 含 `-`(`dead-acct-1`)。
这是唯一能区分"按已知平台前缀匹配"与"贪婪 match"的用例 ——
实测不含 `-` 的 id 两种实现结果相同,**咬不住**(第一版就栽在这)。
- 变异:① `dry_run` 默认改 false ⇒ 报红;② 改回贪婪 match ⇒ 报红。
## ★ 过程中踩到的三个坑(都已记进代码注释)
1. **`Plugins.Call` 的参数是平铺的,不是 `req.body`** —— `bodyOf(req)` 返回空表,
`dry_run=false` 被静默丢成默认 true ⇒ "真删"永远没发生。
必须同时兜住两种调用形态(HTTP 路由走 body,插件 Call 平铺)。
2. **内核 `add_source` 取 `args["source"]`(嵌套一层)**,平铺字段被拒
("add_source requires a source table")。
3. **`config.Model` 要求 models 是对象数组 `{id=...}`**,传字符串数组被拒。
4. **判据只查 Go 侧 `err` 会静默通过**:内核把失败放在**返回体**里,
Go `err` 仍是 nil ⇒ "源根本没注册"看起来像"没有孤儿"。
2026-10-17 08:34:47 +08:00
..
2026-10-14 16:52:58 +08:00
2026-10-14 16:52:58 +08:00
2026-10-14 16:52:58 +08:00
2026-10-14 20:01:24 +08:00
2026-10-14 20:01:24 +08:00
2026-10-14 16:52:58 +08:00
2026-10-16 20:47:50 +08:00
2026-10-14 16:52:58 +08:00
2026-10-14 16:52:58 +08:00
2026-10-14 16:52:58 +08:00
2026-10-16 07:51:59 +08:00
2026-10-14 20:01:24 +08:00
2026-10-14 16:52:58 +08:00
2026-10-16 00:56:35 +08:00
2026-10-14 16:52:58 +08:00
2026-10-14 16:52:58 +08:00
2026-10-14 16:52:58 +08:00
2026-10-14 16:52:58 +08:00
2026-10-11 20:50:52 +08:00
2026-10-16 13:52:02 +08:00
2026-10-14 20:01:24 +08:00
2026-10-14 16:52:58 +08:00
2026-10-14 16:52:58 +08:00
2026-10-14 16:52:58 +08:00
2026-10-14 16:52:58 +08:00
2026-10-16 17:44:04 +08:00
2026-10-14 16:52:58 +08:00
2026-10-16 21:49:36 +08:00
2026-10-14 16:52:58 +08:00
2026-10-13 07:41:56 +08:00
2026-10-15 22:43:58 +08:00
2026-10-17 08:34:47 +08:00
2026-10-14 16:52:58 +08:00
2026-10-16 09:01:01 +08:00
2026-10-14 16:52:58 +08:00
2026-10-14 16:52:58 +08:00
2026-10-14 20:01:24 +08:00
2026-10-14 16:52:58 +08:00
2026-10-14 16:52:58 +08:00
2026-10-14 16:52:58 +08:00
2026-10-14 16:52:58 +08:00
2026-10-14 16:52:58 +08:00
2026-10-16 10:26:55 +08:00
2026-10-16 09:36:23 +08:00
2026-10-14 20:12:10 +08:00
2026-10-14 16:52:58 +08:00
2026-10-14 16:52:58 +08:00
2026-10-16 08:28:47 +08:00
2026-10-14 16:52:58 +08:00
2026-10-14 16:52:58 +08:00
2026-10-16 00:56:35 +08:00
2026-10-14 16:52:58 +08:00
2026-10-14 16:52:58 +08:00
2026-10-16 13:52:02 +08:00
2026-10-16 17:44:04 +08:00
2026-10-15 08:23:25 +08:00
2026-10-15 08:23:25 +08:00
2026-10-15 20:31:45 +08:00
2026-10-15 08:23:25 +08:00
2026-10-16 01:38:51 +08:00
2026-10-17 00:01:33 +08:00
2026-10-14 16:52:58 +08:00
2026-10-14 16:52:58 +08:00
2026-10-14 16:52:58 +08:00
2026-08-13 12:25:07 +08:00
2026-10-11 20:50:52 +08:00
2026-10-11 20:50:52 +08:00
2026-10-14 16:52:58 +08:00
2026-10-15 08:23:25 +08:00
2026-10-14 16:52:58 +08:00
2026-10-14 16:52:58 +08:00
2026-10-11 13:52:29 +08:00
2026-10-03 08:01:37 +08:00
2026-10-03 07:45:54 +08:00
2026-10-14 16:52:58 +08:00
2026-10-07 17:37:22 +08:00
2026-09-28 22:52:51 +08:00
2026-10-14 16:52:58 +08:00