feat: publish immutable workflow definitions with typed SDK
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Weave 流程编排功能与设计
|
||||
|
||||
> 版本 0.2 · 2026-09-17。首版功能范围及研发定义发布方式已确认,包含有界重复查询和生产管理能力。具体字段、状态表示、算法及参数仍待技术评审;未实现、未验收。
|
||||
> 版本 0.3 · 2026-09-18。首版功能范围已确认。定义结构、发布校验与不可变版本已实现,见[定义格式](api/workflow-definition-format.md)和[发布API](api/workflow-definitions.md);下述实例推进、等待、查询与管理仍待P4–P5实现验收。
|
||||
|
||||
## 1. 职责与边界
|
||||
|
||||
@@ -30,13 +30,13 @@ Weave 不执行特定业务逻辑,也不把整段业务代码放入平台进
|
||||
|
||||
首版通过 SDK / 管理 API 提供运行查看与管理能力;后台操作界面可以调用这些 API,完整图形化控制台的交付范围另定。业务人员自由拖拽编排不纳入本次确认范围。
|
||||
|
||||
人工审核可以由业务系统完成,再提交经过授权的信号。Weave 记录提交者和证据,不代替业务系统判断“谁有权批准这笔账”。
|
||||
人工审核可以由业务系统完成,再提交经过授权的信号。Weave 记录提交者和证据,不代替业务系统判断“谁有权批准这次操作”。
|
||||
|
||||
## 3. 定义与实例身份
|
||||
|
||||
研发在代码中通过 Go SDK 描述步骤与规则,定义源码跟随业务项目进行版本管理和评审,再显式发布到 Orbit。业务服务每次启动不应自动覆盖已发布定义。
|
||||
|
||||
建议 SDK 将流程描述生成为可校验的 JSON 定义,表达步骤、输入映射、结果结构、条件、等待、时限和失败策略。Orbit 不执行上传的任意 Go 函数;业务计算和外部请求通过命名、版本化处理器完成。SDK 的构建 API、定义 Schema 及发布命令形式待协议评审。
|
||||
建议 SDK 将流程描述生成为可校验的 JSON 定义,表达步骤、输入映射、结果结构、条件、等待、时限和失败策略。Orbit 不执行上传的任意 Go 函数;业务计算和外部请求通过命名、版本化处理器完成。SDK采用强类型结构及显式引用,schema_version=1已按[定义格式](api/workflow-definition-format.md)实现,发布接口见[手册](api/workflow-definitions.md)。
|
||||
|
||||
发布前至少验证引用、可达性、顶层无环、分支穷尽性、结构化汇合、类型匹配与资源上限。有界重复查询封装为一个节点,在节点内部保存轮次和截止时间,不将次数上限展开成大量静态节点。定义发布需要独立权限和审计,版本内容不可变;重复发布同版本同内容可幂等确认,不同内容明确冲突。
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
| P1 任务受理闭环 | 应用凭据与作用域权限、队列、幂等提交、查询、待执行取消、受理事件;SDK 客户端 | API/SDK 创建查询闭环;重复键与内容冲突、响应未确认重报、跨命名空间拒绝、参数边界 | 已完成并通过阶段回归(见 P1 报告;真实断路/提交 ACK 丢失注入留后续故障阶段) |
|
||||
| P2 Worker 执行闭环 | WSS 接入、能力/容量、领取与开始、租约、续租、结果确认、排空与恢复;Worker SDK | 真 Worker 执行;失联/重连/重复确认/旧尝试拒绝;业务效果未知转核查;节点故障接管 | 已完成并通过阶段回归:服务端、自动 SDK、历史查询、完整 Schema 与真实进程强杀恢复;测试拓扑和剩余生产故障矩阵见 P2 验收报告 |
|
||||
| P3 Pulse 完整能力 | 安全重试、延时、Cron/固定间隔、漏跑策略、计划版本、运行中取消、并发许可、配额/背压、可靠结果订阅、批量受理、独立任务核查/人工重试、查询筛选与事务Outbox接入 | 多实例领取/触发竞争、重试上限、取消竞争、队列隔离、积压恢复、事件重复交付 | 已完成平台功能阶段验收:[原范围逐项核对](reports/phase-3.md)、[本轮完整回归](reports/phase-3-delay-recovery.md)。补齐相对延迟、改参数关联示例和四种重试全停恢复场景;20个可运行示例全部通过。全平台生产门槛及SDK首版交付剩余项仍按P6–P7推进 |
|
||||
| P4 Weave 主流程 | SDK 定义构建与发布校验、实例、顺序/分支/结构化并行汇合、信号/定时等待、版本绑定 | 重启接续、早到/重复信号、并行竞争、内部事件重放、发布版本兼容;端到端通用流程 | 下一阶段:先实现定义校验、不可变版本发布及独立SDK,再接实例推进与持久化等待 |
|
||||
| P4 Weave 主流程 | SDK 定义构建与发布校验、实例、顺序/分支/结构化并行汇合、信号/定时等待、版本绑定 | 重启接续、早到/重复信号、并行竞争、内部事件重放、发布版本兼容;端到端通用流程 | 定义格式/词法类型校验、不可变发布、独立SDK及六类节点定义例子已实现,已通过[子项验收](reports/phase-4-definitions.md);实例推进、事件接续与持久化等待仍待实现 |
|
||||
| P5 Weave 恢复与查询 | 有界查询、暂停继续、取消、人工核查恢复、控制门控与审计 | 轮次与尝试独立预算;暂停/开始/回执/超时竞争;恢复保留预算;未知结果不盲目重复 | 待开发 |
|
||||
| P6 生产验证与运维 | 完整监控、凭据轮换、备份恢复、滚动升级、运行手册、可复现负载和故障工具 | 对照生产验收清单执行,报告环境/指标/遗留项;容量、RPO/RTO 按真实拓扑验证 | 待开发 |
|
||||
| P7 首版交付核对 | SDK 兼容与发布准备、完整 API 手册、场景示例、全量回归及交付清单 | 新接入者按文档跑通全部示例;所有首版能力可追溯到实现与测试;报告实际生产边界 | 待开发 |
|
||||
@@ -83,6 +83,7 @@ SDK、文档与示例随 P1–P5 同步开发,P7 是全量核对,不是最
|
||||
| 业务事务Outbox | 业务记录/请求同事务 → 原键发送 → 受理/业务关联同事务 → 故障恢复 | P3,已实现独立模块与完整示例 |
|
||||
| 业务操作定位 | 精确业务键 → 创建区间 → 游标分页 → 查询详情 | P3,已实现完整示例 |
|
||||
| 独立任务人工恢复 | 未知结果 → 证据核查 → 保留原任务 → 关联新任务 → 审计查询 | P3,已实现完整示例 |
|
||||
| 研发定义发布 | 六类节点描述 → 校验/发布 → 原键确认 → 新版本 → 读取旧版本 | P4定义子项,[已实现示例](examples/workflow-definition.md) |
|
||||
| 并行生成结果 | 发布流程 → 并行执行 → 汇合 → 完成 | P4 |
|
||||
| 审核与外部回执 | 提交流程 → 等待信号 → 授权信号注入 → 继续 | P4 |
|
||||
| 外部作业轮询 | 提交一次 → 有界查询处理中状态 → 回执或最终结果 → 超限核查 | P5 |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Orbit HTTP / WebSocket 接口手册
|
||||
|
||||
更新:2026-09-17。接口实现状态随 [开发计划](../08-development-plan.md) 更新。
|
||||
更新:2026-09-18。接口实现状态随 [开发计划](../08-development-plan.md) 更新。
|
||||
|
||||
## 当前接口状态
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
| `/v1/schedules`、不可变版本、暂停/恢复及触发查询 | P3 已实现 | [计划接口与 SDK 场景](schedules.md) |
|
||||
| `/v1/subscriptions` 及管理、交付查询与重试 | 已实现 HTTP、管理 SDK 和完整管理示例 | [订阅手册](subscriptions.md) |
|
||||
| `/v1/events/connect` | 已实现 WSS、消息 Schema、连接 SDK 和自动消费器 | [消息协议](subscriptions.md#5-websocket-建连与边界) / [消费 SDK](../sdk/event-consumer.md) |
|
||||
| `/v1/workflow-definitions` 创建、发布与固定版本读取 | P4定义子项已实现,实例执行尚未实现 | [定义接口](workflow-definitions.md)、[格式规范](workflow-definition-format.md) |
|
||||
| `/v1/workflows` 与流程管理 | 计划 P4–P5,尚未实现 | [流程接口规划](workflows.md) |
|
||||
|
||||
未实现路由返回 404。健康检查就绪不表示任务执行、定时调度或流程引擎已经可用。
|
||||
|
||||
@@ -61,3 +61,5 @@ P3 应用额度管理新增 `application:resources:read` 和 `application:resour
|
||||
P3 独立任务核查、人工重试和操作审计分别增加 `tasks:review`、`tasks:retry`、`tasks:audit:read`,bootstrap显式 `--recovery-access` 才授予三项;默认凭据和 `--worker-access` 都不自动获得。核查/重试记录真实认证凭据及证据,读取任务详情仍需tasks:read,见[人工恢复](task-recovery.md)。
|
||||
|
||||
P3 结果订阅核心新增 `events:read`、`events:manage` 和 `events:consume`,bootstrap 仅显式 `--event-access` 时授予。订阅绑定创建凭据与单个队列,不能用同命名空间的另一张凭据消费或管理。当前 HTTP/WSS、管理及消费 SDK 已接入;凭据重绑继续开发,详见 [订阅接口](subscriptions.md)。
|
||||
|
||||
P4定义发布新增`workflows:definitions:read`与`workflows:definitions:publish`,仅显式`--workflow-access`授予。创建/读取元数据作用于命名空间,发布及读取完整版本额外校验全部引用队列;默认提交/Worker凭据不获此权限。发布不创建任务,不要求tasks:submit,详见[定义API](workflow-definitions.md)。
|
||||
|
||||
102
docs/api/workflow-definition-format.md
Normal file
102
docs/api/workflow-definition-format.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# 流程定义结构版本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待验收项。
|
||||
159
docs/api/workflow-definitions.md
Normal file
159
docs/api/workflow-definitions.md
Normal file
@@ -0,0 +1,159 @@
|
||||
# 流程定义与不可变版本
|
||||
|
||||
状态:P4 定义校验、持久化发布及独立 Go SDK 已实现;实例启动、推进、等待和恢复尚未实现。规则格式见[结构版本1](workflow-definition-format.md),可运行源码及命令见[研发发布场景](../examples/workflow-definition.md)。
|
||||
|
||||
## 1. 权限、传输与范围
|
||||
|
||||
使用 HTTPS、`Authorization: Bearer <token>`、统一 `request_id` 信封。POST 必须有唯一 `Idempotency-Key` 头及 `Content-Type: application/json`。请求体最多512 KiB,完整定义编码最多256 KiB,JSON总深度最多32;拒绝未知字段、大小写别名、重复字段、非法Unicode、无效数字和不符合类型的null。
|
||||
|
||||
| 接口 | 权限 | 范围 |
|
||||
| --- | --- | --- |
|
||||
| `POST /v1/workflow-definitions` | `workflows:definitions:publish` | 当前凭据命名空间 |
|
||||
| `GET /v1/workflow-definitions/{definition_id}` | `workflows:definitions:read` | 当前命名空间元数据,不返回规则 |
|
||||
| `POST /v1/workflow-definitions/{definition_id}/versions` | `workflows:definitions:publish` | 定义及其引用的全部队列 |
|
||||
| `GET /v1/workflow-definitions/{definition_id}/versions/{version}` | `workflows:definitions:read` | 定义及其引用的全部队列 |
|
||||
|
||||
发布与完整版本读取均在事务中核对队列存在、命名空间归属及当前凭据队列范围。发布不要求`tasks:submit`,不创建任务;发布者可以与运行方分权。默认Bootstrap凭据没有流程权限,显式`--workflow-access`才增加上述两个动作。读取元数据只受命名空间级定义权限限制。
|
||||
|
||||
GET不接受查询参数。当前没有定义列表、修改、删除或latest接口;调用方保存创建回执中的定义ID,并显式使用版本名。
|
||||
|
||||
## 2. 创建定义
|
||||
|
||||
`POST /v1/workflow-definitions`
|
||||
|
||||
| 字段 | 类型 | 规则 |
|
||||
| --- | --- | --- |
|
||||
| name | string | 必填,1–128 ASCII字符;首位字母或数字,其余可含`.`、`_`、`-`;同命名空间唯一且区分大小写 |
|
||||
| description | string | 可省略为空,最多1024个Unicode字符,不允许NUL |
|
||||
|
||||
```json
|
||||
{"name":"object.pipeline","description":"通用对象作业"}
|
||||
```
|
||||
|
||||
首次创建201,原键重报200。回执示意(实际ID、时间由服务端生成):
|
||||
|
||||
```json
|
||||
{
|
||||
"request_id":"0123456789abcdef0123456789abcdef",
|
||||
"data":{
|
||||
"definition":{
|
||||
"id":"1123456789abcdef0123456789abcdef",
|
||||
"namespace_id":"2123456789abcdef0123456789abcdef",
|
||||
"name":"object.pipeline",
|
||||
"description":"通用对象作业",
|
||||
"revision":"1",
|
||||
"created_at":"2026-09-18T00:00:00Z",
|
||||
"updated_at":"2026-09-18T00:00:00Z"
|
||||
},
|
||||
"deduplicated":false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`GET /v1/workflow-definitions/{definition_id}`的`data`直接返回上述`definition`对象。`revision`为字符串编码的uint64,初始1,每个新版本发布增加1。名称和说明在本阶段没有修改入口。原创建回执保留创建时的revision,当前值通过GET查询。
|
||||
|
||||
每个命名空间最多100个定义。不同键重用同一名称返回409;恢复创建结果必须使用原键,不能用名称猜测操作是否成功。
|
||||
|
||||
## 3. 发布版本
|
||||
|
||||
`POST /v1/workflow-definitions/{definition_id}/versions`
|
||||
|
||||
| 字段 | 类型 | 规则 |
|
||||
| --- | --- | --- |
|
||||
| version | string | 必填,1–64 ASCII字符,名称规则同上;研发指定的业务版本名,不与schema_version混用 |
|
||||
| specification | object | 必填,完整结构版本1定义;所有生效任务策略显式冻结 |
|
||||
| reason | string | 必填非空白,最多1024个Unicode字符,不允许NUL,写入发布审计 |
|
||||
|
||||
最小定义直接返回输入,可用于验证发布链路:
|
||||
|
||||
```json
|
||||
{
|
||||
"version":"v1",
|
||||
"reason":"initial developer release",
|
||||
"specification":{
|
||||
"schema_version":1,
|
||||
"input_type":{"kind":"STRING"},
|
||||
"timeout_ms":60000,
|
||||
"failure_policy":"REVIEW",
|
||||
"body":{
|
||||
"output_type":{"kind":"STRING"},
|
||||
"output":{"kind":"REFERENCE","reference":{"source":"input"}}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
首次发布201;原键重报或不同键的同版本同内容发布200。信封`data`为:
|
||||
|
||||
```json
|
||||
{
|
||||
"version":{
|
||||
"id":"3123456789abcdef0123456789abcdef",
|
||||
"namespace_id":"2123456789abcdef0123456789abcdef",
|
||||
"definition_id":"1123456789abcdef0123456789abcdef",
|
||||
"version":"v1",
|
||||
"specification":{
|
||||
"schema_version":1,
|
||||
"input_type":{"kind":"STRING"},
|
||||
"timeout_ms":60000,
|
||||
"failure_policy":"REVIEW",
|
||||
"body":{
|
||||
"output_type":{"kind":"STRING"},
|
||||
"output":{"kind":"REFERENCE","reference":{"source":"input"}}
|
||||
}
|
||||
},
|
||||
"content_digest":"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"published_by":"4123456789abcdef0123456789abcdef",
|
||||
"published_at":"2026-09-18T00:00:00Z",
|
||||
"analysis":{"steps":0,"max_concurrency":0,"max_task_attempts":0,"queues":[]}
|
||||
},
|
||||
"deduplicated":false
|
||||
}
|
||||
```
|
||||
|
||||
示意中的全零摘要不是上述请求的实际摘要。实际`content_digest`为64位小写十六进制SHA-256:对已校验结构的规范JSON加域前缀`orbit.weave.spec.v1\0`后计算。对象键顺序、数字的等值十进制表示不影响内容比较;数组顺序属于内容,包括枚举/状态分组数组。数字全程保留精度,不使用float64生成内容摘要。
|
||||
|
||||
`published_by`是最初发布凭据ID,`published_at`是原始数据库UTC时间;重复发布不改写。`analysis`按全部静态路径保守计算节点、并发与任务尝试上界,队列排序去重且始终为数组。它不是运行用量或已授予配额。
|
||||
|
||||
每个定义最多100个版本。达到上限仍可原键核对和同版本同内容确认。发布v2不改写v1。数据库不可变触发器拒绝UPDATE,关联关系由事务校验,无外键、无级联删除。
|
||||
|
||||
## 4. 幂等、并发及未知结果
|
||||
|
||||
- 创建操作按命名空间和`workflow.definition.create`隔离;发布按命名空间、`workflow.version.publish`及定义ID隔离。幂等键格式和90天保留窗口沿用[公共规则](tasks.md)。
|
||||
- 原键绑定整个命令,包括`reason`。原键不同内容为`IDEMPOTENCY_CONFLICT`;换键不允许覆盖已存在版本,不同规则为`STATE_CONFLICT`。
|
||||
- 不同键、相同版本及相同规则返回第一次的版本。后续请求的原因不替换原审计,不增加父定义revision,不重复产生发布审计。
|
||||
- 并发控制顺序为认证共享锁→应用额度行→操作身份→定义行→排序后的引用队列。定义、版本、父定义revision、审计和幂等回执同事务提交,审计失败全部回滚。
|
||||
- 任何超时、连接中断或503都可能发生在提交前后。保留原ID、版本、内容、原因和键核对,禁止生成新身份或盲目修改规则重发。
|
||||
- 每次重报仍核对当前权限和引用队列;权限被收回、队列缺失时不得用旧回执绕过。版本读取还验证存储原文、结构版本和内容摘要,损坏或不兼容数据返回503,不能默默忽略后继续使用。
|
||||
|
||||
## 5. 读取与错误
|
||||
|
||||
`GET /v1/workflow-definitions/{definition_id}/versions/{version}`的`data`直接返回上述`version`对象,200。输入版本名被严格限制,不能携带路径片段。
|
||||
|
||||
| 状态 / code | 处理 |
|
||||
| --- | --- |
|
||||
| 400 / INVALID_ARGUMENT | 修正结构、引用、类型、预算或字段;此校验拒绝不发布版本 |
|
||||
| 401 / UNAUTHENTICATED | 核对凭据与有效期 |
|
||||
| 403 / PERMISSION_DENIED | 缺少定义动作权限 |
|
||||
| 404 / NOT_FOUND | 定义/版本/队列不存在、不同命名空间或队列范围不允许;不据此猜测他人资源 |
|
||||
| 409 / IDEMPOTENCY_CONFLICT | 原键绑定不同命令;回查原操作,不直接换键 |
|
||||
| 409 / STATE_CONFLICT | 名称冲突或同版本不同规则;有意更新需显式发布新版本 |
|
||||
| 409 / WORKFLOW_DEFINITION_LIMIT | 命名空间达到100个定义,原创建回执仍可恢复 |
|
||||
| 409 / WORKFLOW_VERSION_LIMIT | 定义达到100个版本,旧版本确认与读取不受此上限影响 |
|
||||
| 413 / BODY_TOO_LARGE | 整个HTTP请求超过512 KiB |
|
||||
| 415 / UNSUPPORTED_MEDIA_TYPE | 必须使用application/json |
|
||||
| 503 / UNAVAILABLE | 服务/事务/存储完整性异常,原身份核对;持续异常需要运维核查 |
|
||||
|
||||
## 6. SDK
|
||||
|
||||
独立module为`git.yuntuo.hk/k2safe/orbit/sdk/go`,无服务端模型、数据库或ORM依赖。
|
||||
|
||||
| 方法 | 输入 → 返回 |
|
||||
| --- | --- |
|
||||
| `CreateWorkflowDefinition(ctx,key,in)` | CreateWorkflowDefinitionRequest → WorkflowDefinitionResult |
|
||||
| `GetWorkflowDefinition(ctx,id)` | 定义ID → WorkflowDefinition |
|
||||
| `PublishWorkflowVersion(ctx,id,key,in)` | PublishWorkflowVersionRequest → WorkflowVersionResult |
|
||||
| `GetWorkflowVersion(ctx,id,version)` | 定义ID及固定版本 → WorkflowVersion |
|
||||
| `WorkflowRef(source,path...)` | 构造有类型校验的引用表达式;发布时校验作用域 |
|
||||
|
||||
规则通过`WorkflowSpecification`、`WorkflowStep`等强类型结构构建,常量使用`json.RawMessage`,避免把大整数先转float64。SDK不复制服务端完整校验器;发布返回权威校验结果。网络错误不会自动重试发布,也不自动变更版本。完整示例见[发布场景](../examples/workflow-definition.md)。
|
||||
@@ -1,10 +1,9 @@
|
||||
# 流程接口规划
|
||||
# 流程接口状态
|
||||
|
||||
状态:计划 P4–P5,尚未实现。研发通过 Go SDK 描述流程并显式发布,服务端保存不可变定义版本。
|
||||
状态:定义格式校验、创建与不可变版本发布已实现,详见[定义接口](workflow-definitions.md)、[格式规范](workflow-definition-format.md)和[可运行SDK例子](../examples/workflow-definition.md)。实例执行与管理仍按P4–P5开发。下表仅列后续实例接口。
|
||||
|
||||
| 操作 | 候选接口 | 完成要求 |
|
||||
| --- | --- | --- |
|
||||
| 发布版本 | `POST /v1/workflow-definitions/{definition_id}/versions` | 图结构、类型、预算校验;同版本同内容幂等,不同内容冲突 |
|
||||
| 启动实例 | `POST /v1/workflows` | 固定版本并幂等启动,首批任务与实例原子创建 |
|
||||
| 查询实例 | `GET /v1/workflows/{workflow_id}` | 状态、暂停标记、版本、等待原因、预算摘要 |
|
||||
| 查询步骤 | `GET /v1/workflows/{workflow_id}/steps` | 步骤、激活、查询轮次、输入/结果引用与任务关联 |
|
||||
|
||||
@@ -2,6 +2,12 @@
|
||||
|
||||
示例只使用通用的作业、对象、文件、资源与审核信号,不包含接入方项目名称或行业规则。
|
||||
|
||||
## 已可运行:研发定义与发布流程
|
||||
|
||||
- [完整命令和结果](workflow-definition.md)、[SDK源码](../../sdk/go/examples/workflow-definition/main.go)。
|
||||
- 六类节点的有限结构定义、原键及同版本确认、新版本发布、旧版本读取保持不变。
|
||||
- 当前只发布定义,实例执行仍在P4–P5开发。
|
||||
|
||||
## 已可运行:业务事务与任务提交Outbox
|
||||
|
||||
- 独立模块:[task-outbox](../../examples/task-outbox/README.md),[完整前置、命令、Go方法及故障处理](task-outbox.md)。
|
||||
|
||||
54
docs/examples/workflow-definition.md
Normal file
54
docs/examples/workflow-definition.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# 研发定义与发布流程
|
||||
|
||||
本例运行真实HTTP发布与读取,验证六种节点的格式以及不可变版本。当前不创建流程实例、不执行外部业务。实例运行示例随P4–P5交付。
|
||||
|
||||
源码:[workflow-definition/main.go](../../sdk/go/examples/workflow-definition/main.go)。接口:[定义发布](../api/workflow-definitions.md);字段规范:[结构版本1](../api/workflow-definition-format.md)。
|
||||
|
||||
## 1. 准备与运行
|
||||
|
||||
使用专用开发环境,MySQL已完成当前迁移、服务已启动,配置方式见[SDK接入](../sdk/README.md)。从仓库根目录初始化专用发布凭据(ORBIT_MYSQL_DSN已在当前环境安全设置):
|
||||
|
||||
```sh
|
||||
bin/orbit-admin bootstrap --application definition-demo --namespace default --environment test --queue workflow --workflow-access --output /tmp/orbit-definition.credentials.json
|
||||
```
|
||||
|
||||
首次创建文件后保留,不要覆盖或打印凭据内容。该标志只增加定义读取和发布动作;生产凭据应限制到需要的命名空间及队列。
|
||||
|
||||
```sh
|
||||
cd sdk/go
|
||||
ORBIT_URL=http://127.0.0.1:8080 \
|
||||
ORBIT_CREDENTIALS_FILE=/tmp/orbit-definition.credentials.json \
|
||||
ORBIT_OPERATION_ID=object-definition-demo-001 \
|
||||
go run ./examples/workflow-definition
|
||||
```
|
||||
|
||||
开发回环地址可用HTTP,生产使用HTTPS。可改用`ORBIT_TOKEN`及`ORBIT_QUEUE_ID`,不把Token写入URL或提交版本库。不传`ORBIT_OPERATION_ID`时随机生成并先输出;发生未知结果时保存此操作ID,保持相同队列及源码再次运行。已成功的相同操作ID也可以重复执行,旧版本与revision不会增加。
|
||||
|
||||
## 2. 定义内容与调用链
|
||||
|
||||
输入契约为`{object_ref: STRING, operation: STRING, approved: BOOLEAN}`。示例依次定义:
|
||||
|
||||
1. `prepare`:对象准备TASK,引用input.object_ref,输出STRING。
|
||||
2. `route`:根据input.approved选择路径,带显式默认分支。
|
||||
3. `outputs`:并行定义preview与manifest两个TASK,全部成功后输出命名结果。
|
||||
4. `approval`:等待与input.operation关联的布尔审核信号。
|
||||
5. `settle`:1000毫秒TIMER等待。
|
||||
6. `result`:有界POLL查询,最多5轮、每轮最多2次尝试、总时限20秒;PENDING、DONE、FAILED、REVIEW四种状态完全分组,并声明可选最终回执。
|
||||
|
||||
实际调用:CreateWorkflowDefinition → PublishWorkflowVersion(v1) → 原键确认v1 → 新键同内容确认v1 → 发布v2 → GetWorkflowVersion(v1) → GetWorkflowDefinition。v2仅把整个流程时限从60秒改到90秒;测试确认v1内容和原发布身份保持不变。
|
||||
|
||||
可直接在自己的Go代码中构建强类型`orbit.WorkflowSpecification`;`orbit.WorkflowRef("input","object_ref")`生成引用。常量使用`json.RawMessage`保留精确JSON数字。条件、步骤与处理器都在研发代码中声明,不上传任意可执行代码。
|
||||
|
||||
## 3. 预期输出与异常
|
||||
|
||||
输出包含操作ID、定义ID、v1/v2版本记录ID以及以下静态校验结果:
|
||||
|
||||
```text
|
||||
revision=3
|
||||
steps=8 max_concurrency=2 max_task_attempts=13
|
||||
Both definitions are stored. No workflow instance or business task has been started.
|
||||
```
|
||||
|
||||
HTTP响应未知时使用原操作ID及相同源码核对,不临时更换版本或键。若有意更改v1内容则返回409,需研发评审并显式发布新业务版本。缺少定义权限为403;引用队列不存在或越权为404;类型/引用/预算错误为400。审计失败不会留下半个发布版本,持续503需核查存储及服务状态。
|
||||
|
||||
本例保留定义和发布审计,不直接删库清理;目前没有删除接口。每命名空间最多100个定义,每定义100个版本,重复运行优先复用操作ID。完整隔离回归由`scripts/test-mysql.sh`负责数据库销毁,不能对共享环境做硬删除。
|
||||
48
docs/reports/phase-4-definitions.md
Normal file
48
docs/reports/phase-4-definitions.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# P4 子项:定义校验与不可变发布
|
||||
|
||||
日期:2026-09-18。本子项已通过验收。范围是研发定义格式、静态校验、定义创建、版本发布/读取及独立SDK。实例启动、推进、信号/时间等待、暂停/恢复和轮询执行仍未实现;本报告不构成P4整体或生产高可用验收。
|
||||
|
||||
## 实现
|
||||
|
||||
- `weave/definition`提供schema_version=1结构及类型契约,六类节点、词法引用、条件、并行汇合和有限预算校验。不会执行上传源码。
|
||||
- 创建/发布/读取四个HTTP路由,两个显式权限与`--workflow-access`初始化标志。API严格匹配字段,映射值递归检查;仅DSL常量允许显式null,普通任务参数限制保持不变。
|
||||
- 复用现有两张定义表,未新增迁移、外键、级联或数据库依赖。发布在应用→身份→定义→队列顺序下串行化,版本/revision/审计/回执同事务。中文字段注释随代码保留。
|
||||
- 同键绑定完整命令,同版本按规则摘要比较;数字使用精确JSON规范化。读取核对原文及结构摘要,损坏或悬空关联拒绝;重复请求仍检查当前队列权限。
|
||||
- 独立SDK强类型定义、引用构建及四个客户端方法;完整六类节点发布例子和[API](../api/workflow-definitions.md)、[格式](../api/workflow-definition-format.md)、[场景](../examples/workflow-definition.md)同步。
|
||||
|
||||
## 回归证据
|
||||
|
||||
环境:macOS arm64,Go 1.27.1;Docker隔离MySQL 8.4.10,随机秘密/回环端口,由脚本创建并清理临时容器,不连接已有业务库。
|
||||
|
||||
| 检查 | 结果 |
|
||||
| --- | --- |
|
||||
| make fmt / test(race)/ vet / build | 通过;覆盖服务端、SDK与独立Inbox/Outbox模块 |
|
||||
| DSL定向单测 | 顺序/分支/并行类型与作用域、禁用前向/跨分支引用、默认路径、策略完整性、轮次与尝试预算、状态完整分组、深度/数量上限、精确数值与非变更检查通过 |
|
||||
| HTTP严格JSON | 嵌套map大小写别名/未知字段/重复键/null集合拒绝;DSL显式null常量可用,普通任务null仍拒绝 |
|
||||
| 数据校验模糊测试 | 2个并行worker、10秒目标,15699次执行,通过(工具耗时11.278秒) |
|
||||
| 真MySQL发布定向回归 | `TestIntegrationWorkflowDefinitions -count=3`通过,总12.756秒;包含并发、权限、无外键关联、回滚、损坏及数量上限 |
|
||||
| 真HTTP提交后回执丢失 | 新SDK集成回归通过,1.314秒;服务确认201后代理断开连接,首次调用明确报错,原键重报返回同一版本,revision不重复增长 |
|
||||
| 六类节点可运行发布例子 | 通过;v1/v2发布及旧版读取,revision=3、steps=8、max_concurrency=2、max_task_attempts=13;没有启动实例 |
|
||||
| 独立SDK依赖 | GOWORK=off列出依赖,不包含服务端internal/model/platform/pulse/weave、MySQL或ORM |
|
||||
| 完整隔离链路 | scripts/test-mysql.sh终态退出0;所有19个SDK例子及独立Inbox/Outbox两个例子通过,临时容器已清理 |
|
||||
|
||||
并发用例以12个调用竞争6个幂等身份,均取得同一不可变版本,只有一次新发布;随后验证等值小数重报、相邻大整数内容冲突、v2不改变v1、审计次数与父revision,数据库触发器拒绝直接UPDATE。发布不产生Pulse任务。
|
||||
|
||||
权限用例覆盖默认凭据无定义权限、原回执队列权限收回、跨命名空间队列/定义、不存在的父定义/队列、手工删除关联后的拒绝。真实数据库断言外键为0。
|
||||
|
||||
故障用例通过隔离库审计写入失败使版本/父revision/幂等身份全部回滚,再用原键成功发布;另外新增损坏摘要记录及删除父记录,确认读取失败。100个定义/100个版本上限真实由API填满,达到上限仍恢复旧回执。
|
||||
|
||||
首次完整回归在发布人读取上发现VARCHAR文本标识被当作BINARY ID扫描;修正为文本读取后再校验ID。三次定向回归已覆盖修正。本报告保留此失败记录,未将此前未到达的SDK链路视为通过。
|
||||
|
||||
|
||||
最终完整回归中,存储集成108.239秒(定义子项2.42秒),Worker SDK91.133秒,计划5.782秒,队列4.458秒,批量1.378秒,查询1.335秒,订阅管理33.363秒,事件消费52.103秒,任务恢复3.418秒,定义SDK1.314秒;独立Inbox35.669秒、Outbox33.839秒,应用额度1.481秒。10个SDK进程故障父用例全部通过,总95.274秒,其中重试全停恢复四场景33.10秒;独立Inbox/Outbox另各有一个进程故障父用例。本次全链路零失败,已确认终态退出及容器清理,没有以日志片段或等待超时替代完成结论。
|
||||
|
||||
复现:`make fmt test vet build`、`make integration`;定向用例为`go test -race -count=3 -run '^TestIntegrationWorkflowDefinitions$' ./internal/storage/mysql`(只在隔离库设置ORBIT_TEST_MYSQL_DSN)。SDK定义用例在全量脚本中使用专门签发的流程权限运行。最后完整回归后仅补文档证据,没有修改运行代码。
|
||||
|
||||
## 后续边界
|
||||
|
||||
P4下一步是启动实例、固定版本与输入、同事务创建首批任务、内部事件接续和有界推进;继而交付顺序/条件/并行、信号与持久化定时等待。P5补齐轮询运行、门控、取消及有证据人工恢复。现在发布格式支持节点,不等于节点运行器已存在。
|
||||
|
||||
启动时必须再次核对定义版本、当前权限、队列与实际运行参数;JSON来源可能为null或超出Pulse字段限制,不能以静态校验代替运行校验。数据库列、已保存规则和SDK版本兼容都需要进入后续升级回归。
|
||||
|
||||
独立发布操作的数据库COMMIT回执丢失尚未单独注入;已有回滚及HTTP提交后回执丢失场景不能替代全部存储故障。定义列表、删除/归档、配置化额度、凭据轮换、容量、MySQL故障切换、备份和滚动升级继续按P6–P7处理;不承诺未经验证的生产吞吐和可用性。
|
||||
@@ -198,3 +198,7 @@ P2 已提供底层协议、[自动 Worker 运行器及示例](worker-runtime.md)
|
||||
## 订阅管理示例
|
||||
|
||||
[完整运行方法](../examples/subscriptions.md) 使用显式 --event-access 凭据,执行创建/同键核对/暂停/恢复/查询,再暂停本次订阅并保留审计。源码见 [examples/subscriptions](../../sdk/go/examples/subscriptions/main.go)。WSS 连接 SDK 与自动消费器见 [消费手册](event-consumer.md),可运行 [协议示例](../examples/event-protocol.md) 验证跨连接 ACK;[持久化 Inbox 示例](../examples/result-inbox.md) 已独立交付,核心SDK不新增数据库驱动。
|
||||
|
||||
## 流程定义发布
|
||||
|
||||
已提供独立WorkflowSpecification类型及CreateWorkflowDefinition、GetWorkflowDefinition、PublishWorkflowVersion、GetWorkflowVersion四个HTTP方法。业务侧研发显式发布,服务端冻结版本;当前不包含实例执行方法。见[接口与字段](../api/workflow-definitions.md)、[结构版本1](../api/workflow-definition-format.md)、[完整可运行场景](../examples/workflow-definition.md)。
|
||||
|
||||
Reference in New Issue
Block a user