事务、一致性与上限

第 7 课 · 共 7 课 约 8 分钟

一个 Action 就是一个事务。普通批量最多 20 个请求,writeback 只接受单请求;一次最多改 10,000 个对象;编辑 Function 的编辑由 Action 统一提交。

本课目标

读完这一课,你将能够

  • 说出「一个事务」保证什么、不保证什么
  • 用批量执行处理一批请求,说出并发冲突时会怎样,以及各项上限
  • 说出 Function 驱动的 Action 解决什么问题,以及 AIDC 的现状

一个 Action 就是一个事务

一个 Action 的编辑是一个事务:读、算、写一起发生,写入要么全部生效,要么全部不生效。这就是常说的 ACID:原子性(全有或全无)、一致性(不满足值类型约束、必填等就不提交)、隔离性(并发时互不串扰)、持久性(提交后永久保存)。一个 Action 完成之后开始的任何 Action 和查询,都能看到它的全部编辑。

原子性只覆盖对象上的编辑,不覆盖通知和 Webhook,也不覆盖 Function 里的外部调用。示例工厂的 ship-order 是个好例子:新建发运单,再把订单改成 shipped,两条规则在同一个事务里。

{
  "kind": "actionType",
  "apiName": "ship-order",
  "title": "发运订单",
  "schema": {
    "parameters": [
      { "name": "order", "type": "object", "objectType": "salesOrder", "title": "订单", "required": true },
      { "name": "carrier", "type": "string", "title": "承运商", "required": true, "maxLength": 60 }
    ],
    "rules": [
      {
        "type": "createObject",
        "objectType": "shipment",
        "values": { "shipmentNo": "$uuid", "carrier": "$carrier", "status": "shipped", "shippedAt": "$now", "orderNo": "$order.orderNo" }
      },
      { "type": "modifyObject", "objectType": "salesOrder", "object": "$order", "values": { "status": "shipped" } }
    ],
    "submissionCriteria": [
      {
        "condition": { "type": "comparison", "left": { "param": "order", "property": "status" }, "operator": "is", "right": { "literal": "inProduction" } },
        "failureMessage": "只有生产中的订单可以发运"
      }
    ],
    "actionLog": true
  }
}

不会出现「订单已经发运,却没有发运单」,也不会出现相反的情况。日志对象也在这个事务里。

批量与并发

用 applyBatch 一次处理多张工单的产出。普通批量最多 20 个请求;配置 writeback webhook 的 Action 只能单请求提交。批量先全部校验,任何一个不通过就不执行。整批编辑在一个事务里,遇到冲突整批回滚。

aidc semantic apply-batch report-output reports.json --return-edits
[
  { "workOrder": "WO-2001", "goodQty": 120 },
  { "workOrder": "WO-2002", "goodQty": 80, "scrapQty": 2 }
]

上面是 reports.json 的样子:一个数组,每项是一次请求的参数。并发是另一件事:两个人同时改同一个对象,谁生效?通用做法用隔离级别回答。缺省的快照隔离让一个 Action 读到的所有数据都来自它开始的那一刻;它要写的对象如果在这期间被别的 Action 改过,它就失败,而不是悄悄覆盖。遇到冲突可以自动重试,最多 5 次,含外部调用的 Action 默认不重试。

上限

10,000一次最多改的对象数
50一次最多涉及的对象类型数
20普通批量最多的请求数;writeback 只接受单请求

超过上限不会部分成功,整个请求会被拒绝,并说明是哪一项超了。

AIDC 普通批量最多 20 个请求;有 writeback 的 Action 不接受 applyBatch。处理更多对象,要拆成多次调用。每次自成一个事务,整体不再是一个事务。事先想好中途停下的状态,比如把批次号写进参数,让日志帮你续跑。

规则不够用时:Function 驱动的 Action

规则只描述声明式改动。需要读取多个对象并计算时,可以用编辑 Function。Function 按调用人的权限读对象,用 ctx.edits 产生对象和链接的编辑。Action 统一提交这些编辑。Action 的规模上限和 Function 的执行上限仍然生效。

下一门课《Function 与逻辑》从这里接着讲:什么该用声明式构件,什么该写成代码,以及怎样测试。

要点

  • 一个 Action 是一个事务:对象上的编辑与日志要么都生效,要么都不生效;通知和 Webhook 不在里面。
  • 普通批量最多 20 个请求,先全部校验,一个事务,冲突整批回滚。配置 writeback 的 Action 只能单请求提交。
  • 一次最多改 10,000 个对象、涉及 50 个对象类型;超过整个请求被拒绝。
  • 编辑 Function 在隔离运行时里读取对象并计算,用 ctx.edits 产生编辑,Action 统一提交。

练一练

批量、拆分与判断

第一个任务会写入数据,请在你有权限写入的测试组织里做。

准备一个 reports.json,里面三条 report-output 请求。先对每条运行 aidc semantic apply report-output --validate-only,再用 aidc semantic apply-batch report-output reports.json --return-edits 一次提交,比较返回的 edits。

小测

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

Q1用 applyBatch 提交 20 个 report-output,第 12 个在执行时碰到并发冲突,结果是什么?

Q2用一个对象集参数一次暂停 12,000 张工单,会怎样?

Q3receive-material 想把收货数量加到库存上,在 AIDC 里今天该怎么做?

延伸阅读