Repository navigation
Description
发现于 #5109(集群对端广播不失效本节点缓存)实现期,不在该单范围内,故单独立卡。未认领 —— 只是记录。
现象
packages/metadata/src/node-metadata-manager.ts 的 handleFileEvent()(:88-131)在 chokidar 报告 add / change / unlink 之后,只做两件事:重新 load() 一次文件内容,然后 notifyWatchers(type, event)。
let data: any = undefined;
if (eventType !== 'deleted') {
data = await this.load(type, name, { useCache: false }); // 只读,不写任何缓存
}
// ...
this.notifyWatchers(type, event); // 只通知它不碰 this.listCache,也不碰 this.registry —— 而 load() / loadDiagnosed()(metadata-manager.ts)是纯读路径,同样不写这两个缓存(registry 只由 register / registerInMemory / 回滚三处写入)。
这与 #5109 是同一形状、不同触发源:本节点自己的 register() / unregister() 会 invalidateListCache(type) 再通知;文件系统改动只通知、不失效。
后果
rootDir 下手改一个 view/<name>.json(或任何被监听的元数据文件)之后:
get(type, name)是新的 —— 它穿透到 FilesystemLoader;list(type)在LIST_CACHE_TTL_MS = 30_000窗口内继续返回改动前的清单(REST/api/v1/metadata/:type、Studio 左栏、listViews()等一切走list()的读);- 被 HMR SSE 叫醒的前端如果回头拉
list()重新渲染,拉到的还是旧的 —— 与 集群对端的元数据写入不失效本节点的listCache/ registry —— 收到广播的节点最长 30s 继续服务旧定义 #5109 一样的「失效通知附带失效数据」。
另外 type === 'api' 时,EndpointMatcher 索引也只经 watcher 那条缝失效(#5089 装的 subscribe('api', …) 覆盖了它),invalidateListCache 这条缝在此路径上是空的 —— 目前不构成额外缺陷,但两条缝的覆盖面在这里是不对称的,值得一并确认。
触发前提(请在裁决时核实)
FS 监听要开着才会命中。MetadataPlugin 的默认是 watch: true,仅在 bootstrap: 'artifact-only' 下被强制关掉(packages/metadata/src/plugin.ts :241-249);packages/runtime/src/standalone-stack.ts :341 显式传 watch: false。也就是说:artifact 模式的 os dev 与 standalone 不受影响,非 artifact 的默认 MetadataPlugin 装配受影响。命中面主要是开发期,不是生产多节点。
修法(一行,与 #5109 同一样板)
notifyWatchers 之前补 invalidateListCache(type)。invalidateListCache 目前是 private,NodeMetadataManager 是子类,需要放宽到 protected(或复用 #5109 落地的 invalidateForForeignWrite(type, name) —— FS 改动同样是「不是本进程写的」那一类,语义正好对上:删而不预填,穿透回 loader)。
registry 要不要一并删,这里比 #5109 更简单:FS 加载的条目本来就不进 registry,只有当同名条目此前被 register() / registerInMemory() 写过时才存在,而那种情况下删除同样是对的(穿透回 loader 就是文件的真相)。
复现
// rootDir/view/v_a.json 存在
const mgr = new NodeMetadataManager({ rootDir, watch: true, formats: ['json'] });
await mgr.list('view'); // 预热,返回 [v_a]
// 此时在磁盘上写入 rootDir/view/v_b.json,等 chokidar 报告 add
await mgr.list('view'); // 仍然是 [v_a],最长 30s
await mgr.get('view', 'v_b'); // 却能读到 —— 两个读接口彼此矛盾关联
#5109(集群那条同形缺陷,已修,invalidateForForeignWrite 即本单可复用的样板)、#5184(同一个 listCache 字段的第三条缺陷:降级结果照常入缓存)、packages/metadata/src/node-metadata-manager.ts handleFileEvent()、packages/metadata/src/metadata-manager.ts invalidateListCache()。
三单共用 listCache 这一个字段,建议串行。
Activity
os-zhuang commentedon Aug 4, 2026
分诊(PM 循环第 2 轮,会话
session_01Pbu27iNUfQCHeuS551Rqo7):落点packages/metadata(node-metadata-manager.ts + metadata-manager.ts 的可见性放宽)→domain:engine;挂pm:blocked,Blocked-by: #5219 —— 修法样板invalidateForForeignWrite随该 PR 落地,且与其同文件,合并前不派。#5219 合入后转pm:queue即派;届时与 #5184(同一listCache字段的第三条缺陷)保持串行,正文「三单共用一个字段,建议串行」的约束进派发词。Generated by Claude Code
os-zhuang commentedon Aug 4, 2026
认领:PM 循环第 2 轮(阻塞解除:#5219 已合入 main,
533a0a4,invalidateForForeignWrite样板可用)会话:
session_01Pbu27iNUfQCHeuS551Rqo7分支:
claude/issue-5218-fs-watch-invalidate-list-cacheWorktree:
objectstack-issue-5218域:
domain:engine文件面:
packages/metadata/src/node-metadata-manager.ts(handleFileEvent)、packages/metadata/src/metadata-manager.ts(仅方法可见性放宽 / 复用所需的最小触碰)、本包测试、changeset(越界即停,报告说明)串行约束:#5184(同一
listCache字段的写入路径判据)排在本单之后,本单 ⛔ 不碰cacheListResult()与缓存条目形状。⛔packages/spec/**零改动。在飞不相交已核:#5038(objectql/service-automation)、#5134(driver-sql)与本面不交。Generated by Claude Code
os-zhuang commentedon Aug 4, 2026
验收:ACCEPT —— PR #5229(等 CI 绿后入队)
会话:
session_01Pbu27iNUfQCHeuS551Rqo7(PM 循环第 2 轮)落地内容:
handleFileEvent()在notifyWatchers之前调invalidateForForeignWrite(type, name)(复用 #5219 样板,private→protected,零新失效逻辑)。dev 没有假设复用成立而是逐个核了registerInMemory调用方(单名删除契约保护代码态构件),并证明只放宽invalidateListCache是不够的(register()写过的条目在get()/list()里遮蔽 loader —— 有专门用例);issue 请核的 EndpointMatcher 不对称确认非缺陷,本单把第二条缝接对称,幂等有实测。实况核验:draft ✓ / Fixes 行 ✓ / 4 文件全在面内 ✓ / ⛔
cacheListResult零触碰(#5184 的面)、spec 零改动 ✓ / 11 用例中 9 个在回退修复后失败(2 个幸存者是负向对照与 api guard,注释如实标明)/ 真 chokidar 端到端用例含ready竞态修复,3 连跑稳定 / 全包 444 绿 /tsc --noEmit基线 92→92 零增量。顺带发现处置:#5228(
catch不可达,坏文件广播为data: null)已按纪律立卡带finding,定级论证完整(当前无消费者读event.data,休眠),留发现分诊轮;其建议方向 A(改用loadDiagnosed按degraded分流)先记录在案。→ #5184(listCache 写入路径判据,PM 已裁方向 1)在本单合入后即为下一单。
Generated by Claude Code
fix(metadata): an FS change invalidates this node's listCache/registry (
fix(metadata): don't announce an unreadable file as `data: null` (obj…