Skip to content

[storage] unified store only grows: content rows are never deleted or archived — index.db at 637 MB on a single dev machine (GC: refcount content, expire sessions, vacuum) #3463

Closed

Description

@ranxianglei

一句话

统一存储(index.db)只进不出:消息正文的内容行从不删除、老会话从不归档过期,主库文件在单机开发环境已经 637 MB 并持续增长——需要一套 GC(引用计数删行 + 会话过期归档 + VACUUM 收缩)。这是 #2671/#2960 路线里的 ⑦。

现状实测(2026-10-17,本机)

index.db       637 MB  ← 主库文件(一周前 563 MB,持续涨)
index.db-wal    32 MB  ← #3255 修复后有界(journal_size_limit 8MB + 周期 PASSIVE)

上次普查(563 MB 时)的构成:

构成 大小 说明
content CAS(消息正文,append-only 去重) ~360 MB 真实数据,持续增长
700 会话的 state/blocks/metadata ~200 MB 662 proxy / 33 pi / 5 dsh
freelist(已删未回收空间) 仅 ~5 MB 连删除都很少发生

病根(为什么不是 checkpoint 的问题)

#3255 修的是 -wal 伴生文件永不回收,和这里无关。主库膨胀是四件事叠加:

  1. 正文 CAS 只追加:内容行按内容哈希全局去重,但会话删除后其内容行没有任何引用回收路径;
  2. CCR 依赖保留原文:折叠后的原始消息必须可检索,旧内容版本不能随折叠释放;
  3. 会话无过期:Storage layer: four concrete defects (filename coupling, multi-writer heuristic, non-atomic content-store write, immortal compressed sessions) #2671 §7 定了 archiveAfterDays: 365(默认值拍板过),但从没实现;
  4. 无 VACUUM:即使删了行,freelist 空间也不还给操作系统。

要做的(建议拆两步)

第一步:引用计数 + 删除(纯增量,不动 schema 大结构)

  • content 行记引用来源(活会话 / 活块 / CCR 条目 / session_ext);
  • 删除会话时联动清算:该会话独占的内容行删掉,共享行减计数;
  • 提供手工入口(/__bili/storage/gc 或 CLI)先跑一遍,验证收益后再谈自动化。

第二步:过期归档 + 自动化

  • archiveAfterDays 落地(默认 365d,web 会话列表默认不显示已归档);
  • 归档 = 内容行照删、会话元数据留一行墓碑(可按 id 找回备份);
  • VACUUM(或 PRAGMA incremental_vacuum + auto_vacuum)在 GC 后收缩文件——注意 VACUUM 需要约 2× 磁盘瞬时空间和大锁,安排在空闲期或用增量模式。

验收

参考:#2671(§7 决策)、#2960(⑦ 排位)、#3255(WAL 修复,别混淆)。

