# 存储收尾第二波:九项一次清账(正确性 + GC + 姿态) 承接 #3818/#3819(六修+缺省翻 full)。那一波明确"不在本 PR"的三类遗留,现在一次清完,**清完才发下一版**。每项独立可回滚,统一一个 PR 交付。 ## A. 正确性类 ### 1. #3841 — full 模式重启后被收割块复活 **选型:schema v6 `sessions.orphans_json` 列(候选 a)**。理由:索引自足(不依赖信封兜底)、additive NULLable 迁移零风险(既有的列探测迁移模式)、verify 采样的 digest 口径自然对齐(expect/got 同含孤儿内容)。b)块表 discriminator 动查询面大;c)加载期探测治标不治本(行仍是错的)。 - 记账:reap 形状会话保存时,把 `blockContents` 中不在 `state.blocks` 的孤儿内容写入 `orphans_json`; - 重建:`viewFor` 把孤儿内容并入 `blockContents`,**不**进 `state.blocks`(reap 意图跨重启保真); - 存量行 NULL = 旧行为(升级前从未 reap 过的会话不受影响); - 验收:reap → 重启 → 块不复活、孤儿内容可 decompress、信封不再被污染(跨重启路径打桩,现有 stake-8 只盖冷读)。 ### 2. #3798 — 增量 resync 冷重建丢共享历史 **修法:canonical 行指针持久化**。 - `session_ext` 新键 `inc:canonical-ptrs`:每次 raw ingest 后记录**当前 canonical 消息的有序 audit 行指针**(seq 数组); - `readCanonicalFromStore` 冷读改按指针取行(不再用 base-seq 切计数——remapPlanToAbsolute 对同 hash 复用旧行,共享前缀会落在切点之前); - 折叠/信封-only 保存必须保留最后指针清单;指针缺失/畸形 → 返回 bad 逼客户端 resync(不供部分历史); - 旧纪元(无指针)= 兼容路径维持现行为; - 验收:同史重发/共享前缀编辑/冷缓存 delta/折叠后保存/追加,shadow+full 双模式回归。 ### 3. #3788 / #3823 — win32 legacy-only 复测 构建装 Windows VM(node 22 → 内置 node:sqlite 直通 full);Node<22.5 的下载路径已有镜像回退+升级提示(见 #3489 核实),单测覆盖;回评请报告者 ≥0.1.204 复测。 ## B. 资源回收类(GC) ### 4. #3463 — index.db 只增不删:归档 + GC 入口 + 收缩 现状核实:content 表 **refcount 已在**(schema v5),deleteSession 已联动清算+零引用回收(store.ts:812-851)。真正缺的是**活会话的过期归档**(archiveAfterDays 拍过板从未落地)与**收缩**(freelist 不还给 OS)。 - `storage.archiveAfterDays`(文件键+env,默认 365,0=关):超期会话归档——内容行释放、会话行留墓碑(可按 id 找回)、web 列表默认不显示; - 手动入口 `POST /__bili/storage/gc`(admin 面):跑一遍归档扫描 + 零引用清扫 + `PRAGMA incremental_vacuum`(auto_vacuum=INCREMENTAL 建库即设;存量库首次需全量 VACUUM,加 `?vacuum=full` 显式触发并提示 2× 磁盘瞬时); - 验收:单测(归档墓碑/共享行存活/找回路径)+ 本机 index.db 实测数字写进 PR。 ### 5. #3671 — 压缩原文永久驻留 本 PR 落地**归档联动释放**(归档会话的 blockContents 随内容行释放,摘要保留在墓碑)。单点依赖风险(插件失效=70MB 原文重放)的结构性修复是快照渲染(#3756,已合灰度 0%)——在 issue 回帖明确该归因,不在这重复造。 ### 6. #3762 — 媒体按内容寻址(图片跨会话去重) - CoreMessage 的媒体 sidecar(imageBase64)拆出:媒体字节进 content CAS(sha256 寻址,复用 refcount),消息 JSON 存 hash 引用; - **lazy 迁移**:存量行内嵌字节照读,新写才拆分(无一次性迁移窗口); - 读侧 join 透明还原,wire round-trip 金桩逐字节不回归;媒体指纹与 #3751 的 id 指纹同源(一套哈希)。 ## C. 姿态类 ### 7. #3723 — dsh 会话无限涨:亲自压缩转正 `BILI_DSH_AUTHORED_COMPACTION` **缺省开**(env 显式 `0` 可关),加文件键 `dsh.authoredCompaction`;本机 lane 狗粮先行;回帖 #3723。 ### 8. #3489 — 多镜像回退:核实后关 master 已有 npmmirror 链(engine-bootstrap.ts:284-292)+ 升级 Node 提示(:322,#3788 诊断输出可证)。核实无缺项 → 关闭并回链。 ### 9. #3633 — 多实例姿态文档 docs 落一段:单实例单卷(RWO)、NFS/网络卷禁止(WAL 需要字节范围锁)、replicas 端点不是集群、扩展=每实例一卷。 --- **不在本 PR**:GC 自动调度周期(手动入口先验证收益)、blockContents TTL(等归档联动实测)、#3354/#3765 族。 **验收总闸**:统一验证 harness(verify2964)+ 全 storage 家族绿 + 金桩零漂移(媒体 CAS lazy 模式不碰存量字节)+ CI full。
Activity
[-]存储收尾第二波:九项一次清账(正确性 #3841/#3798 + GC #3463/#3671/#3762 + 姿态 #3723/#3489/#3633/#3788)[/-][+]Storage cleanup wave 2: Batch-clearing nine items (Correctness #3841/#3798 + GC #3463/#3671/#3762 + Posture #3723/#3489/ | 存储收尾第二波:九项一次清账(正确性 #3841/#3798 + GC #3463/#3671/#3762 + 姿态 #3723/#3489/#3633/#3788)[/+]ranxianglei commentedon Oct 20, 2026
(ai: vllm-qwen/qwen3.8-27b)
查重: 不重复。 open/closed 全量检索(关键词: orphans/resurrect、canonical resync、archiveAfterDays/vacuum/GC、media CAS、authoredCompaction、镜像回退)无并行 issue/PR;九个子项各自也均无在途修复。本 issue 是 #3818/#3819 的收尾批次,统一一个 PR 交付。
标签: bug + dsh + scope/storage + p1(含正确性类数据完整性缺陷——#3841 收割块跨重启复活、#3798 冷重建丢共享历史,按 owner 修订属 p1 面;dsh 会话无限涨为第 7 项)。
接单计划(按依赖排序,每项独立可回滚):
sessions.orphans_json(候选 a),reap 记账 → viewFor 重建合并孤儿内容不进 state.blocks;session_ext["inc:canonical-ptrs"]持久化 canonical 行指针,冷读按指针取行,缺失/畸形返回 bad 逼 resync;storage.archiveAfterDays(默认 365,0=关)+POST /__bili/storage/gc+ incremental_vacuum;BILI_DSH_AUTHORED_COMPACTION缺省开 + 文件键dsh.authoredCompaction;验收总闸:verify2964 harness + storage 家族绿 + 金桩零漂移 + CI full。开始动手,进展回帖。
ranxianglei commentedon Oct 20, 2026
PR #3911 交付九项:GC/归档(#3463)、reap 台账(schema v6,#3841)、媒体 CAS(schema v7,#3762)、增量指针(#3798)、dsh 代压缩默认开(#3723)、README 多实例章节(#3633)。#3788/#3823 请报告者在 ≥本版本复测(引擎镜像回退已落),#3489 核实关闭,#3671 归因快照渲染。测试:4 个新套件 10 测试打桩先行,家族全绿。
ranxianglei commentedon Oct 20, 2026
(ai: vllm-qwen/qwen3.8-27b)
收到——#3911 已覆盖本 issue 全部九项,我停止并行实现(本地只做到 A1/orphans_json 一半,弃用不推分支,设计选型与 PR 一致可作交叉印证),转为独立审核 #3911:按规范走方向关(对原 issue 九项逐条核验收)、回归关(既有行为清点)、代码关、测试有效性关、diff 整洁度关,结论用八问回帖。先拉 PR head 通读全量 diff。
fix(storage): release media refs on the stale-row sweep (#3762 review, …
fix(admin): accept ?vacuum=full on /__bili/storage/gc per documented …
docs(storage): correct stale v6 orphan-journal comment (#3841 review, #…
ranxianglei commentedon Oct 20, 2026
(ai: vllm-qwen/qwen3.8-27b)
PR #3911 独立审核结论(审的是最终 head,含我补的 3 个 commit)
方向关(①):九项逐条对过 issue 规格——A1 orphans_json 候选 a、A2 canonical-ptrs 指针化、B4 归档+GC+收缩、B5 归档联动释放、B6 媒体 CAS lazy 迁移、C7 缺省翻开+文件键、C8/C9 核实关单+文档,全部按你拍板的方向落地,无跑偏;#3671 的结构性修复正确归因 #3756 没有重复造。
回归关(②):审过的既有行为清单——孤儿守卫语义(从「拒写」变「记账后写」,driftedSessions 兜底保留)、verify digest 口径(expect/got 经 completeBlockContents 对称性验证成立)、stale-row sweep 引用计数(发现泄漏,已修,见下)、turn-lock 409 合同(现有 incremental-lane 测试钉住,reorder 后语义不变)、lazy 迁移不碰存量字节(golden-storage-render 零漂移实测通过)、writerOff 安全阀路径、deleteSession/archiveSession 引用纪律。发现的回归:1 处(sweep 媒体泄漏),已当场修复。
代码关(③)+ 测试有效性(④):4 个新套件是真测试(直查表证明存储层拆分、refcount 2→1→0、跨重启不复活、真实 HTTP e2e 打桩同史重发杀手形状);4 个新测试我先本地复跑全绿。diff 干净(25 文件,无 version/lockfile/无关改动)。
审核中发现并直接修掉的 3 处(已 push 到 PR 分支,e23d9c70b..7dc3bbe):
dd98738abstale-row sweep 泄漏媒体 CAS 引用(store.ts):full-path sweep 删消息行时只 release content_hash,不清 message_media 映射也不 release media hash → 图片字节永久驻留、引用计数只增不减,与你自己写的「Same image bytes stored once per conversation/message copy — split media payloads into a content-addressed store (follow-up to #3751/#3748) #3762 refcount release on delete/archive」合同矛盾(deleteSession/archiveSession 都清了,唯独 sweep 漏)。已补 release+清理,并加回归测试(无此修复红、有则绿,RED/GREEN 双证)。770e407ef?vacuum=full文档与实现不符(admin.ts):issue 规格和 CONFIGURATION.md 都写?vacuum=full,但路由是req.url === "/__bili/storage/gc"精确匹配且 vacuum 只读 body——按文档用会直接 404。已让路由接受查询串(query 优先于 body),行为不变、文档归真。7dc3bbe4aschema v6 迁移注释陈旧(「never gutted into the index」与新设计矛盾),改对。留给你的两个决策点(未擅动):
status='archived'且注释明说「web list keeps showing it」。二者必居其一:要么按规格隐藏(默认列表排除 archived,restore 入口不受影响),要么认下「墓碑可见=可找回」的设计并在 issue 里改口。我倾向隐藏(归档物不该占列表心智,找回走 restore 端点)。其余信息项:F4 畸形指针 PR 选「回落 legacy」而非 issue 写的「返回 bad」——最坏后果是一次强制 409 resync 自愈,不会供错分支,判定可接受;F7 ingestSession upsert 会把 archived 墓碑隐式激活回 active(杂散流量复活会话),倾向可用优先,确认一下意图即可。
本地定向验证(非全量,全量以 CI 为准):pr-3911 head 上 4 个新套件 10/10;改动面家族(storage-unified/ext/watermark/full-flip/json-writer-off/incremental-lane/dsh-authored-compaction/golden-storage-render)84 pass / 1 skip / 0 fail。CI 已在 7dc3bbe 上跑(static-gates 已过,test lanes 进行中)。
结构化八问
storage.archiveAfterDays(文件键+envBILI_STORAGE_ARCHIVE_AFTER_DAYS,默认 365,0=关)、dsh.authoredCompaction(文件 boolean;缺省行为变更:off→on,env 显式0可关,CHANGELOG 已披露)、新增管理端点POST /__bili/storage/gc与/__bili/storage/restore(loopback-only)。判定:可合(等 CI test lanes 绿;合并动作在你)。两个决策点(F6/F3)不阻塞合并,可在下个 follow-up 处理;#3788 已回帖请报告者 ≥v0.1.204 复测,#3489 你已核实关闭,#3723/#3671 已回帖。
Merge pull request #3911 from ranxianglei/2026-10-20_storage-wrapup-2
storage wrap-up: GC/archive + reap journal + media CAS + incremental …