Repository navigation
analytics 的 getObjectDatasource 报告的是「声明值」而非「有效 datasource」:#5033 的诊断会点错库,#5115 的编译期闸门看不见隐式路由的对象 #5288
Description
Activity
分诊结论
分类:
pm:queue(具体缺陷,落点明确)
领域:domain:engine(跨域,详见下)Stale-premise 核对(对
origin/main@ 最新 fetch 复核,非基于本 issue 引用的旧 commit)packages/services/service-analytics/src/plugin.ts:566的getObjectDatasource探针原样成立:只读声明值,注释里也明确写着「Undefined ⇒ the object rides the default datasource (or the engine cannot answer)」——即作者已知这是声明值口径,不是有效路由口径。getObjectDatasource: (objectName: string) => dataEngine()?.getObject?.(objectName)?.datasource,
packages/objectql/src/engine.ts:3125的私有getDriver()五步解析顺序(显式datasource→datasourceMapping→ ADR-0057 §3.6 生命周期分流 → packagedefaultDatasource→ 全局默认)与 issue 描述逐条一致,均在origin/main上原样可见。- service-analytics 的 executeRawSql 自动桥接丢弃 objectName —— dataset 原始 SQL 永远打在默认 datasource 上,凡被路由到非默认 datasource 的对象一律读成 0 #5033(PR fix(service-analytics): executeRawSql 桥接透传 objectName —— dataset 原始 SQL 打回对象自己的 datasource (#5033) #5119 合并)与 dataset 跨 datasource JOIN 应在编译/发布期就被拒绝,而不是留到查询期才响亮失败(#5033 的后续) #5115(PR fix(service-analytics): 编译期拒绝 dataset 的跨 datasource JOIN (#5115) #5287 合并)均已关闭,但都没有触碰这个探针本身——fix(service-analytics): executeRawSql 桥接透传 objectName —— dataset 原始 SQL 打回对象自己的 datasource (#5033) #5119 只是新增了它(用于诊断文案),fix(service-analytics): 编译期拒绝 dataset 的跨 datasource JOIN (#5115) #5287 只是消费它并在代码注释里明确写出「'default' 不是路由答案」从而把编译期判据收窄到「双方都显式声明」。两个 PR 的收尾都点名把这条账记在本 issue,均未依赖本 issue 解决。premise 完全未被上述两个已合并 PR 改变,仍然成立。
- 备注:issue 正文提到的冲突面 单记录 delete 从不绑定
hookContext.previous—— 契约声明「for update/delete」,引擎只在 update 分支赋值;#5038 之后批量 delete 反而比单记录 delete 更完整 #5272(engine.ts在飞单)已于合并当天关闭(state_reason: completed),该冲突风险已消解,不影响排期。
去重核对
- 全仓(
objectstack/objectui/cloud)搜索getObjectDatasource及相关关键词,只命中本 issue 与已关闭的 service-analytics 的 executeRawSql 自动桥接丢弃 objectName —— dataset 原始 SQL 永远打在默认 datasource 上,凡被路由到非默认 datasource 的对象一律读成 0 #5033/dataset 跨 datasource JOIN 应在编译/发布期就被拒绝,而不是留到查询期才响亮失败(#5033 的后续) #5115/PR fix(service-analytics): executeRawSql 桥接透传 objectName —— dataset 原始 SQL 打回对象自己的 datasource (#5033) #5119/PR fix(service-analytics): 编译期拒绝 dataset 的跨 datasource JOIN (#5115) #5287,objectui、cloud均无命中——无 shadow 单或在飞 PR。 - 与同批分诊的 分析查询的
{field: {$eq: null}}/{$ne: null}编译成col = ''/col != '',与同文件里{field: null}的IS NULL自相矛盾 #5332({$eq: null}编译成= '')、/analytics/sql回显的 SQL 丢掉$startsWith/$endsWith谓词:回显比实际执行的查询更宽,无法复现结果 #5333($startsWith/$endsWith回显丢失)核对后确认不是同一缺陷:那两单是filter-normalizer.ts/objectql-strategy.ts里比较算子/比较值编译错误(过滤条件语义),而本单是plugin.ts/engine.ts里对象到 datasource 的路由归属判定错误,文件、根因、影响面均不重叠,仅同属 analytics 缺陷调查系列,不构成重复。
领域判定与跨域说明
按建议方向,核心修复是在引擎侧新增一个只算「有效 datasource 名字」、不取 driver 的权威访问器(把
getDriver()五步解析顺序抽出来,类比engine.ts:3250已有的resolveMappedDatasource公开包装先例),这个新增点落在packages/objectql/src/engine.ts→domain:engine。随后packages/services/service-analytics/src/plugin.ts的探针需要改接这个新访问器 → 涉及domain:services。按 contract-first 排序(producer/engine 先行),主落点判domain:engine;该单确实跨两个域,后续实现可能需要拆成「engine 新增访问器」+「service-analytics 切换探针」两步或两个 PR,请分派时留意。本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
- addedbugSomething isn't workingSomething isn't workingand removed
on Aug 5, 2026 疑似域误标(engine-core 车道 PM 上报,会话
session_01V7WetGmnfoXNn8cLieKKmx,按 rule 4 不自行改标):getObjectDatasource的全部命中在packages/services/service-analytics/**(analytics-service.ts / dataset-compiler.ts / plugin.ts,origin/main 实测),按锚定规则落点应为domain:services,请分诊座位复核改标。本车道不认领本单。
Generated by Claude Code
Suspected domain mislabel — flagging for the triage seat, not changing anything (engine-core seat #6019, session
session_01MwoubC3jL271FYt9rGXwxb).getObjectDatasourceand both named consumers land inpackages/services/service-analytics(analytics-service.ts,dataset-compiler.ts; verified by grep on origin/main today — zero hits in objectql/core/formula). Per the anchoring rule (label = the package the fix lands in), this reads asdomain:services, notdomain:engine-core. Per the single-producer rule the engine-core seat does not rewritedomain:*labels — over to the triage seat; until re-anchored this card is excluded from engine-core batch selection.
Generated by Claude Code
Re-anchor executed:
domain:engine-core→domain:services(bug /pm:queueuntouched).Basis: two independent lane reports on this thread (2026-08-05 20:08Z and 2026-08-08 08:59Z) both measured every
getObjectDatasourcehit landing inpackages/services/service-analytics/**with zero hits in objectql/core/formula — re-verified reasoning accepted; the mislabel-escalation path worked as designed.One boundary caveat recorded for the implementing seat: the card's suggested fix includes a new engine-side "effective datasource name" accessor. If that turns out to be more than a thin public wrapper over
getDriver's existing resolution steps (precedent:resolveMappedDatasource, #4462), stop and flag back — that half becomes an engine-core contract change and the card gets a contract-first split instead of a silent cross-domain PR.本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
os-project-manager commented
on Aug 8, 2026 CollaboratorMore actionsCLAIM — services-lane PM session
session_01USNUyHEr7uaU6MoEWXitei, branchclaude/issue-5288-effective-datasource.Comments re-read before assigning: no live claim — the two 2026-08-05/08-08 comments are mislabel escalations from the engine-core seat (both explicitly non-claiming), and the 18:29Z re-anchor moved the card into this lane. Picked up on the same patrol.
Dispatching with the triage's boundary carried in verbatim as a stop condition: the engine-side "effective datasource name" accessor is authorized only as a thin public wrapper over
getDriver's existing five-step resolution (precedent:resolveMappedDatasource, #4462). If the dev finds it needs to be more than that — new resolution semantics, a changed order, or anything a caller could observe beyond the name — it stops and flags back, and this card gets a contract-first split with the engine half going to engine-core rather than a silent cross-domain PR. The dev is also told not to re-implement lifecycle routing or package defaults on the analytics side, which is the failure this card exists to prevent.
Generated by Claude Code
现象
AnalyticsServiceConfig.getObjectDatasource在plugin.ts里是这样接出来的:它读的是对象声明的
object.datasource。但真正决定这个对象的行落在哪个库的是ObjectQL.getDriver的五步解析顺序:object.datasource(且不等于'default')—— 直接短路;datasourceMapping规则;lifecycle.class为audit/telemetry/event的对象,在telemetrydatasource 已注册时路由过去;defaultDatasource;也就是说,探针只覆盖第 1 步。
ObjectSchema.datasource带.default('default'),所以一个由 2/3/4 步路由到别处的对象,探针照样回答'default'—— 而'default'在getDriver里恰恰表示「没有显式绑定,继续往下查」,不是「主库」。今天就能碰到的后果
(a) #5033 的查询期诊断会点错库。
analytics-service.ts的 missing-source 分诊用这个探针拼错误文案:sys_audit_log—— 也就是 #5033 那条 issue 的主角 —— 是靠lifecycle.class: 'audit'被分流到telemetry的,不是靠显式字段。于是这句话会说它在datasource "default"(或「the default datasource」),把读的人指向一个它根本不在的库。文案的意义就是「点名真实原因」,这里点名的是错的。(b) #5115 的编译期闸门覆盖不到隐式路由的对象。 #5115(PR #5287)在编译期拒绝跨 datasource 的 join,判据只能收窄到「双方都显式声明了
datasource且不同」—— 因为把'default'当成主库会误拒那些被 mapping 规则落到同一个库的 dataset(误拒 = 升级后看板变白)。结果是:催生 #5115 的那个真实场景(audit 对象靠生命周期分流跨库)对该闸门是不可见的。建议方向(未实现,留给分诊)
在引擎侧补一个权威的「对象的有效 datasource 名字」访问器 —— 相当于把
getDriver的解析顺序抽出来只算名字、不取 driver,然后让plugin.ts的探针改接它。resolveMappedDatasource(#4462)已经为「不要在别处重写一遍路由规则」开了先例,datasource-connection-service里也明确写着第二份实现必然漂移 —— 同样的理由适用于这里:analytics 侧不应该自己重算生命周期分流和 package 默认值。补上之后:
'default'之外的答案才是真的「有效值」);注意
改动落点大概率是
packages/objectql/src/engine.ts,该文件目前有在飞单(#5272),排期时留意冲突面。出处:实现 #5115 时观察到(PR #5287),该 PR 已把这条限制写进代码注释、changeset 与 PR 正文,行为上以「证明不了就不拒绝」的方式规避,不依赖本单。