You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
在 #3724 落地方案 B(PR #3734)时撞到,按 Prime Directive #10 拆出来单独跟踪。
事实核实
packages/objectql/src/engine.ts:1868-1888:
constfailedDrivers: string[]=[];for(const[name,driver]ofthis.drivers){try{awaitdriver.connect();this.logger.info('Driver connected successfully',{driverName: name});}catch(e){failedDrivers.push(name);this.logger.error('Failed to connect driver',easError,{driverName: name});}}if(failedDrivers.length>0){this.logger.warn(`${failedDrivers.length} of ${this.drivers.size} driver(s) failed initial connect. `+`Operations may recover via lazy reconnection or fail at query time.`,{ failedDrivers });}
一句话说明
ObjectQLEngine.init()对每个 driver 的connect()做 try/catch,失败只 log 一条 error 就继续启动。结果:数据库连不上的服务器会"启动成功",然后所有请求在查询时炸;更糟的是,driver 没有任何办法通过connect()拒绝启动——任何启动期致命校验都会被这层 catch 降级。在 #3724 落地方案 B(PR #3734)时撞到,按 Prime Directive #10 拆出来单独跟踪。
事实核实
packages/objectql/src/engine.ts:1868-1888:两点值得注意:
reconnect,除了这条 warning 字符串本身,driver-sql/driver-mongodb里没有任何重连实现。所以现实中只剩下 "fail at query time" 这一半。packages/objectql/src/plugin.ts:418await this.ql?.init(),下一步(同文件 431)就是syncRegisteredSchemas(ctx)—— 对一个没连上的 driver 跑建表/建索引。影响
生产误配静默通过:错的
OS_DATABASE_URL、轮换过的密码、没开的网络策略 —— 服务器照常起来、健康端点可能还是绿的,然后每个请求 500,报出的错误跟真实原因(数据库连不上)相距很远。driver 失去了"拒绝启动"的能力,这是更结构性的一条。任何 driver 想在启动期做致命校验(不只是网络不可达:许可、版本、配置不兼容、能力缺失),走
connect()抛错都会被这层 catch 吃掉,降级成运行时错误。feat(driver-mongodb)!: 显式单租户 —— 检测到多租户模式即拒绝启动 (#3724) #3734 就是被这一点逼出来的:driver-mongodb 检测到多租户模式必须拒绝启动,但只放在
connect()里的话,"拒绝启动"会退化成"启动了、之后在查询时炸"——只好把守卫挪进构造函数。这个绕法能用,但它不是下一个 driver 作者会知道要复制的模式,而且构造函数不是所有启动期校验都放得进去的地方(需要连接才能查到的信息就不行)。建议处置
A.
init()默认 fail-fast —— 任一 driverconnect()失败即向上抛,boot 中止并打印哪个 driver、什么原因。要保留宽容行为的话,做成显式 opt-in(OS_ALLOW_*形态的逃生阀,且启动时 loud 标注处于降级状态),而不是默认。B. 至少区分错误种类 —— 网络类瞬时失败保留现状,但必须真的实现 lazy reconnect,否则那条 warning 是在骗人;driver 主动拒绝(带
code的语义性失败)直接抛。倾向 A:它同时修好两件事,且和平台已有的取向一致 ——
resolveTenancyPosture()对非法值拒绝启动、ADR-0093 D5 的 degraded-tenancy 拒绝启动、serve.ts对UnsupportedDriverError拒绝启动,都是"宁可不启动,也不带着说不清的状态服务流量"。这里是同一个决定,只是还没做。无论选哪个,"lazy reconnection" 那句话要么兑现、要么删掉 —— 它现在是 declared ≠ enforced 的一个小样本。
关联