Activity

  1. ranxianglei commented on Oct 17, 2026

    @ranxianglei
    OwnerAuthor

    🤖 Powered by ework · qwen3.8-27b

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

    查重: 不重复。 检索了 open+closed 的 issue 与 PR(关键词 archiveAfterDays / VACUUM / refcount / content rows / storage gc):

    开始处理。先做三件事再动手:① 把 src/storage/ 全链读一遍(schema、CAS content 表的引用来源、deleteSession 现状、CCR 条目、session_ext),确认真实的引用图;② 核对 #2671 §7 的 archiveAfterDays 决策原文与 #3255 的 WAL 修复边界,避免混淆;③ 按 issue 建议先落第一步(引用计数 + 删除 + 手工 GC 入口),收益验证后再谈第二步自动化。有进展回本线程。

  2. ranxianglei commented on Oct 17, 2026

    @ranxianglei
    OwnerAuthor

    🤖 Powered by ework · qwen3.8-27b

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

    第一步完成 → PR #3466(分支 2026-10-17_storage-gc-step1:清扫联动修复 + GC 手工入口 + 一个 gate 小修)。按你定的顺序只做了「引用清算 + 手工入口」;自动化(第二步)等收益确认后再上。

    动手前的审核结论:先把 #2671 §7 的四层 refcount 防护设计对照代码逐条核查——①同事务计数已有(ingestSession/deleteSession 全程事务内维护计数,storage-engine-proofs 钉住);②verify 对账缺,本次补上;③不一致注入 fixture 由新测试覆盖;④周期调度属第二步。引用计数机制本身不是病根,真正缺的是两件事:(a) #1082 文件清扫从不通知统一存储——gcSessionFiles 只 rm(file),被扫会话的 index.db 行及其背后全部 CAS 引用永久存活(「文件在减、库还在涨」就是这个机制);(b) 没有任何路径把释放的页还给 OS(从未有 VACUUM)。与你的四条病根一致,另挖出具体泄漏路径 (a)。

    八问:

    1. 是什么问题:统一存储 index.db 只进不出——会话文件被清扫后其索引行与正文 CAS 行永不回收,释放的页也不还给操作系统。
    2. 什么原因导致的:两层。直接原因:[Feature] Default state file cleanup strategy #1082 清扫路径只删 legacy JSON 文件、从不调用统一存储的 deleteSession,CAS 引用计数永不递减;放大原因:即使存在零引用行,也没有对账/回收/VACUUM 入口,空间留在 freelist。注:存量 637MB 的大头是 700 个从未被删除的会话行——那部分要「删除/归档」真正发生才有收益,本 PR 让删除生效 + 提供一次性手工入口。
    3. 影响范围与严重程度:所有 unified 模式实例(shadow 是默认模式 = 所有新实例);磁盘持续增长(单机一周 563→637MB),不丢数据、不影响功能,慢性资源问题。
    4. 怎么修复的:三条腿。①清扫联动:gcSessionFiles 删文件前先调 SessionStore.removeUnifiedSession(id)(索引先行、文件殿后,与既有 removeLegacyFile 同序,幂等自愈);②手工 GC 入口 POST /__bili/storage/gc(loopback-only,与其余 __bili 路由同一道门):先对账(每条 CAS 行的账面引用计数 vs messages/块摘要+one-fold/CCR/checkpoint state 五列实数——多记的变可回收、少记的先纠正再谈删,防提前误删),再收零引用行,最后可选全量 VACUUM 缩文件;响应带行数/字节数/漂移分类/前后文件大小;③CONFIGURATION.md 中英文档。fix/vacuum 在 HTTP 层默认 true,按构造安全(fix 只把账面拉回实际值,reclaim 只碰可证无人引用的行,VACUUM 不碰活数据)。
    5. 是否有回归问题:逐项审过既有行为——legacy-only 模式:无 sidecar = no-op,行为不变;pinned checkpoint 保护(Storage Phase 2a: replica/checkpoint REST — freeze, restore, GC-proof pins (#2671) #2745):对账 SQL 把 checkpoint state 引用计入实数,pinned 副本引用的内容不会被当孤儿收掉;共享去重:t5 用例钉住(两会话共享一行,删一存活、删二消失);[bug] Fold anchor detaches after host restart (parent-gone): hydrated and unified-shadow DIGEST DRIFT within the same second, gap solidifies without self-healing (0.1.197, complementary to #3013 restart path) | [bug] 宿主重启(parent-gone)后 fold 锚点脱锚:hydrated 与 unified-shadow DIGEST DRIFT 同秒,缺口固化不自愈(0.1.197,与 #3013 重启路径互补) #3285 水位/增量摄入路径未触碰;STORAGE_SCHEMA_VERSION 保持 v5(纯增量、无迁移)。高危模式逐项:无语义漂移、无 fail-fast 变吞错(GC 失败走 500 并保留错误文本)、无阈值/时序变化(VACUUM 仅手动触发、不进写路径)、既有端点响应未动(纯新增端点)。本地定向套件全绿(sweep/storage 相关 99 pass,1 个环境性 skip 与本改动无关);全量以 CI 为准——首推后仅 unused-exports 静态 gate 红(报告类型未在测试里具名,已补标注 commit,重跑中)。
    6. 是否破坏缓存:不涉及 LLM 前缀缓存(纯持久化层);WAL 仍受 fix: 长驻进程里 index.db-wal 永不回收 —— journal_size_limit + open/close TRUNCATE + 周期 PASSIVE (#3250) #3255 的 journal_size_limit 约束,未动。
    7. 是否改了设计方向:没有。完全沿 Storage layer: four concrete defects (filename coupling, multi-writer heuristic, non-atomic content-store write, immortal compressed sessions) #2671 §7 既定设计落地(四层防护中的第②③层:verify --fix + 注入 fixture),只新增一个运维 loopback 端点形态,数据流不变。
    8. 是否引入了新的配置:零新 config key/env var/CLI flag。唯一新表面是 POST /__bili/storage/gc,body {fix?, vacuum?} 均可省略、默认 true,已在 CONFIGURATION.md 中英记录。

    实测数字(如实说明):本沙箱够不到你机器上的活 index.db,PR 里写的是合成语料实测:300 活会话 + 100 死会话(模拟修复前的清扫泄漏类:行被删但 CAS 引用未放)→ 一轮 runGc({fix,vacuum}):78.9MB → 59.26MB(−24.9%),0.3s;修正 100 条孤儿引用,回收 100 行/19.54MB,剩余 ≈ 恰好等于活会话内容。真实数字:合并后在你本机跑 curl -sS -X POST http://127.0.0.1:<bili端口>/__bili/storage/gc(VACUUM 需约 2× 瞬时磁盘空间,先确认盘上有 ~1.3GB 空闲)。提醒:你那台机器的最大杠杆是打开 BILI_SESSION_GC=1(opt-in 清扫)让老死会话的文件真正被清掉——本 PR 之后每次清扫都会连带释放索引行,再跑一次 GC 端点收编。

    遗留(已写进 PR,不阻塞):lane-excluded(inc:)会话在下次启动水位重置前跳过 #3285 陈旧消息清扫,其间陈旧消息行持有 CAS 引用(自愈合);第二步待你拍板:archiveAfterDays 默认 365d(#2671 §7 已定)、瘦身归档(删原文保账本+摘要+墓碑)、增量 VACUUM 调度。

    判定:第一步闭环,可合(等 CI 绿 + 你过目);合入后在本机跑一轮端点拿真实数字,确认收益即开第二步。PR:#3466

  3. ranxianglei commented on Oct 17, 2026

    @ranxianglei
    OwnerAuthor

    🤖 Powered by ework · qwen3.8-27b

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

    进展同步:#3466 的 CI 已全绿,现在只差人工合并。

    期间发生了三件事,如实说明:

    1. 分支已 rebase 到最新 master:我工作期间 master 合入了十几个 PR(到 fa41483d4),分支已在新 master 上重新验证——typecheck clean、storage 相关定向套件(session-gc / state-gc / proxy-orphan-gc / engine-proofs / unified / replicas / ext / json-writer-off / watermark / review-fixes)全绿。
    2. 分支上多了一个加固 commit(3371fcdfd,不是我推的,内容已逐行核对后保留):/__bili/storage/gc 对非对象 JSON body(null / 数组 / 数字 / 字符串)现在直接 400(原来会落到 500),并新增一个真实 server 的 HTTP 测试用例钉住默认参数契约(bare POST → 200,vacuum 默认执行)。质量没问题,按「小修直接进 PR 分支」惯例收下。
    3. CI 状态:完整矩阵已有一轮全绿(9 个 test 分片 ubuntu/windows × node 22/24 + 全部静态门禁)。其中 test (windows-latest, 22, 1) 在早期一次运行里失败过(日志已过期取不到、无失败签名;同一分片在后续运行中通过,判定为瞬时 flake),但该失败记录仍挂在 head commit 上,而 master 分支保护要求这 12 个 test check 全绿 → PR 显示 blocked。我已对分支 tip 触发了一轮全新的 workflow_dispatch 核心矩阵,新一轮 check-run 挂绿后会覆盖旧的红记录。

    代码内容没有变化,仍是上一轮说的两个 commit(sweep parity 修复 + 手动 GC 端点)。等这轮 CI 挂绿后,PR 就只剩等你的 review/merge。

  4. ranxianglei commented on Oct 17, 2026

    @ranxianglei
    OwnerAuthor

    🤖 Powered by ework · qwen3.8-27b

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

    状态更正与进展(如实):

    上一轮我说「等这轮 CI 挂绿」——期间 master 又前进了(到 f054c9d9a),我已把分支 rebase 上去并推送(tip 2cbf0a6f5,代码内容不变,仍是那 5 个 commit,diff 逐文件核对过),并触发了一轮完整 12 分片矩阵。当前状态:

    • 11/12 test 分片绿;test (windows-latest, 22, 2) 红了,正在拉日志定位是 flake 还是真问题(我 diff 只碰 session-gc/persist/storage/admin + 自己的测试文件,该分片红需要证据定性,不会猜);
    • master 在跑 CI 期间又合了 2 个 PR——即使这轮全绿,合并前还需要最后一次 rebase + 一轮 CI(今天仓库很活跃,这是流程现状,不是本 PR 的问题);
    • 定位出结果后回本线程,给出最终收口结论。
  5. yanghuan commented on Oct 18, 2026

    @yanghuan

    补一条 #3748 的实测数据(bili 0.1.201 / storage.unified 未设 = shadow 默认 / Windows x64 / Node v24.19.0,未调任何参数)。它和上面「引用计数机制本身不是病根」的结论对不上,可能影响 #3466 的验收前提,所以贴过来:

    1. 孤儿是"被持续生产"的,不是存量

    • content 表 79,992 行 / 2,478.1 MiB,其中 refcount = 0 的孤儿 62,138 行 / 2,199.5 MiB = 88.6% 的字节。
    • 也就是说这里的大头不是「700 个从未被删除的会话行」——它们已经是被 releaseContent() 降到 0 的行,只是没有任何路径回收。

    2. 主因是同一份内容被反复摄录,且 CAS 键每次都变

    • 图片 blob 2,592 行,却只有 261 个不同像素载荷 → 11.06× 冗余(实际 2,316.8 MiB vs 理想 209.5 MiB)。
    • 取同一个载荷的两行逐字段 diff,只差两个字段:
    [id]        A: "h_88b5433245c4751e_51"    B: "h_88b5433245c4751e_50"
    [wireIndex] A: 3229                       B: 3228
    byte_len:   1557535                       1557535      <-- 字节数完全相同
    sha256:     7cfb6125…                     1936538c…    <-- 却分成两行
    

    putContent() 对整个 JSON 包装取 sha256,而包装里带着每次 ingest 重铸的 id(_N 后缀)和 wireIndex → 同载荷必然未命中,去重在结构上不可能发生。

    • messages 表里同一张图有 289 行:h_88b5433245c4751e、_1 … _288,seq/ref 一路递增。UNIQUE(session_id, msg_id, content_hash) 因为 msg_id 每次都变,从不触发 → shadow 双写不是幂等的。
    • 最坏单张图被存 56 份 = 83.2 MiB(本该 1.49 MiB);另一张 44 份 = 96.7 MiB。
    • 对照:所有消息正文 + 工具输出加起来只有 168.1 MiB,即真实载荷不到文件的 7%。

    3. 增速与 VACUUM

    三个观测点 index.db:442.8 → 1,224.5 → 2,543.1 MiB;第二段窗口 758 MiB/h ≈ 17.8 GiB/天(第一段 390 MiB/h)。auto_vacuum = 0,全库无 VACUUM,DELETE FROM content WHERE refcount <= 0 只出现在 deleteSession / deleteCheckpoint 尾部。

    4. 对 #3466 的影响

    POST /__bili/storage/gc 回收存量是必要且正确的第一步,但源不清 → 会按同样速率长回来:孤儿不是只在删会话时产生,而是在每次 re-ingest 时批量产生。合并后如果只跑一次 GC,很容易被读成"已解决"。

    建议(写入侧,详见 #3748):CAS 键改为对规范化载荷取哈希或剔除 id/wireIndex 等易变字段;ingest 改成按 (session_id, content_hash) 幂等 upsert;shadow 模式不再镜像图片原始字节。

    复现脚本(只读 node:sqlite)与完整证据在 #3748。

  6. ranxianglei commented on Oct 18, 2026

    @ranxianglei
    OwnerAuthor

    🤖 Powered by ework · qwen3.8-27b

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

    @yanghuan 的实测数据我逐条对着代码核过了,机制成立,分层结论如下:

    1. 代码级验证(写入侧非幂等,属实)

    2. 与我之前结论的关系(修正表述)
    我之前说的「引用计数机制本身不是病根」仍然成立但要补全:refcount 记账本身是准的(有测试钉住),但 rc=0 行的生产者不止一个——①sweep 不清理 index(#3466 修)、②写入侧 re-ingest 非幂等持续铸造(#3748)。你的数据证明 ② 是图片密集会话下的主力。#3748 单独立项的粒度是对的:症状不同(持续增长 vs 存量积压)、机制不同(写侧键不稳定 vs 保留侧不回收),不属于本 issue 范围,我不在 #3466 里顺手扩面去修它。

    3. 对 #3466 验收的影响(直接回答你第 4 点)
    同意——合并后只跑一次 GC 清的是存量,源不堵会按 ~758 MiB/h 长回来。已做两件事防误读:

    4. CI 状态(顺带同步)
    分支已 rebase 到 master 7efa991f6(tip 22257be4f),全矩阵 dispatch run 39003896353 28/28 全绿。core 自动跑的 win-22-2 又红了一次:日志核实为 runner 磁盘写满(ENOSPC ×2)导致 7 个 lane-matrix 子测试被 cancel,fail 0——同一 commit 的全矩阵 run 里该 shard 是绿的,判定基础设施死亡而非代码问题,已提交 rerun。另发现 ci-gate-plugins.yml(设计上仅手动触发)在最近所有分支的 push 上都会自动跑且零 job 失败——全仓既有现象、与本 PR 无关,已单独立记录 issue([no-dispatch]),不混入本线程。

    判定不变:#3466 可合(等 win-22-2 rerun 转绿 + 过目);#3748 是并行的写入侧修复线,两条腿都落地后这个病的闭环才算完整。

  7. ranxianglei commented on Oct 18, 2026

    @ranxianglei
    OwnerAuthor

    🤖 Powered by ework · qwen3.8-27b

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

    补充一个写入侧近亲机制,供 step 2 评估参考:#3748(已开 issue 并本地复现)证明 index.db 增长的另一半来自持续生产,而非仅保留不足——shadow ingest 在每次 fold 后为存活图片重铸身份(id + wireIndex 漂移),CAS 按含易变字段的 wrapper 全文哈希 → 每次 fold 突发 O(tail) 新 blob;completeLog 清扫留下的 rc=0 行目前只在 deleteSession/deleteCheckpoint 时被物理删除。你 PR 里的 reclaim 步骤正是这类孤儿的唯一出口,step 2 自动化(定期 reclaim ± vacuum)对 #3748 的磁盘侧同样是必要件。两侧互链、不重复立项;根因侧(kernel 媒体身份稳定化)已单独立项为 #3751,等 owner 批准。

  8. ranxianglei commented on Oct 18, 2026

    @ranxianglei
    OwnerAuthor

    🤖 Powered by ework · qwen3.8-27b

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

    CI 状态同步(#3466 收尾中):

    • master 这两天推进了 200+ 个提交,分支已 rebase 到当前 master(6f2b113bd),新 tip 851e349d6(5 个提交内容与之前完全一致,patch-id 逐一核对过)。该 sha 的全量矩阵已全绿(12/12 必需测试上下文 + 全部静态门);刚才的 push 又触发了一轮核心测试(push 事件),正在跑,同代码预期同样绿。
    • 期间唯一的红是 test (windows-latest, 22, 2),两次尝试签名完全一致:TAP fail 0 / cancelled 5~7 / pass ~3315,日志里 ENOSPC: no space left on device ×2 —— Windows runner 磁盘满的基础设施死亡,不是代码问题(同一提交同一分片在全量矩阵运行里是绿的,两次尝试零真实测试失败)。
    • 顺带发现并记录了个小噪音:.github/workflows/ci-gate-plugins.yml 按设计是纯手动工作流,但最近每次 push 都会自动触发一次且以「零 job」方式失败(不阻塞合并、不在必需检查里)。已立记录 issue ci-gate-plugins.yml (manual-only gate) auto-runs on every push and fails with zero jobs #3750(带 [no-dispatch],只作 owner 可见性,请求确认是不是有自动化在每次 push 后 dispatch 它)。

    判定不变:#3466 可合——等这轮核心测试跑完转绿(mergeable_state 会自动变 clean),你合入即可。第二步(archiveAfterDays 过期归档 + 自动化 GC)按你的验收节奏,等你对第一步实际收益点头后再开工。

  9. ranxianglei commented on Oct 18, 2026

    @ranxianglei
    OwnerAuthor

    🤖 Powered by ework · qwen3.8-27b

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

    #3466 最终状态(含一条更正):

    先更正我上一条同步里的一个错误:当时说「该 sha 的全量矩阵已全绿」为时过早——我引用的那个运行 ID 实际不存在,851e349d6 当时并没有跑过全量矩阵。现在补上了:我手动 dispatch 了一次全量矩阵运行(run 39166574470),已完成且全绿——12 个必需测试上下文(ubuntu/windows × 22/24 × 分片 1-3)+ 全部静态门都是 success,win-22-2 这次也干净通过(没有再出现磁盘满)。逐上下文核对过 check-run 数据(翻了全部页面,不是只看第一页),没有任何一个必需上下文是红或 pending;分支 base 与 master 完全一致(6f2b113bd,落后 0)。

    但有一个异常:API 里 mergeable_state 仍然报 blocked。我把能查的都查了——分支保护只要求那 12 个上下文(strict)、无 rulesets、无 review 要求、无签名要求,而 12 个上下文的最新 check-run 全部是绿;老的 combined status 接口却返回 pending(且 0 条 legacy status)。判断是 GitHub 侧的状态评估没刷新(这个分支经历过多次 rebase + force-push,加上这次绿来自手动 dispatch 的运行,可能触发了评估缓存问题)。我还顺手取消了一个卡住的核心 CI 运行(它从 20:53 起一直 in_progress 但零 job,疑似并发排队卡死),取消后状态也没变。

    请你打开 PR #3466 的 Checks 页确认一下:如果 UI 上 12 个必需检查都显示绿,直接合入即可(按钮应该是可用的);如果 UI 显示某个具体检查还在挡,告诉我挡的是哪一个,我来定向处理。如果你愿意,我也可以再 dispatch 一轮全新全量矩阵强制触发重新评估(代价是再烧约 20 分钟 runner 时间)。

    代码层面结论不变:#3466 可合,只差合并门禁认账这一步。

  10. ranxianglei commented on Oct 18, 2026

    @ranxianglei
    OwnerAuthor

    🤖 Powered by ework · qwen3.8-27b

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

    「分支过期」核查结果:无需 rebase——刚做了权威核对:git rev-list --count HEAD..origin/master = 0,merge-base 与 master HEAD 完全一致(都是 6f2b113bd),PR base 也是它。这条通知反映的应该是昨晚之前 master 的移动(f054c9d9a → 7efa991f6 → 6f2b113bd),而当前 tip 851e349d6 已经包含全部——按「冲突解完不要重复 rebase」的纪律,这次不动分支。

    当前唯一悬着的还是那条异常:12 个必需检查上下文在 head sha 上全部绿(全量矩阵 run 39166574470),但 API mergeable_state 一直报 blocked。我刚又手动 dispatch 了一轮全新全量矩阵(约 20 分钟出结果)强制触发重新评估;跑完后我会逐上下文复核并回帖。

    在你那边:如果 PR #3466 的 Checks 页 UI 显示必需项全绿,直接点合入就行(API 状态可能是缓存滞后);如果 UI 上能看到具体哪个检查在挡,发我一下我定向处理。

  11. ranxianglei commented on Oct 18, 2026

    @ranxianglei
    OwnerAuthor

    🤖 Powered by ework · qwen3.8-27b

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

    #3466 卡在 GitHub 合并状态评估上(非代码问题)——需要你拍板一个动作

    八问:

    1. 是什么问题:代码与验证已全部完成并全绿;卡住的只是 GitHub 对 PR [PR] storage: unified index GC — release rows on file sweep + manual reconcile/reclaim/VACUUM pass #3466 的 mergeable_state 评估一直停在 blocked,不转 clean。
    2. 什么原因导致的:本地能查的原因全部排除——分支落后 master 0 个提交(merge-base == master HEAD == PR base == 6f2b113bd);分支保护只要求 12 个测试上下文且 strict(已逐上下文翻全部页核对,最新 check-run 全绿);无 rulesets、无 review 要求、无签名要求(ranxianglei 是用户账号,org 级 rulesets 不存在)。同一 sha 上两轮独立的全量矩阵运行都完整成功(39166574470 + 39170092755),取消卡死的重复运行后仍不变。API 拿不到服务端的具体拦截理由;最可能是这个分支经历多次 rebase+force-push 后 PR 合并性计算缓存卡死(GitHub 已知行为类别)。
    3. 影响范围与严重程度:只影响这一个 PR 的最后「点合入」一步;master、其他 PR、任何用户均不受影响。程度 = 流程阻塞,非功能缺陷。
    4. 怎么修复的:推荐先用零成本探一下 UI(选项 A);不行就做 close+reopen(选项 B)——这是对该类缓存卡死成功率最高、代价最小的标准补救。
    5. 回归风险:A 无任何动作风险;B 有两个小风险——重开瞬间会重新触发一轮核心 CI(约 15 分钟,若再遇 win-22-2 磁盘满的基础设施抖动可 rerun)、平台镜像可能记一次短暂的 close 事件;全程不改任何代码,零回归面。C 只有时间成本。
    6. 是否破坏缓存:不涉及(不动项目内任何缓存/重试机制,只影响该 PR 对象的状态计算)。
    7. 是否改了设计方向:不涉及。
    8. 是否引入新配置:无。

    选项对比:

    选项 动作 成本 预期
    A 你打开 PR #3466 的 Checks 页:若必需项全绿且 Merge 按钮可用,直接合入 0 若是纯 API 侧滞后,到此结束
    B 我关闭并重开 #3466(评论/check 保留,PR 号不变),重置合并性计算 ~15min CI + 一次短暂 closed 窗口 大概率转 clean
    C 提 GitHub support 工单 小时~天级 兜底

    我的建议:先 A,按钮不可用就回我一个字,我立刻执行 B。代码层结论维持可合;第二步(archiveAfterDays 过期归档 + 自动化 GC)继续等你对第一步实际收益点头。

  12. ranxianglei commented on Oct 19, 2026

    @ranxianglei
    OwnerAuthor

    🤖 Powered by ework · qwen3.8-27b

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

    状态更新:第一步(CAS 引用计数清算 + 手工入口 + VACUUM)已由 #3860 实现(bili sessions ls/rm/prune + UnifiedStore.vacuum(),审核修复已推、待合并)。合并后本 issue 可收窄到第二步(archiveAfterDays 自动过期归档)。另:本 issue 验收里的「本机实测减重(index.db 637MB)」属于第二步的验证范围,#3860 不覆盖。与 #3860 互链。

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions