Skip to content

fix(marketplace): heal missing sample data when rehydrating installed packages onto a new database#3421

Merged
os-zhuang merged 1 commit into
mainfrom
claude/eloquent-kare-177948
Jul 24, 2026
Merged

fix(marketplace): heal missing sample data when rehydrating installed packages onto a new database#3421
os-zhuang merged 1 commit into
mainfrom
claude/eloquent-kare-177948

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

问题

examples/app-showcaseobjectstack dev --ui --seed-admin 起在全新 SQLite 库上时,已安装的 marketplace 模板包(app.objectstack.hotcrm)完全没有业务种子数据:crm_opportunity / crm_account / crm_lead 等全部 0 行,executive_dashboard 所有 KPI 为 0,Sales Pipeline 看板 7 列全空。

根因

安装 ledger(<cwd>/.objectstack/installed-packages/*.json)锚定在项目目录,而数据库可以在它脚下被整个换掉(os dev --fresh 的临时库、删掉的 dev.db--database 切换)。重启时 MarketplaceInstallLocalPlugin.rehydrate() 会重新注册 manifest + syncSchemas() 建表,但刻意 seedNow:false 不重放种子(注释假设"装机时的行还在库里")。于是出现不对称:

  • config 声明的 app(showcase 自己)走 AppPlugin,单租户下每次 boot 都 inline 重放种子 → 新库有数据;
  • marketplace 安装的包 rehydrate 永不重放 → 新库上 app 可见、表存在、永远 0 行。

已在 worktree 复现(拷贝 ledger + 新库):安装产物本身带全 12 个数据集 162 条种子,安装当天 inline seed 正常 —— 问题只出在"换库后的 rehydrate"。

修复

rehydrate 后新增 maybeHealSampleData():当且仅当

  1. 缓存 manifest 确实带 data 种子数据集;
  2. 用户从未显式 purge(新增 sampleDataPurged ledger 标记,purge 端点落章、install/reseed 落行后清除);
  3. 单租户模式(多租户仍归 per-org replay 所有,数据集照旧合并进 seed-datasets 服务);
  4. 每个被种对象都是空表 —— 任何一行幸存都视为数据仍在,完全不动库;

才以 upsert + multiPass 重放种子。因此对重启幂等,且永远不会覆盖用户对 demo 行的编辑。

顺手修正:install 的 seed 全部 skipped(行已在库,如对着有数据的库重装)时,withSampleData 现在如实置 true,不再在有数据的库上留着 false 假装没有样例数据。

验证

  • 新增 7 个回归用例(marketplace-install-local-heal.test.ts):空库愈合+标志翻转、任一对象有行即跳过、purge 后重启不复活(经真实端点端到端)、多租户跳过、0 行落地保持 false 并大声告警、all-skipped install 标志修正;包内 62 测试全绿。
  • 真机验证(worktree showcase + 真实 hotcrm 产物 + 新库):boot 后 REST 计数 61/5/21/38/4 全部到位,executive_dashboard KPI(378,366 / 5 / 5 / 21)与 Sales Pipeline 看板(51 条记录分列)在浏览器确认;再次重启行数与 updated_at 逐字节不变(幂等)。

顺带发现(不在本 PR 范围)

marketplace 包种子的 lookup/master_detail 引用自装机第一天起就未解析成 id(crm_contact.crm_account 列存的是 "Acme Corporation" 字符串)——crm_contactsharingModel: controlled_by_parent 的 RLS join 悬空而对所有人(含平台管理员)整表不可见。疑似 SeedLoader 引用图只认 metadata 服务、不认 marketplace 注册进 objectql registry 的对象定义。已另立任务跟进。

🤖 Generated with Claude Code

… packages onto a new database

The install ledger (.objectstack/installed-packages/) is anchored to the
project directory while the database can be swapped out from under it
(os dev --fresh, a deleted dev.db, a --database switch). Rehydrate
deliberately never re-seeds, which left a rehydrated marketplace package
permanently empty on a new database: app in the switcher, tables created,
zero rows — the "HotCRM installed but every KPI is 0" state.

Rehydrate now replays the bundled seed datasets iff the manifest bundles
them, they were never explicitly purged (new sampleDataPurged ledger
marker), the runtime is single-tenant, and EVERY seeded object is empty —
one surviving row anywhere leaves the database untouched, so the heal is
idempotent and can never revert user edits on restart.

Install now also marks withSampleData=true on an all-skipped seed run
(rows already present), instead of leaving the flag false over a seeded
database.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 23, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jul 23, 2026 4:32pm

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

No hand-written docs reference the 1 changed package(s). ✅

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

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant