Skip to content

[PR] fix: invariant judge 4MiB body cap — skip parsing on overflow, no more OOM vector for oversized requests (#4021) | fix: 不变量裁判 4MiB body 上限 —— 超限跳过不解析,超大请求不再有 OOM 向量(#4021) - #4023

Open
ranxianglei wants to merge 3 commits into
masterfrom
2026-10-21_judge-body-cap

Conversation

@ranxianglei

Copy link
Copy Markdown
Owner

Fixes #4021(现象/根因见 issue 正文)。

改动(src/invariant-judge.ts)

验证

  • tests/invariant-judge.test.ts 新增回归:5MiB 字符串 body 零 verdict、跳过日志落在 debug(不是 warn)、Buffer 同路径、连续性车道 prev/next 任一超限即跳、小 body 照常判红(裁判未坏)。27/27 绿。
  • tsc --noEmit 干净。

不触 wire/协议/kernel;纯诊断层加固,且方向只会少做事(超限跳过),不会改变任何判定结果。

@ranxianglei ranxianglei changed the title fix: 不变量裁判 4MiB body 上限 —— 超限跳过不解析,超大请求不再有 OOM 向量(#4021) [PR] fix: invariant judge 4MiB body cap — skip parsing on overflow, no more OOM vector for oversized requests (#4021) | fix: 不变量裁判 4MiB body 上限 —— 超限跳过不解析,超大请求不再有 OOM 向量(#4021) Oct 20, 2026
@github-actions

github-actions Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

📦 Built Package Artifact

Branch: 2026-10-21_judge-body-cap (b1946db)

Option A — Install this exact build (recommended)

npm install -g billion-context@0.0.4810-pr.4023.927500d

This exact version is immutable and reproducible. The rolling pr tag tracks the newest test build across all PRs.

Option B — Download artifact

  1. Download the artifact from the Actions run
  2. Extract the tarball and install:
tar xzf billion-context-pr4023.tgz
npm install -g package

Install instructions are refreshed on each push.

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[bot] 🏷 (ai: vllm-qwen/qwen3.8-27b)

查重: 不重复 —— 按失败签名(invariant judge / JUDGE_BODY_CAP / body cap)检索 open+closed issues 与 PRs:只有本 PR 修复的原始 issue #4021,没有其他在途或已合并的条目修同一缺陷(#3866/#3944 是该裁判的功能引入与 GA,#3985 是 echo 归一化的另一处修复,均已合入,机制不同)。

标签: bug, scope/kernel, p1 —— 缺陷修复(裁判诊断层缺 body 上限);对象是 bili 自身的上下文管理诊断面,不绑定具体客户端故不打客户端标;p1 理由:#3128 放开 5GiB 请求预算后,单个超大请求在这里走整 body JSON.parse,属「内存涨到进程死亡」类向量,且常规 1–5MiB body 每请求都付 CPU 税。

开始独立审核(方向 / 回归 / 代码 / 测试 / diff),结论稍后按八问体例回复。

@ranxianglei ranxianglei added bug Something isn't working p1 scope/kernel labels Oct 20, 2026
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

(ai: vllm-qwen/qwen3.8-27b)

审核结论:可合。 独立审核完成(方向 / 回归 / 代码 / 测试 / diff 全过);审核中发现两处小问题已按「小问题直接修」推到分支上(见下)。

八问:

  1. 是什么问题:不变量裁判(advisory 诊断层)对每个主道请求和 loop 轮 2+ 做一次完整出站 body 的 JSON.parse 来核对「出站内容是否被篡改」,而它没有任何大小上限。[Bug/Enhancement] Codex 超过 100 MiB 的请求在 ACP 处理前断开:希望返回明确 413 并支持配置字节预算(#2606 后续) #3128 把 HTTP 请求预算放到 5GiB 之后,一个超大请求在这里就是一次全量字符串解析 + 全量对象树构建——OOM / 事件循环长阻塞向量;常规 1–5MiB body 则每请求白付几十 ms CPU。
  2. 什么原因导致的:裁判作为纯诊断层没有继承 seam 取证的大小纪律——seam 侧早有 SEAM_BODY_CAP = 512KiB「部分取证,静默跳过」(src/cache-ledger.ts:393,已核实),裁判侧没有同类上限。属边界条件缺失,不是逻辑错误。
  3. 影响范围与严重程度:修复前所有会话的每个主道请求都走无上限 parse——超大 body 有进程级 OOM 风险(p1 类),常规大 body 是稳定 CPU 税。修复后,出站 body >4MiB 的会话失去全部裁判覆盖——恰好是旗舰大会话失去诊断,但只影响诊断面,功能/wire 不受影响。
  4. 怎么修复的:两个入口(maybeRunInvariantJudge 主道 / maybeJudgeContinuity loop 轮 2+)统一先算字节长度(字符串 Buffer.byteLength,Buffer 直接长度),超范围(含空)→ debug 一行日志 + 直接返回,零 verdict 零异常。阈值是模块常量 4MiB,刻意不做 knob——与 SEAM_BODY_CAP 同款常量纪律,避免未经拍板的配置面扩张,符合仓库配置面规则。已核实两个入口覆盖全部生产调用点(src/server/relay.ts:679、src/loop/core.ts:514),且 loop 车道的 prevSentFull 对 clipped/超大场景本来就是 null,无遗漏路径。
  5. 是否有回归问题:逐项过——≤4MiB body 路径逐字节不变;空/缺省 body 原先在 parseExitCores 内部守卫静默返回,现在在门口挡下(verdict 结果不变,多一行 debug 日志);裁判在 body 构造完之后运行、只读,不碰 wire 字节、不进任何缓存键、不触 kernel;没有引入吞错或 fail-fast 语义变化。除「超限跳过代替解析」这一本 PR 目的本身外,无其他行为变更。
  6. 是否破坏缓存:不涉及(裁判输出不参与前缀缓存键,也不改任何重试/游标策略)。
  7. 是否改了设计方向:否。一个取舍已明示:4MiB 阈值意味着超大会话失去裁判覆盖——issue 正文已验证该取舍(诊断完整性 vs 进程安全),我认同这个选择。
  8. 是否引入新配置:否(常量,无 env/config/CLI 面扩张)。

审核中顺手修的两处小问题(PR 分支上的附加 commit,各自独立绿):

  • 60c5c1571 — 原跳过日志写死 "body over 4 MiB",但门实际连空/缺省 body 也跳,措辞与事实不符;改为报告实际尺寸("body 0B outside judge range"),并把长度计算从两次收敛为一次(超大字符串的跳过路径不再扫两遍)。补测试钉住「缺省 body → 零 verdict」。
  • b1946dbc0 — issue 规格与 PR 描述都说两个入口超限各打一行 debug 日志,但连续性车道(maybeJudgeContinuity)实际静默。补齐 debug 行,补测试钉住「两次连续性跳过均可在 debug 观测」。

测试有效性:新增回归断言有牙——5MiB body 里藏了 "REWRITTEN BY DEFECT" 标记,cap 失效一旦去解析就会判红被抓;跳过级别钉在 debug(不是 warn);Buffer/字符串双路径;小 body 照常判红的 sanity 检查证明 cap 没弄坏裁判。基线(原 head)27/27 绿,我的两个 commit 后仍 27/27,tsc --noEmit 干净。全量套件判定以远程 CI 为准。

diff 整洁度:原 PR 2 文件 +59/-0,加我两个 commit 后仍只有 src/invariant-judge.ts 与 tests/invariant-judge.test.ts,每一行都与本 PR 目的相关,无无关改动、无格式 churn。

自动合并门槛(§7.4):机械条件满足(单模块 fix:、有回归测试、干净 diff、引用 Fixes #4021、不触 config schema/持久化/wire/kernel/update.ts)——合并动作归你。

关联发现:发送咽喉点还有一处同域的未封顶整 body parse(src/server/relay.ts:639,seam 取证,喂估算/消息计数/#3803 指纹)——机械照搬 cap 会回退 #3803 的尾字段可见性设计,已在 #4021 登记为 checklist 项并给出 A/B/C 选项(推荐 A),等你拍板,未混入本 PR。

CI:新 head b1946db 上 gate 已绿,guard/test 分片在排队(hermetic runner 并发受限),完成后我补一条结果。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

(ai: vllm-qwen/qwen3.8-27b)

CI 结果跟进(上条八问回复承诺的收尾)

b1946db 的全量 CI 已跑完:42 项检查 = 25 绿 / 12 skip / 5 个测试分片红。我把 5 个红分片的原始日志全部拉下来逐一对过:

5 个红分片的真实失败全部是同一对既有测试(#3769 会话记录读回家族),与本 PR 改动无关:

分片 失败
ubuntu-22 s1 issue3769-pooled-bare-load.test.ts:115(断言 hydrated envelope)
ubuntu-22 s3 issue3769-upgrade-compat.test.ts:179(断言 record hydrates before the upgrade turn)
ubuntu-24 s1 两条同中(该分片 2 fail)
windows-22 s1 upgrade-compat 同断言
windows-22 s2 pooled-bare-load 同断言(+9 条 pi-omp-fork-adopt 的 cancelledByParent 尾随取消,伴生噪声、非独立缺陷)

判定「与 PR 无关」的硬证据:

  1. master 自己就是红的:最近两个 master 提交(bc4a3f8、be1e4cdae)各自 5 个测试分片红,签名相同——master 上没有本 PR 的任何 diff;
  2. 上一轮修这个家族的 [PR] fix: bare-id loadSync hydrates pooled envelopes without the unified index (master CI flake, #4014) #4015(walk 播种条件放宽)已包含在两边树里,红依旧——残留机制在 [PR] fix: bare-id loadSync hydrates pooled envelopes without the unified index (master CI flake, #4014) #4015 之后仍在发作;
  3. 两条测试对推上去的同一棵树本地定向跑 2/2 通过(CI 高频、本地不复现,与 master CI red: #3769 upgrade compatibility test flake — bare-id loadSync only records one read path (sqlite index) for t | master CI 红: #3769 升级兼容测试 flake — bare-id loadSync 对 pooled 路径记录只有 sqlite index 一条读路径 #4014 观察一致);
  4. 本 PR 只动 src/invariant-judge.ts(纯诊断层、只读判定、不触存储路径)+ 其测试文件,没有影响存储水合时序的机制。

本 PR 自身在 CI 里的表现: invariant-judge 相关测试在所有跑到它的分片全部通过(含新增 cap 回归 ok 562);CI 日志里能看到新行为实际生效,例如 [invariant-judge] body 5242991B outside judge range (≤4194304B) — skipping (advisory layer, #4003 cap)。非测试门禁(gate/guards/build/静态检查)全绿。

处置:

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

(ai: vllm-qwen/qwen3.8-27b)

收尾补充

本 PR 的工作已全部完成,补两点状态说明:

  1. 平台自动转发的「CI 失败修复」(floor 6)由上面的人工 triage 覆盖:5 个红分片全部是既有的 [Bug] MCP failed compression record rotation prematurely rewrites the history prefix, triggering expensive cache recompu | [Bug] MCP 失败压缩记录轮换提前改写历史前缀,触发大额缓存重算 #3769 会话记录读回测试家族——master 自己同样红、[PR] fix: bare-id loadSync hydrates pooled envelopes without the unified index (master CI flake, #4014) #4015 的修复已包含在两边树里、两条测试在同一棵树本地 2/2 通过,与本 PR 改动无关。因此本分支上不再做额外「修 CI」动作(避免再派一个 agent 从零分析同一问题),残留面已在 master CI still red after #4015's flake fix: two session-record-load tests fail intermittently on ~40% of test shards | master CI 在 #4015 修完 flake 后仍红:两条会话记录读回测试在约四成测试分片上间歇失败 #4039 跟踪。
  2. 当前状态:分支 head b1946dbc0(你的原始提交 + 审核顺手修的 2 个小 commit);非测试门禁全绿,invariant-judge 相关测试全绿且新 cap 行为在 CI 日志中实际生效;唯一未决项是既有 CI 红——master CI still red after #4015's flake fix: two session-record-load tests fail intermittently on ~40% of test shards | master CI 在 #4015 修完 flake 后仍红:两条会话记录读回测试在约四成测试分片上间歇失败 #4039 修好后重跑一次(或 rebase 到那时的 master)即可拿干净判定。

无其他未决事项。合并判定维持八问结论:内容可合,合并动作归你。

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working p1 scope/kernel

Projects

None yet

1 participant