Skip to content

feat(runtime): the standalone default datasource is a declaration, connected through the one datasource path (#3826) - #3869

Merged
os-zhuang merged 1 commit into
mainfrom
claude/explicit-datasource-connection-fallback-5b83d0
Jul 28, 2026
Merged

feat(runtime): the standalone default datasource is a declaration, connected through the one datasource path (#3826)#3869
os-zhuang merged 1 commit into
mainfrom
claude/explicit-datasource-connection-fallback-5b83d0

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

#3826 讨论中的方案 B 落地(部分完成 —— 见末尾余项;issue 保持 open)。

改动

createStandaloneStack 不再构建 driver,而是产出 default 的 datasource 定义(URL→config 翻译和 mkdir 仍归 host),由新的 DefaultDatasourcePlugin 在启动期通过共享的 DatasourceConnectionService 连接 —— 同一个 factory、同一份失败判决(bootCritical ⇒ D5 fail-fast,新增的第三条判据)、同一个 OS_ALLOW_DRIVER_CONNECT_FAILURE 逃生阀、同一份留存状态(主库终于在 Setup → Datasources 显示真实 status,#3827 补全)。

配套:

  • sqlite-wasm 进入共享 factory(sqlite-wasm / wasm-sqlite),消灭最后一处 bespoke 构造。
  • default 成为 host 保留名:app bundle 声明即在装载时被拒(AppPlugin),runtime-admin 创建同样拒绝 —— 此前是未定义行为(shadow + 静默改道)。
  • connect(record, { asDefault: true }):driver 保留自然名(路由走引擎的 default fallback,从不经 drivers.get('default')),以 isDefault 注册,幂等守卫走新增的 engine.getDefaultDriverName()
  • default 刻意不过 connect policy(与旧 boot 逐字节一致 —— 那道门为可选/外部 datasource 而设;测试钉死了「deny-all policy 不能挡住主库」)。
  • ObjectQLEngine.init()不改:它对已连接的 default 再 connect 一次(五种开源 driver 的 connect() 均幂等,逐一核实过),恰好保留 ObjectQLEngine.init() 吞掉 driver 连接失败:连不上数据库的服务器照常启动,driver 的启动期致命错误被降级成运行时报错 #3741 要的启动校验角色。
  • driver.<name> kernel service 仍然注册 —— os migratefindSqlDriver 和 serve 的 storage 探测靠它;ObjectQL 发现循环对同名 driver 是 skip-if-present,no-op。

冒烟测试抓住并修掉的两个真实回归

诚实记录,这两个都是单元/集成测试抓住、真机启动抓住的:

  1. 启动顺序不是注册顺序。 kernel 的 init/start 都按依赖拓扑排序(resolveDependencies),serve 全量 boot 里 ObjectQL 被更早注册的服务插件的依赖边提前,我的 plugin 的 start 排到了 schema sync 之后 —— 服务器起得干干净净,然后 dev:crm --fresh 只建出 10 张表(对照 main:71 张),所有业务对象查询报 no such table。修法:connect 挪进 init()(Phase 1 全部完成才进 Phase 2,任何拓扑下都先于 sync),并声明对 ObjectQL 的硬依赖(保证 'data' service 先注册)。start() 再经共享服务 replay 一次(幂等命中 already-registered),让判决落进 admin 列表读取的状态里。
  2. os migratedriver.* service 定位 SQL driver —— 新路径起初没注册它,CLI 集成测试红。补上注册,全部消费方(schema-migrate、serve storage 探测、发现循环)保持兼容。

另:serve 的 hasDriver 探测教会识别 DefaultDatasourcePlugin,避免 config-load fallback 再建一份重复 pool(第一次冒烟抓到的双构造)。

验证

  • 真机对照实验:dev:crm --fresh 在本分支与未修改 main 上各跑一次 —— 两边同为 71 张表、零 no such table;认证登录 + GET /api/v1/data/crm_account 返回 seed 数据;artifact-serve 路径(quickstart/生产形态)boot 后 default 状态 ok、无重复 driver。
  • runtime 702 passed(+9 新集成用例:端到端 boot/默认注册/admin 状态/fail-fast/degraded/policy 不挡主库/保留名拒绝)、service-datasource 124(+factory wasm 用例)、objectql 1151、cli 738,全绿。
  • pnpm build 全量、examples typecheck、ESLint、changeset 门禁全绿。
  • degraded-boot-parity.test.ts 继续全绿 —— 两条 connect 路径的运维契约(fail-fast 默认、旗标解析逐值一致、stderr banner)未漂移。

ADR 与文档

  • ADR-0062 D1 增补 Resolution 段:定义即输入的解法、bootCritical、自然名 + asDefault、分层反转为何未发生(runtime host 编排,ObjectQL 无感知)、以及余项
  • drivers.mdx 补一段declared default 的说明与保留名规则。

余项(#3826 保持 open)

CLI serve 的 config-load fallback(createStorageDriver + DriverPlugin):它还承载共享 factory 不支持的 mysql/turso,且 telemetry sibling-datasource 的供给耦合在它的解析结果上 —— 是剩下的第二构造点,连同 cloud-stack 的自组路径一起留在 issue 里。在它们收敛前,parity test 继续作为漂移守卫。


Generated by Claude Code

…nnected through the one datasource path (#3826)
ADR-0062 D1 asked for exactly one "definition → live driver" path. Construction
converged earlier; connect + failure verdict did not — the standalone `default`
was pre-built and smuggled into the engine as a `driver.*` kernel service, so
"what if it cannot connect" lived in `ObjectQLEngine.init()`, a second
implementation of the policy `DatasourceConnectionService` owns for every other
datasource. #3741#3758 showed what two copies cost.
- `createStandaloneStack` emits a datasource DEFINITION; the new
`DefaultDatasourcePlugin` connects it through the shared connection service.
The connect happens in init() with a hard dependency on ObjectQLPlugin: the
kernel resolves BOTH phases from the dependency graph, so list position
proves nothing — the first cut connected in start() and a serve boot hoisted
ObjectQL ahead of it, shipping a server with no tables (caught by the dev:crm
smoke, fixed by phase separation: all inits precede all starts).
- `bootCritical` on ConnectableDatasource: a third D5 fail-fast cause — the
host declares the platform cannot run without it; shares
OS_ALLOW_DRIVER_CONNECT_FAILURE and the DEGRADED BOOT banner. The default
deliberately bypasses the connect policy (byte-for-byte with the old boot;
that gate exists for optional datasources).
- `connect(record, { asDefault: true })`: registers under the driver's natural
name with isDefault, guarded by engine.getDefaultDriverName() idempotency.
start() replays through the shared service so the primary DB shows a real
status in Setup → Datasources (#3827).
- `sqlite-wasm` joined the shared driver factory (last bespoke construction).
- `default` is host-reserved: rejected in app bundles at load (AppPlugin) and
in runtime-admin create.
- The `driver.<name>` kernel service is still registered (os migrate's
findSqlDriver and serve's storage detection read it); ObjectQL's discovery
loop no-ops on it via the engine's skip-if-present guard.
- serve's hasDriver detection counts DefaultDatasourcePlugin as a driver
provider so the storage-driver fallback doesn't build a duplicate pool. The
config-load fallback (createStorageDriver, mysql/turso, telemetry coupling)
remains a tracked second site in #3826.
- ObjectQLEngine.init() unchanged: it re-connects the already-connected default
(all open-core drivers' connect() is idempotent) — the #3741 verification
role D1 leaves it.
Verified end to end: dev:crm --fresh creates the same 71 tables as unmodified
main (the broken intermediate produced 10), zero "no such table", authenticated
data reads serve seeded rows, and the artifact-serve path boots with `default`
status 'ok' and no duplicate driver.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TQVM3A9Yd6N2eZS8ZcdnMk
@vercel

vercelBot commented Jul 28, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectstackIgnoredIgnoredJul 28, 2026 1:06pm

Request Review

@github-actionsgithub-actionsBot added size/l documentation Improvements or additions to documentation tests tooling labels Jul 28, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 4 package(s): @objectstack/cli, @objectstack/objectql, @objectstack/runtime, packages/services.

42 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/skills-reference.mdx(via packages/cli)
  • content/docs/api/client-sdk.mdx(via @objectstack/cli, packages/runtime)
  • content/docs/api/data-flow.mdx(via @objectstack/cli)
  • content/docs/api/environment-routing.mdx(via @objectstack/cli)
  • content/docs/api/error-catalog.mdx(via @objectstack/cli)
  • content/docs/api/index.mdx(via @objectstack/runtime)
  • content/docs/api/wire-format.mdx(via @objectstack/runtime)
  • content/docs/automation/hook-bodies.mdx(via packages/cli, @objectstack/runtime)
  • content/docs/automation/webhooks.mdx(via packages/services)
  • content/docs/concepts/metadata-lifecycle.mdx(via @objectstack/objectql)
  • content/docs/concepts/north-star.mdx(via packages/runtime)
  • content/docs/data-modeling/drivers.mdx(via @objectstack/runtime)
  • content/docs/data-modeling/formulas.mdx(via packages/objectql)
  • content/docs/deployment/backup-restore.mdx(via @objectstack/cli)
  • content/docs/deployment/cli.mdx(via @objectstack/cli)
  • content/docs/deployment/index.mdx(via @objectstack/runtime)
  • content/docs/deployment/migration-from-objectql.mdx(via @objectstack/objectql)
  • content/docs/deployment/production-readiness.mdx(via @objectstack/runtime)
  • content/docs/deployment/self-hosting.mdx(via @objectstack/cli)
  • content/docs/deployment/single-project-mode.mdx(via @objectstack/runtime)
  • content/docs/deployment/vercel.mdx(via @objectstack/objectql, @objectstack/runtime)
  • content/docs/getting-started/your-first-project.mdx(via @objectstack/cli, @objectstack/runtime)
  • content/docs/kernel/runtime-services/audit-service.mdx(via packages/services)
  • content/docs/kernel/runtime-services/data-service.mdx(via packages/cli)
  • content/docs/kernel/runtime-services/index.mdx(via packages/cli, packages/services)
  • content/docs/kernel/runtime-services/settings-service.mdx(via packages/services)
  • content/docs/kernel/services-checklist.mdx(via @objectstack/objectql)
  • content/docs/kernel/services.mdx(via @objectstack/objectql)
  • content/docs/permissions/authentication.mdx(via @objectstack/cli, @objectstack/objectql, @objectstack/runtime)
  • content/docs/permissions/authorization.mdx(via packages/runtime)
  • content/docs/plugins/index.mdx(via @objectstack/objectql)
  • content/docs/plugins/packages.mdx(via @objectstack/cli, @objectstack/objectql, @objectstack/runtime, packages/services)
  • content/docs/protocol/kernel/http-protocol.mdx(via @objectstack/runtime)
  • content/docs/protocol/kernel/i18n-standard.mdx(via packages/services)
  • content/docs/protocol/kernel/index.mdx(via @objectstack/objectql, @objectstack/runtime)
  • content/docs/protocol/kernel/lifecycle.mdx(via @objectstack/runtime)
  • content/docs/protocol/kernel/plugin-spec.mdx(via @objectstack/cli)
  • content/docs/protocol/kernel/realtime-protocol.mdx(via @objectstack/cli)
  • content/docs/protocol/objectql/state-machine.mdx(via @objectstack/objectql)
  • content/docs/releases/implementation-status.mdx(via @objectstack/cli, @objectstack/objectql, @objectstack/runtime)
  • content/docs/releases/v16.mdx(via @objectstack/cli)
  • content/docs/releases/v9.mdx(via @objectstack/objectql)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

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

Labels

documentationImprovements or additions to documentationsize/lteststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@os-zhuang@claude