Files
orbit/docs/api/workflow-definition-format.md

103 lines
8.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 流程定义结构版本1
本页冻结已实现的发布格式与静态校验。TASK、BRANCH、PARALLEL、SIGNAL、TIMER、POLL均可描述并发布;对应实例执行器仍按P4–P5开发,发布成功不能当作流程执行成功。API见[定义发布](workflow-definitions.md)。
## 1. 顶层、顺序块与类型
顶层`schema_version`必须为1;`input_type`声明实例输入;`timeout_ms`为1毫秒至30天的总时限;`failure_policy`必填`REVIEW`或`FAIL_AFTER_SETTLED`;`body`为顺序块。未来实例总时限包含等待和暂停,不能因恢复重新计时;未知外部效果始终需要核查,不能由失败策略覆盖。
一个块包含`steps`(可省略为空,不能为null)、必填`output_type`和`output`。步骤顺序固定,输出表达式在全部步骤完成后解析。空块可以直接映射输入或常量。组合节点只把该块输出暴露给外部,禁止从外部读取内部步骤。
类型对象使用`kind`:
| kind | 附加字段 | 契约 |
| --- | --- | --- |
| STRING | 可选`enum: string[]` | 非空枚举最多32项,值互异且每项最多128字节;无enum表示任意有效JSON字符串 |
| NUMBER | 无 | 精确JSON数字;数字token最长256字节,指数范围等沿用平台JSON边界,不以float64比较 |
| BOOLEAN / NULL | 无 | 必须精确匹配布尔或null,不做隐式转换 |
| OBJECT | `fields: map<string,Type>` | 0–64个字段,所有声明字段必填,额外字段不允许;空映射可省略 |
| ARRAY | 必填`items: Type` | 所有元素同型;运行数据校验最多4096项 |
| JSON | 无 | 任意合法JSON整体值;不允许根据未知字段或下标做引用 |
类型嵌套最多8层。字段名1–64 ASCII字符,首位字母或数字,其余可含`.`、`_`、`-`;每个path元素按完整字段名匹配,点号不自动展开。类型不支持可选字段、隐式null、联合类型或脚本。
输入/结果校验同时受256 KiB及平台JSON深度和数字边界限制。NUMBER和STRING不互相转换;字符串枚举来源必须是目标枚举子集。OBJECT字段集合必须相同且递归兼容。目标JSON可以接收任意合法类型,JSON来源不能窄化为未验证的具体类型。
## 2. 数据表达式与条件
| Value.kind | 配置 | 说明 |
| --- | --- | --- |
| LITERAL | 必填`literal` | 任意合法常量,显式null仅用于允许NULL/JSON的目标;保留原数字文本 |
| REFERENCE | 必填`reference:{source,path?}` | source为`input`、`workflow`或当前词法作用域已完成步骤key;path最多8个已声明OBJECT字段 |
| OBJECT | `fields: map<string,Value>` | 构造对象,最多64个字段;输出契约为OBJECT时必须覆盖全部字段 |
| ARRAY | `items: Value[]` | 构造数组,最多256项;更大业务数组可整体引用 |
表达式最多8层;禁止前向、自引用、跨兄弟分支引用和越过组合节点引用内部步骤。空path引用整个值,不支持数组索引、动态路径、字符串插值、当前时间、随机数或任意代码。`workflow`内置类型为`{id: STRING, business_key: STRING}`。
条件为`Predicate`:比较操作`EQ/NE/LT/LE/GT/GE`必须有`left`和`right`,且类型相同;有序比较只支持STRING、NUMBER,布尔和NULL只支持相等/不等。`AND/OR`使用2–16项`arguments`,`NOT`恰好1项,不能同时携带比较操作数;条件最多8层。STRING按精确文本比较,NUMBER后续执行必须保留十进制精度。
不属于当前kind的非空配置会拒绝;可省略集合与空集合使用统一编码。任何未识别字段仍直接拒绝。
## 3. 步骤
每步必填`key`和`kind`。key在整个定义中唯一,1–64 ASCII字符,名称规则同字段名,保留`input`、`workflow`。必须且只能携带对应的一种配置。
### TASK:普通业务任务
`task`字段:
| 字段 | 类型 / 规则 |
| --- | --- |
| queue_id | 必填32位ID;发布时核对当前命名空间、队列存在和权限 |
| handler / handler_version / payload_version | 必填,沿用Pulse命名与版本规则,Worker承载对应实现 |
| input_type / input | 必填,处理器参数契约及构造表达式 |
| result_type | 必填,权威成功结果契约;未来不匹配不能推进后续步骤 |
| timeout_ms | 必填正值,不超过流程总时限;执行时还受实例剩余时间约束 |
| retry | 必填显式策略:max_attempts包含首次,1–100;attempt_timeout_ms等按[Pulse规则](retries.md)校验;多次尝试须提供合法退避区间 |
| recovery_safety | 必填RECONCILE_ONLY或IDEMPOTENT,不接受隐式默认策略 |
| priority | 可省略为0,0–9 |
| business_key / concurrency_key | 可选STRING表达式;业务键只用于追踪,资源键按Pulse许可语义使用 |
输入和结果类型不能声明为NULL,任务输入不能是字面null。JSON来源仍可能在运行时产生null,实例引擎必须再次检查实际输入/结果、键长度和Pulse限制,不能把静态通过当作运行数据有效。处理器名/版本是否有在线Worker不在发布时检查,发布不要求Worker正在运行。
### BRANCH:条件分支
`branch.cases`为1–16项`{when: Predicate, body: Block}`,按顺序取第一个匹配路径;`branch.default`必须给出Block。所有路径的output_type必须等价。对外结果是选中路径输出,不允许绕过默认分支或引用仅部分路径存在的内部节点。
### PARALLEL:有限并行与汇合
`parallel.branches`为2–8项`{name,body}`,name在本节点内唯一,规则同字段名。分支分别使用进入该节点前的作用域;全部成功后汇合。节点结果为以分支name命名的OBJECT,例如`outputs.preview`通过source=`outputs`、path=`["preview"]`读取。没有任意交叉边、动态分支或任意JOIN节点。
### SIGNAL:等待输入
`signal`必填`name`(最多128)、`payload_version`(最多32)、`correlation`(STRING表达式)、`payload_type`和`timeout_ms`。名称规则同字段名;等待时限为正值且不超过流程总时限。correlation字面值必须非空且最多512字节,动态值在激活时再检查并冻结。节点输出为经payload_type验证的信号内容。
信号的提前到达、重复、激活关联、授权和竞态处理属于后续实例引擎;本次只验证并保存等待契约。
### TIMER:等待时间
`timer.delay_ms`为正值且不超过流程总时限;输出类型为NULL。等待不占业务Worker并发槽,实际持久化计时和恢复随后实现。
### POLL:有界重复查询
| 字段 | 规则 |
| --- | --- |
| task | 完整TASK配置,固定查询处理器与输入;只能查询既有作业,不能重复发起原业务提交 |
| max_rounds | 1–1000,包含首次查询;每轮单独Pulse任务,单轮重试不增加查询轮次 |
| timeout_ms | 正值,不超过流程时限;task.timeout_ms不得超过此值 |
| interval_ms | 至少1000,必须小于查询总时限;从“仍在处理”结果受理后起算,不补发错过轮次 |
| status_path | 可省略为空,引用task.result_type中的STRING枚举;空表示整个结果就是枚举 |
| pending / succeeded | 各至少1个枚举值 |
| failed / review | 可省略为空,与前两组互斥;四组必须无重复、完整覆盖状态枚举 |
| final_signal | 可选SIGNAL;类型必须等价于查询结果,timeout_ms必须等于查询总时限 |
查询成功且PENDING意味着继续等待;网络或执行错误才按该轮Pulse策略重试。两种预算独立,节点总时限不延长。最终信号不得是PENDING;轮次/时限耗尽、信号与查询同时到达的处理仍由后续运行器实现。发布格式中的配置不提供任意循环能力。
## 4. 整体预算与兼容
最多128个静态步骤(组合节点也计数),顶层块深度0,嵌套块深度不超过4;嵌套并行计算出的业务任务同时运行上界不超过32。SIGNAL/TIMER不占此业务任务并发。所有静态TASK的max_attempts加所有POLL的`max_rounds × max_attempts`不超过10000;条件各路径也全部计入保守预算,不依据当前输入缩减。
定义大小、JSON总深度、类型深度和块深度同时适用,任何一项超限都拒绝;不能仅满足步骤数就忽略深度。完整定义在调用方编码后才有最终字节大小。
结构版本1的既有定义解释必须兼容;将来若改变语义或冻结内容格式,应增加schema_version和独立校验/执行分支,不能原地修改旧版本。业务版本名由研发显式推进;运行实例固定版本及后续恢复兼容是P4–P7待验收项。