Skip to content

driver-turso 住在闭源 cloud 仓,却是开源 runtime 点名偏好的默认 driver — 建议把核心迁回本仓 #4645

Description

@os-zhuang

@objectstack/driver-turso(现居 objectstack-ai/cloudpublishConfig: restricted
目标路径packages/drivers/driver-turso packages/drivers/ 目录;现有四个 driver 与它同批迁入——见「推进顺序」)
发现于:核对 #4484findStream enforce-or-remove)时,发现该 remove 的工作范围只覆盖本仓三个 driver,cloud 侧 4 处实现完全在盲区——见 #4484 的补充评论。
核实基线objectstack @ 0a936eacloud @ 0070d51(pin 在 ad5fe25
前置项#4646 / PR #4648(gate 的零发现)— ✅ 已合入

⏸️ 排期:等 maintainer 通知后再动

四条决策点已全部裁定(见文末),方案完整可实施,但实施时机由 maintainer 掌握:当前有多个 agent 在并行改 packages/plugins/driver-*#4484 正在改三个 driver 的 findStream),此时任何对这些包的路径改动都会与进行中的开发撞车。

待那批开发收尾、maintainer 通知后,一次性统一迁移——不做分批。别的 agent 请勿抢跑这个 issue。

摘要

TursoDriverextends SqlDriver 的方式跨仓库继承本仓的类,住在闭源 cloud 仓;而本仓的 runtime 已经把 turso 当一等公民——环境 provisioning 的默认偏好顺序第一位就是它。结果是:开源侧的代码路径引用着一个自己仓里既测不到、也 grep 不到的 driver,而闭源侧只能在每次 pin bump 时追赶父类的重构。

证据 0:它本来就在本仓,而且本仓至今为它保留着扩展点

CHANGELOG.md:2052-2060 记录了它的到来:

@objectstack/driver-turso plugin — Migrated and standardized the Turso/libSQL driver from @objectql/driver-turso into packages/plugins/driver-turso/. The driver extends SqlDriver

同一个 release 还做了这件事(CHANGELOG.md:2066-2073):

@objectstack/driver-sql — Protected extensibility — Changed private to protected for all internal properties and methods(knexconfigapplyFiltersformatInput/formatOutputintrospect* 等约 25 个成员)。Enables clean subclassing for driver variants (Turso, D1, etc.)

也就是说:本仓的 SqlDriver 至今维持着一整片 protected 扩展面,专为一个已经不在本仓的子类而存在——而这份扩展契约在本仓没有任何子类去行使它,等于一个无人验证的 API surface。这不是「要不要迁进来」的问题,是「它被迁出去了,接口债留在了这里」。

证据 1:开源侧已把 turso 当默认

位置 内容
packages/runtime/src/http-dispatcher.ts:1324 provisioning 偏好顺序:tursomemory → 任意其他已注册 driver
packages/runtime/src/http-dispatcher.ts:1299 POST /cloud/environmentsdriver 参数示例即 memory | turso
packages/runtime/src/default-datasource-plugin.ts:70 提到 distribution 的 turso
packages/objectql/src/engine.ts:3133 turso 专属的瞬时 fetch failed 重试
packages/objectql/src/plugin.ts:54, 88, 144 三处以 Neon/Turso 这类 latency-bound 远程 driver 为前提的设计推理(含 cold start 不被 sync 打死)

本仓有 turso 专属的容错逻辑和调度偏好,却没有 turso 的代码和测试。

证据 2:闭源侧在持续追赶父类

cloudpackages/driver-turso 最近 5 个提交里 3 个是在追本仓 SqlDriver 的内部变化

0352d3c fix(driver-turso): remote 模式的 filter 列也读进驱动的存储形态 (#937) (#1003)
eca7f7e fix(driver-turso): remote 模式的写入与 comparand 接回 SqlDriver 的 temporal seam (#937) (#942)
6d1ab28 test(driver-turso): 接入 temporal conformance 矩阵——canonical + 遗留存储四条扫描 (framework#4191) (#938)

耦合面不是「用了个接口」而是继承turso-driver.ts:166),且 find / findOne / findStream / create / update 全部带 override。父类每次重构,子类都可能静默坏掉,只能在 bump SHA 时才发现

节奏差放大了这一点:本仓最近 50 个提交跨约 11 小时;cloud 的 50 个提交跨约 2.7 天。

证据 3:仓库级 gate 与清扫物理上看不见它

scripts/check-driver-conformance.mjs 的 scope 注释写得很清楚:

packages/plugins/driver-* — discovered from disk, never listed here, so a new driver package is in scope the moment it exists

这正是迁回的直接收益:turso 落盘即入矩阵,filter 组合语义(#3774)、temporal 存储形态(ADR-0053)、确定性分页读(#4363)三套 case-set 自动 held 住它,不再靠 cloud 侧手工「接入 conformance 矩阵」(6d1ab28 就是这么补的)。

同理,#4484 那种「全仓 grep + 删实现 + 删桩」的 ADR-0049 清扫,今天必然漏掉 cloud 的 4 处实现。这类清扫是本仓常规动作,每一次都有同样的漏网风险

拆分方案

cloud/packages/driver-turso 共 4,824 行。

迁到 packages/drivers/driver-turso(~4,162 行)

  • turso-driver.ts(896)— TursoDriver extends SqlDriver,迁后变成同仓继承,父类重构立刻可见,protected 扩展面终于有子类验证
  • remote-transport.ts(961)— 纯 @libsql/client 走 HTTP/WebSocket,无任何平台机密;文件头本来就是 Apache-2.0
  • index.ts(95)、libsql-sqlite-stub.testkit.ts(87)
  • 测试:turso-driver.test.ts(1,135)、spec/turso*.{test,zod}.tsturso-{,remote-}temporal-conformance.test.ts(591)、date-bucket-parity.test.ts(135)、remote-*.test.ts(262)

留在 cloud(662 行 + service-cloud 一处)

  • multi-tenant.ts(289)+ multi-tenant.test.ts(242)— 按租户路由、{tenant} URL 模板、group token、TTL 缓存
  • vector-poc.test.ts(131)— 已核实完全独立:直连 @libsql/clientcreateClient,不 import TursoDriver;驱动四个源文件里 vector / embedding / F32_BLOB 零命中。留下来不需要从驱动里切任何东西。
  • service-cloud/src/control-plane-proxy-driver.ts — 控制面 org 注入

cloud 随后按既有的 link: + .objectstack-sha pin 消费开源版 driver;multi-tenant.ts 只 import 公开的 TursoDriver

迁完后 cloud 侧 driver-turso 包的收尾(建议,非阻塞):它将只剩一个多租户路由器和一个 vector PoC,已经不是一个 driver。两件小事值得顺手做:把包名/目录改成名副其实的(如 tenant-router),以及把 vector-poc.test.ts 挪进 packages/knowledge-turso——该文件 docstring 写明它的目的就是 "confirm before building knowledge-turso",那才是它的归属。

目录重组:packages/plugins/driver-*packages/drivers/*

五个 driver(现有 driver-memorydriver-mongodbdriver-sqldriver-sqlite-wasm + 从 cloud 迁入的 driver-turso同批落入 packages/drivers/,让 driver 与 plugin 在目录上分开。

收纳范围(已裁定)packages/drivers/ 只收 IDataDriver 实现knowledge-*(本仓 2 个 + cloud 的 knowledge-turso)、embedder-* 留在 packages/plugins/。这与 check-driver-conformance.mjs 的 scope 定义一致——该脚本已明确把「非 driver 的 case-set 消费者」排除在外,目录边界与 gate 边界因此重合,不产生第二套判断标准。

改名的影响面(已实测)

本仓

  • pnpm-workspace.yaml — 增加 packages/drivers/* glob
  • scripts/check-driver-conformance.mjs:70DRIVERS_DIRtest(drivers): a conformance run that discovers zero drivers is a failure, not an OK (#4646) #4648 已把 self-test 里的 driver-sql / >= 3 硬编码消除,现在只剩这一处常量要改)
  • .github/workflows/ci.yml:866 — 遍历 packages/triggers/* packages/services/* packages/plugins/* 的循环
  • .github/workflows/lint.yml:424 — 构建嵌套包的说明与逻辑
  • 各 driver package.jsonrepository.directory
  • packages/spec/liveness/*.json 的 evidence 路径field.jsonobject.jsonquery.json 共 11 处指向 packages/plugins/driver-sql/...)——ADR-0087 registries,路径失效即证据链断裂
  • 文档:README.md:287-289ARCHITECTURE.md:250content/docs/plugins/packages.mdx(4 处)、content/docs/protocol/objectql/{index,query-syntax}.mdxexamples/app-crm/README.md
  • pnpm-lock.yaml 重生

cloud 仓(跨仓,会断)

3 个 package.json 共 6 条 link:../../../objectstack/packages/plugins/driver-* 指向物理路径,目录一动全部失效:

  • packages/objectos-runtime/package.json:32,33,53(memory / sql / mongodb)
  • packages/driver-turso/package.json:34(sql)
  • packages/service-cloud/package.json:27,28,29(memory / mongodb / sql)

外加 lockfile 里十余条同路径 specifier。必须与一次 bump-objectstack 同批推进,否则 pin 前移时 cloud 直接装不上。

这里有个值得记下的递归:目录重组本身正好踩中它要解决的那个跨仓盲区。本仓改目录的 PR 在自己仓 CI 全绿(cloud 的 link: 路径不在本仓任何检查的视野里),破坏只在 cloud 下次 bump 时出现——和 #4484 一模一样的形状。

推进顺序

  1. 修 gate 的零发现check-driver-conformance 的 audit 路径对「发现零个 driver」报 OK — 零发现该是失败,且唯一的守卫硬编码了 driver-sql #4646 / PR test(drivers): a conformance run that discovers zero drivers is a failure, not an OK (#4646) #4648,已合入 main
  2. ⏸️ 等窗口 — 待进行中的 agent 批次收尾(含 IDataDriver.findStream 没有任何调用方,两个 driver 的实现还正好做了它承诺要避免的事(ADR-0049 enforce-or-remove) #4484 对三个 driver 的 findStream 改动),由 maintainer 通知开工。
  3. 一次性统一迁移(一个 objectstack PR + 一个 cloud PR,同批 bump):
    • packages/drivers/,五个 driver 一起进(四个从 packages/plugins/ 平移,driver-turso 从 cloud 迁入)
    • 同一 PR 内改 pnpm-workspace.yaml glob、DRIVERS_DIR、两个 CI workflow、各包 repository.directory
    • cloud 侧 6 条 link: 路径 + lockfile,配 scripts/bump-objectstack.sh
  4. 收敛文档与 packages/spec/liveness/*.json 的 evidence 路径(11 处)
  5. cloud 侧收尾:driver-turso 残包更名 + vector-poc.test.ts 归入 knowledge-turso

为什么不分批:早前版本计划「先只迁 turso,再分批搬其余四个」,理由是降低单次跨仓同步的冲突面。maintainer 裁定改为一次性,理由更强——在多 agent 并行窗口里,任何packages/plugins/driver-* 的路径改动都会与进行中的开发撞车,分批等于把这个撞车面重复 N 次;而且分批必然产生「packages/plugins/packages/drivers/ 各有 driver」的双根中间态,DRIVERS_DIR 得先改成多根扫描、迁完再改回单根,凭空多一次 gate 改动和一段需要维护的过渡状态。等窗口静默后一次做完,冲突面和改动次数都最小。

决策(已裁定)

  1. 许可/商业 — 核心 driver 迁回本仓,作为公开 Apache-2.0 包发布。
  2. 多租户边界multi-tenant.ts 的按租户 provisioning 属云产品差异化能力,留 cloud。
  3. vector-poc — 先留 cloud(已核实与驱动零耦合,留下不需要切分驱动代码;建议后续归入 knowledge-turso)。
  4. packages/drivers/ 收纳范围 — 只收 IDataDriver 实现;knowledge-* / embedder-* 留在 packages/plugins/
  5. 实施时机与批次 — 等进行中的 agent 批次收尾、maintainer 通知后,一次性统一迁移;不分批,不抢跑。

不做的代价

维持现状可行,但要接受:每次本仓 driver 契约或 SqlDriver protected 成员变更,都得有人记得去 cloud 补一刀,而这份记忆目前不在任何检查里——#4484 已经演示了它是怎么丢的。最低限度的止血是在 packages/plugins/driver-sql(或迁移后的 packages/drivers/driver-sql)加一条提示:改动 IDataDriver 契约或 SqlDriver 受保护成员时,同步检查 cloud/packages/driver-turso

Activity

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions