Skip to content

显式绑定的 datasource 连不上只降级成一条 warning:绑上去的对象在启动后全废,直到查询时才炸 #3758

Description

@os-zhuang

一句话说明

DatasourceConnectionService.handleFailure() 只在「external + validation.onMismatch: 'fail'」时 fail-fast,其余一律降级成 warning。但被 object.datasource === name 显式绑定的 datasource 连不上,等于那批对象全部不可用 —— 而这些对象不会回落到 default driver,它们在查询时直接抛。于是又是一次"启动静默通过、请求时才炸"。

#3741 / #3751 刚在 ObjectQLEngine.init() 那一层把同样的形状修掉了。这一层的边界还画在旧位置。

事实核实

packages/services/service-datasource/src/datasource-connection-service.ts:330-349

private handleFailure(
  record: ConnectableDatasource,
  status: ConnectStatus,
  reason: string,
  context?: DatasourceConnectContext,
): ConnectResult {
  const isExternal = record.schemaMode && record.schemaMode !== 'managed';
  const failFast =
    context?.trigger === 'declared-auto' &&
    isExternal &&
    record.external?.validation?.onMismatch === 'fail';
  const msg = `datasource '${record.name}': connect failed — ${reason}`;
  if (failFast) {
    throw new Error(
      `${msg}. (schemaMode=${record.schemaMode}, validation.onMismatch='fail' ⇒ fail-fast per ADR-0062 D5)`,
    );
  }
  this.logger?.warn?.(`${msg} — degrading (datasource left unconnected)`);
  return { name: record.name, status, reason };
}

配合同文件的 D2 gate(isDatasourceAddressed,:140-168),boot 期会自动连接三类 datasource:

条件 连不上时
(a) external(schemaMode !== 'managed' onMismatch: 'fail' → 抛;否则 warning
(b) 有对象显式 datasource: '<name>' 绑定它 一律 warning
(c) autoConnect: true 一律 warning

问题在 (b)。同文件 :151-159 自己的注释写明了后果:

External datasources and explicit object.datasource bindings never resolved to default(they throw when unregistered)

也就是说:显式绑定到某个 datasource 的对象,在该 datasource 没连上时没有任何回落路径 —— 每一次针对它们的查询都会抛"driver 未注册"。启动时只留下一条 warning。

影响

一个 app 声明 datasource: 'analytics' 并把 20 个对象绑上去,ANALYTICS_URL 配错或那台库没起来:

  • 服务器正常启动,没有任何非零退出、没有任何显式信号。
  • 那 20 个对象的所有读写全部失败,报的是"driver 未注册"这种跟真实原因(连不上 analytics 库)相距很远的错。
  • 剩下的对象工作正常,所以整体看起来"服务是好的",只是"某些页面坏了" —— 比整体宕机更难定位。

这跟 #3741 修掉的是同一个决定,只是发生在另一个 datasource 注册路径上。#3751 让 boot 期主 driver 连不上就拒绝启动,而这里一个被 20 个对象依赖的 datasource 连不上,只值一条 warning。

建议处置

"boot 期主库 vs runtime 加的可选副本"的区分是对的,但 (b) 落错了边。 显式 object.datasource 绑定表达的是一个硬依赖 —— 作者已经明说了这些对象只能从这里读 —— 它跟主库失联没有本质区别。

倾向:把 (b) 提升为 fail-fast,与 (a)+onMismatch:'fail' 并列,理由是它同样没有回落路径。(c) autoConnect: true 保持宽容(那是"能连就连"的语义,没有对象声明依赖它)。

需要一并决定的:

  • 逃生阀是否共用 OS_ALLOW_DRIVER_CONNECT_FAILURE 倾向共用 —— 操作者的意图是同一个("我知道数据库连不上,照样起"),两个旗标只会让人漏设一个。
  • isDatasourceAddressed 里 (b) 的判定发生在 connect() 之前,绑定对象列表已经算好并传进 connect(ds, { objects: bound }),所以 handleFailure 拿得到"有几个对象依赖它" —— 错误消息里应该直接列出来,而不是只给 datasource 名。
  • 现有行为是 ADR-0062 D5 明文写下的,改动需要同步更新 ADR,而不是只改代码。

关联

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions