函数里改数据

第 3 课 · 共 6 课 约 8 分钟

编辑函数用 ctx.edits 收集改动,由 Action 提交;规则与对象集参数做批量修改;Action 配置 webhook。

本课目标

读完这一课,你将能够

  • 说出函数怎样改数据,以及改动什么时候才真正生效
  • 分清什么时候规则就够、什么时候需要函数驱动的 Action
  • 在 AIDC 里用规则与对象集参数做批量修改,并说清它和暂存写入的差别

函数怎样改数据

函数不直接写库。它返回一份「改动清单」:新建、修改、删除哪些对象,建立或解除哪些关系。这份清单只有被一个 Action 采用,才会真正生效。在开发环境里试跑一个改数据的函数,得到的只是清单,对象一点没变。

  1. 01函数计算读对象,算出要改什么
  2. 02返回改动清单新建、修改、删除、建关系
  3. 03Action 采用校验参数与提交条件
  4. 04事务写入全改成或都不改,并留记录

什么时候规则写不下?三种情形最常见:

  • 要改的对象靠关系连着,个数运行时才知道,例如关掉一张订单下的全部工单;
  • 要写的值得读好几个对象才算得出来,例如按各条产线的余量挑一条;
  • 要一次新建几种对象,再把它们连起来。

这样的 Action 叫函数驱动的 Action。它依然受 Action 的上限约束(一次最多改 10,000 个对象、涉及 50 个对象类型),也受函数运行上限的约束。被批量触发时,函数默认按请求逐个调用;也可以让函数一次收到整批(入参是一个结构列表),更快,也少一些冲突。

Action 的 webhook 输入可引用参数、对象参数属性或字面量。规则和 side effect 还可用 $writeback.<输出名>。用函数计算 webhook 输入、用函数渲染通知正文仍待补,不能当成现有能力。

一个坑,和它的补救

坑:函数里改了对象,紧接着在同一个函数里搜索,搜到的还是旧数据。改动要等函数执行完才传到对象集接口;只有按主键取回你刚改的那个对象,才会看到新值。

补救:标准模型又提供了暂存写入(Beta):改动先暂存,函数里之后的读取都看得到,也就是先写后读;函数成功结束、Action 完成时才一起提交;中途出错,暂存的全部丢弃。

常规的改数据函数暂存写入
读得到自己刚写的吗读不到,要等函数结束读得到
返回值必须是那份改动清单可以返回别的信息,改动自动暂存
调用别的会改数据的函数不支持支持,改动一起暂存、一起提交

在 AIDC 里:规则、对象集参数、先预演

AIDC 已支持编辑函数。用 aidc semantic functions publish edits.js --api-name holdWorkOrders --version 1.0.0 --output '{"type":"integer"}' --edit-function 发布。函数用 ctx.edits 收集改动,由调用它的 Action 统一提交。简单的批量修改仍可用规则:一个 Action 的多条规则在同一事务提交。参数可以是对象集,一条 modifyObject 规则就修改命中的对象。下面的 eachIs 要求每张工单都满足提交条件:

{
  "kind": "actionType",
  "apiName": "hold-work-order",
  "title": "Hold work orders",
  "schema": {
    "parameters": [
      { "name": "workOrders", "type": "objectSet", "objectType": "workOrder", "title": "Work orders", "required": true },
      { "name": "reason", "type": "string", "title": "Reason", "required": true, "maxLength": 200 }
    ],
    "rules": [
      { "type": "modifyObject", "objectType": "workOrder", "object": "$workOrders", "values": { "status": "paused" } }
    ],
    "submissionCriteria": [{
      "condition": { "type": "comparison", "left": { "param": "workOrders", "property": "status" }, "operator": "eachIs", "right": { "literal": "running" } },
      "failureMessage": "Only running work orders can be paused"
    }],
    "actionLog": true
  }
}

「个数运行时才知道」这个问题,在 AIDC 里这样解决:调用方把「这条产线上运行中的工单」这个对象集本身交给 Action,Action 在执行的那一刻才把它展开成具体的对象。提交条件也按展开时对象的当前值判断:上面的 eachIs 会确认每一张都还在运行中,只要有一张不是,整批被拒绝,什么都不改。一次最多改 10,000 个对象;applyBatch 一次最多 20 个请求,同在一个事务里。

没有暂存写入,就用三样东西拿到相近的保护:

  • 只校验($validateOnly):逐项看参数和提交条件的结果,什么都不写;
  • 工作流预演:读、算照跑,Action 只返回将要写入的计划;
  • 草稿加批准:例如智能体起草一张采购订单,采购员用 approve-purchase-order 批准。

要点

  • 函数返回改动清单,要被一个 Action 采用才生效;试跑不会改对象。
  • 个数运行时才知道,或要读多个对象才能算值,才需要函数驱动的 Action。
  • 函数里搜不到自己刚改的数据;暂存写入提供先写后读,并在结束时一起提交。
  • AIDC 里用多条规则加对象集参数做批量修改,提交条件按执行时的对象值判断,并用只校验、预演和草稿加批准把关。

练一练

用规则写「下达工单」

示例工厂的 release-work-order:把计划中的工单下达到一条产线。

参数:workOrder(对象)、line(productionLine 对象)。一条 modifyObject 规则:status 改为 released,lineCode 取 $line.lineCode。提交条件:工单当前状态必须是 planned,并写好失败信息。

小测

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

Q1在开发环境里试跑一个改数据的函数,对象会变吗?

Q2在 AIDC 里一次暂停一条产线上运行中的十张工单,最合适的是?

Q3函数里改了一个对象后马上搜索,为什么可能搜不到新值?

延伸阅读