对象存储:数据源加上语义层改动

第 2 课 · 共 6 课 约 8 分钟

对象有数据源层和语义层改动两层,叠成当前值;读懂 overridden、sourceGone 和 rev。

本课目标

读完这一课,你将能够

  • 说出对象里的两层,以及当前值是怎样合出来的
  • 读懂 overridden、sourceGone、rev 三个标记
  • 判断一次同步或一次改动之后,对象会变成什么样

两层,叠成当前值

上一节的同步只写对象的数据源层。人和智能体通过 Action 做的改动,写在另一层:语义层改动(edits)。两层叠在一起,就是对象的当前值:一个属性有改动就用改动,没有就用数据源的值,两边都没有就是空。应用、搜索、聚合和 SQL 看到的都是当前值。

  1. 01数据源层只有同步写它
  2. 02语义层改动Action;开放直接编辑的类型也可由开发者直接写
  3. 03当前值逐个属性:有改动用改动,否则用数据源

两层互不干扰。MES 里改了工单的交期,没被人改过的属性会跟着变;人改过的属性,仍是人改的值。数据源再同步,冲不掉人的改动。

一个工单的一天

看 WO-1042 这一个工单。一天里发生了四件事:

  1. 07:30 MES 同步进来

    status 是 running,交期是 10 月 3 日。没有任何改动,当前值全部来自数据源,rev 为 1。

  2. 10:15 计划员执行 hold-work-order

    车间发现缺料,MES 里还没来得及改。计划员先在 Semantic 里把 status 改成 paused,并在 holdReason(只在 Semantic 里维护的属性)写下「缺料:电机」。这两个属性有了改动,rev 变成 2;status 的改动盖住了数据源的 running,进入 overridden。

  3. 14:00 MES 把工单标成 done

    数据源层的 status 变成 done,但当前值仍是 paused:改动优先。当前值没变,rev 也不变;overridden 里 status 的值更新成数据源现在的 done。

  4. 14:05 MES 把交期改到 10 月 5 日

    dueAt 没有改动,当前值直接跟着变,rev 变成 3。

第四步之后,对象的当前值与编辑标记如下(只列几个属性;这是两层存储示意,不是新对象接口的响应):

{
  "type": "workOrder",
  "pk": "WO-1042",
  "props": { "workOrderNo": "WO-1042", "status": "paused", "dueAt": "2026-10-05T09:00:00Z", "holdReason": "缺料:电机" },
  "rev": 3,
  "edited": ["status", "holdReason"],
  "overridden": { "status": "done" },
  "sourceGone": false
}

props 是当前值;edited 列出有改动的属性;overridden 列出被盖住、而且数据源现在是另一个值的属性,连同数据源的值。

这个例子里,改动盖在了一个同步来的属性上。这是允许的,overridden 就是为它设的,但它是例外而不是常态:来自数据源的事实,权威仍在源系统,能在源头改的就去源头改;人在 Semantic 里改的,多是只在这里维护的属性,比如 holdReason、负责人、跟进备注。

三个标记,和几条规矩

OVERRIDDEN

被覆盖

改动盖住了数据源的值,而两边不一样,overridden 连同数据源现在的值一起给出。看到它,先问问这个改动还该不该留,尤其是数据源后来又变了的时候。

SOURCEGONE

源头消失

数据源里已经没有这一行(mirror 模式下行从流里消失)。对象默认不出现在搜索、聚合和 SQL 里,改动保留;行回来时对象跟着回来,之前的改动仍然生效。

REV

版本号

当前值每变一次加一。写入时带 ifRev,对不上就返回 409 rev_mismatch,防止后写的盖掉先写的。

用 Action 删除对象,是给它打上「墓碑」:读不到了,数据源不受影响,数据源再送来同一行也不会让它回来。之后再用 Action 新建同一个主键,得到的是新对象,不继承旧的改动。

新 Object Type 缺省只能经 Action 改。只有类型设置 editsConfiguration.onlyAllowPrivilegedEdits: false,开发者才可直接写入或用 --revert 撤掉属性改动:

aidc semantic object workOrder WO-1042                   # 当前属性
aidc semantic edits-history workOrder --pk WO-1042        # Action 编辑历史
aidc data update workOrder WO-1042 --revert status --if-rev 3

Action 造成的每一次改动都有记录:谁、什么时候、通过哪个 Action、改成了什么。在对象浏览器的对象视图里能看到这段编辑历史,命令行里用 aidc semantic edits-history workOrder --pk WO-1042,加上 --previous 还能看到改前的值。数据源同步来的变化不在这份历史里。

属性是对象类型定义的一部分。active 属性须先改为 deprecated 或 experimental,提交定义或合并改动后再删除。删掉属性后,它的旧值(包括人改过的)不再出现在当前值里;改类型、改主键同样是破坏性变更,定义时会返回,发布时会记档。发布之前先确认调用它的应用都改好了。

下一节讲这些数据有多新:从源头变化到读到它,时间花在哪里,什么时候才会重新计算。

要点

  • 对象有两层:同步写数据源层,Action 写语义层改动。类型开放直接编辑后,开发者也可直接写语义层改动。
  • 当前值逐个属性合成:有改动用改动,否则用数据源。
  • overridden 表示改动盖住了数据源的值、两边不一样,并给出数据源现在的值;sourceGone 表示数据源里没有这一行;rev 随当前值变化加一。
  • 写入带 ifRev 防并发覆盖;只有开放直接编辑的类型,开发者才可用 --revert 撤掉属性改动。

练一练

算一算当前值

先用纸笔,再拿真实的对象验证。

一个工单起初 plannedQty 是 100。计划员用 Action 改成 80;随后 MES 把它改成 120,并把 status 改成 done。写出这两步之后的 props、edited、overridden 和 rev(起初 rev 是 1,status 是 running)。

小测

选一个答案,马上看解析。

Q1计划员早先把 WO-1042 的 status 改成了 paused。现在 MES 把它改成 done。当前值是?

Q2mirror 模式下,某个工单不再出现在 MES 的数据流里,会怎样?

Q3两个计划员同时打开 WO-1042 准备修改。怎样防止后保存的悄悄覆盖先保存的?

延伸阅读