Skip to content

check:durability-log-level 结构性看不见「读接缝把故障答成空值」这一类 —— #4825 / #5108 全家都在闸门盲区里 #5186

Description

@os-zhuang

发现于 #5108(DatabaseLoader 读故障吞成空结果)实现期,不在该单范围内,故单独立卡。未认领 —— 只是记录。观察类,今天没有用户会撞到。

现象

scripts/check-durability-degradation-log-level.mjs#4632 那条规则的机械执行者。它的判据是:

catch 块里调了 DURABILITY_CRITICAL_CALLEES 词表里的操作,而日志级别低于 error 且没有 rethrow → 红。

这个模型对写/DDL 接缝是合身的,对接缝则结构性地表达不了。两条都不成立:

  1. 词表是按 callee 名字匹配的,而读接缝的 callee 是 find / findOne / count 这种彻底通用的名字 —— 加进词表会把全仓库每一处数据读取都拖进来,不可行。词表现有 9 项(syncSchemainitObjectswriteRecorddropPromotedDraftRow…)清一色是写/DDL 语义的专名。
  2. 更根本的:读接缝的错误形态不是「日志太轻」,而是「编了一个返回值,且一行都不记」。 catch { return []; } 在闸门眼里连一个可判级别的日志调用都没有 —— 它检查的那个维度在这里是空的。DatabaseLoader 把存储读故障吞成空结果 —— ADR-0110 D3 的 miss/outage 之分在复数读路径上不成立 #5108 修掉的那五处正是这个形状:catch {}[] / false / null,零日志。[metadata] nextEventSeq() 把驱动读失败也当成「表还没建」,静默从 1 重新发号 —— #4632 同形,机械检查覆盖不到 #4825(nextEventSeqcatch { return 1 })是同一族,而且是最贵的那半(写进去的数是错的)。

也就是说:这个族已经在这一个包里出现过三次(#4728#4825#5108),每次都是人读出来的,闸门一次都没有帮上忙,而且照现在的模型也帮不上。

这一类的可判据形状

三次实例长得一模一样,可以描述:

  • 一个 catch 包着一次(driver/engine 的 find / findOne / count,或它们的薄封装);
  • catch 体里没有任何日志,也没有 rethrow;
  • 而是 return 一个该方法的空值/零值([] / false / null / 0 / 1)。

判据的关键不在「调了什么」,而在「没读到,却编了一个答案出来」。良性豁免也已经有现成词汇:isMissingTableError()(packages/metadata/src/errors.ts 专门为跨包导出它而存在)—— 一个 catch 只要按错误类型区分过、且只在良性分支返回空值,就应当放行。#4825#5108 修完之后的代码正好就是这个形状,可以直接当 fixture。

为什么不该塞进别的单

建议方向(裁决留给维护者)

  1. 给现有脚本加一条独立规则(不走 DURABILITY_CRITICAL_CALLEES):catch 无日志无 rethrow + return 空值 + 块内含读调用 → 红,除非 catch 里出现按错误类型的区分(isMissingTableError 之类)。必然需要一份 baseline —— 全仓库这个形状的 catch 大概率不少,而且相当一部分是合法的功能性降级;
  2. 或者判定这一族不适合机械判(误报率过高),转而只在 AGENTS.md 里把「读接缝不得编造答案」写成明文规则,靠 review 兜 —— 但那样就要接受它会再犯,并且明说这个取舍;
  3. 或者收窄到只扫元数据/持久化层的读接缝(packages/metadatapackages/metadata-protocolpackages/objectql 的存储缝),把误报面压到可管的范围,再逐步放开。

两条不是本卡要定的;要定的是「这一族目前完全没有机械保护,而它已经复发三次」这一点。

复现

# 现状:五处 `catch {} → 空值` 的读接缝(#5108 修复前的 database-loader.ts)
# 对闸门完全透明 ——
node scripts/check-durability-degradation-log-level.mjs
# → OK,12 durability-critical catch seam(s), all loud or rethrowing

关联

#4632(立规矩)、#4728 / #4825 / #5108(同一族的三次复发)、#4754(词表覆盖的另一半:写接缝)、AGENTS.md「Degradation log levels — warn vs error」「Absence must be loud」、packages/metadata/src/errors.ts(良性判据的现成词汇)。

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions