Repository navigation
Conversation
…dd migration tool - Allow storage.jsonWriter=off when backend is mysql - Add scripts/migrate-storage.ts to migrate SQLite sessions to MySQL/MariaDB
…ronous read facade Reverts the writerOff broadening from this PR's first commit: honoring storage.jsonWriter=off on the mysql backend loses every session at every process restart, because the mysql facade has no synchronous read path (UnifiedShadow.viewFor returns null and listSessionIds returns [] there), so with the envelope off both loadSync and boot enumeration find nothing. The P1 aspect is tracked in issue ranxianglei#4942; until a synchronous read facade (or an async boot pre-warm) lands, mysql full mode keeps writing envelopes and the config warns, exactly as before this PR.
…ls identities The hardcoded user_version == 7 gate rejected every current-gen index.db (v8 since ranxianglei#4390) and its retry hint was actively misleading — opening the store with this build bumps it to 8. Accept MIN_SOURCE_VERSION(7)..STORAGE_SCHEMA_VERSION and refuse unknown-newer versions instead. Backfill empty message identities on the target from CAS bytes using the exact formula of the mysql init backfill; without it every cross-save identity join on migrated rows misses. Also fixes the SessionRow|null type error in the parity section and closes the raw sqlite handle.
scripts/ was outside the tsconfig include, so a real TS2322 in migrate-storage.ts shipped invisible to CI. Including the directory also surfaced stale code in update-storage-corpus.ts: a Session import from a module that never exported it, StoredEntry literals predating the kernel CCR re-key (ranxianglei#4733), and non-wire "chat" protocol labels the committed golden fixtures deliberately carry. Fixed in place so the whole tree typechecks clean.
…ntract lane Hermetic gate tests (version refusal, missing-table refusal — both exit before any mysql contact, so they run against an unreachable DSN) always run; DSN-gated cases prove the full migration against a real MySQL: row count, content byte-length and read-back view parity, dry-run stopping after schema ensure, and v7 identity backfill landing on every row. Runs in the existing mysql-contract job, each case on a fresh target database.
(ai: vllm-qwen/qwen3.8-27b) 查重:不重复。 最接近的条目:#3020(已关闭 PR,sqlite-only 标签: pr + scope/storage + p3(功能/工具类、纯 opt-in;其中 p1 数据丢失面已单独立项 #4942)。 审核结论:首版不可按原样合并——已直接在你的分支上对齐重构按外部提交审查规则,我在你的分支上直接重构(additive commits,保留你的作者署名),已推送 核心功能为什么被回滚(P1)MySQL 上开
你的运行时验证证明了「写入会落到 MariaDB」,但没有覆盖「重启后能否读回」——断点正好在后半段。修复方向已立项 #4942(bug/p1/scope/storage):A 异步 boot 预热 + 热路径持有、B 本地同步读镜像、C 维持现状(近期推荐)。在该机制落地前,mysql full 模式必须继续写 envelope。 迁移脚本:保留并修好(首版对当前代库实际不可用)
顺手修的小问题(独立标注 commit)
新增测试
本地定向验证:整树 typecheck 绿;新套件 2 pass / 3 skip(本地无 DSN); 八问
行为变更披露(旧值→新值)
判定:首版不合。重构后剩余部分 = 加固过的迁移工具 + typecheck 覆盖 + 回归钉,自洽且零运行时影响——我的建议是工具部分可以先合(CI 绿即可),writerOff 功能等 #4942 拍板后另走。合并由你执行:#4936 |
|
(ai: vllm-qwen/qwen3.8-27b) Status note from the #4942 lane: the writerOff extension for mysql was reverted in d5a3950 (jsonWriter=off stays sqlite-only until mysql has a synchronous read facade). The gap is tracked as decision request #4942 — options A (async boot pre-warm + eviction hold) / B (local read mirror) / C (status quo); C is in effect right now, owner decision on direction pending. This PR's remaining diff (scripts/migrate-storage.ts + tests) is independent of that decision. Note: the branch currently conflicts with master (mergeable_state=blocked) — a rebase is needed before further review. |
…ss lines CI ran the v8 end-to-end case against real MySQL: the migration itself was fully green (row parity, content bytes, read-back view identical), only my assertion regex missed the colon in the "<table>: N rows ok" success line.
…anglei#1248 tripwire) The runner's SPAWN_RE tripwire requires every process-spawning suite to be registered in scripts/live-files.mjs or all shards fail at startup. The suite only spawns one-shot migrate-storage.ts children with no listening sockets, so the entry is tripwire-only like ranxianglei#3890's.
EMPTY is a MySQL reserved word: the post-migration verification query used "AS empty" and ER_PARSE_ERROR killed the v8 end-to-end case after the migration itself had passed. Renamed the alias to n_empty.
(ai: vllm-qwen/qwen3.8-27b) CI 已全绿,收工状态更新(head
|
# Conflicts: # .github/workflows/ci.yml # scripts/live-files.mjs
…on, ranxianglei#4936) The 3 red shards fail one master-level test - plugin-fork ranxianglei#5140 cold-restored non-retained parent returning 409 instead of 200 - which this storage/migration PR never touches. It surfaced because the branch had merged a stale master base (110 commits behind dcf7607); master itself tracks ranxianglei#5140 as a known cold-tail flake (b5385a7). Per CI-coordination policy, converge onto the sentinel-maintained ci-fixes branch rather than patching a master-level flake on this branch.
# Conflicts: # scripts/live-files.mjs
is resolved by ranxianglei#5213's async reload seam, which is on master; the gate stays sqlite-only as a separate decision (ranxianglei#4936 sync)
(ai: vllm-qwen/qwen3.8-27b) Conflict resolved and synced to current master. What I did this run:
八问
判定:冲突已解除(mergeable=true),分支 0 behind,CI 在新 head |
[ework] CI fix verified green ✓ |
(ai: vllm-qwen/qwen3.8-27b) No new sync needed — this "dirty" signal is a stale snapshot from before my previous push (same pattern as the earlier "behind" false alarms in this thread). Verified against live sources in this run:
No changes made this run; nothing to rebase or re-push. CI is running on the new head — its verdict (and any red, via the #4599 flow) is the next actionable event. 八问
判定:无动作可做的空转信号,已核实并留痕;等 CI 在新 head |
[bot] 🏷 (ai: vllm-qwen/qwen3.8-27b) Conclusion for this wake (full evidence in my previous comment): the repeated "dirty" blocker signal is a stale snapshot, not a real conflict — no action was needed and none was taken. Live-verified in this run:
Status: conflict resolved, branch in sync, CI running on the new head — its verdict is the next actionable event (any red goes through the #4599 coordination flow). Nothing else pending from this lane. |
[ework] CI fix verified green ✓ |
[bot] 🏷 (ai: vllm-qwen/qwen3.8-27b) Third "dirty" signal in ~20 min — again a stale/transient state, not a real conflict. Live-verified in this run, no action needed:
So the PR is conflict-free and CI-clean; it is ready for human review/merge. Nothing further for this lane unless a new real blocker appears. 八问
判定:空转信号,已核实并留痕;PR 现处于无冲突 + CI 全绿状态,等待人工 review/merge。 |
[ework] CI fix verified green ✓ |
1 similar comment
[ework] CI fix verified green ✓ |
PR 3: feat(storage): support disabling JSON envelope on MySQL backend and add migration tool
Problem / Background
When running Billion-Context with network storage backends like MySQL/MariaDB (
BILI_STORAGE_BACKEND=mysql), the server operates in unified full mode (storage.unified=full). However,src/persist.ts:508previously lockedjsonWriterOffexclusively to thesqlitebackend:If
storage.jsonWriter=offwas specified on a MySQL backend, it logged a warning and forced JSON files to continue being written to disk undershare/sessions/openai/*.json.In containerized, multi-instance, or cloud-hosted deployments where MariaDB is the authoritative single source of truth, perpetual double-writing to local JSON files causes:
Additionally, existing users transitioning from local SQLite installations to MySQL lacked an official, end-to-end verified migration utility.
Changes
src/persist.ts:jsonWriterOffcheck to allowbackendName === "sqlite" || backendName === "mysql"when operating infullmode.(sqlite or mysql).src/storage/shadow.ts:resolveJsonWriterOfffrom../knobs.ts.writerOffstatus (json envelopes off (writerOff enabled)vsJSON envelopes keep being written).scripts/migrate-storage.ts:openBackend("mysql", to).content,messages,blocks,dead_refs,refs,session_runs, andconversations.BLOBbuffers to UTF-8 strings before parameter handoff to avoidmysql2buffer serialization edge cases.Verification
storage.jsonWriterremains enabled by default (offis strictly opt-in).scripts/migrate-storage.tsagainst a live production database snapshot (33 sessions, 31,800+ content rows, 27,000+ messages).BILI_STORAGE_BACKEND=mysqlandBILI_STORAGE_JSON_WRITER=off. Verified multi-turn conversations persist cleanly into MariaDB tables with zero writes toshare/sessions/openai/.