213 lines
20 KiB
Markdown
213 lines
20 KiB
Markdown
# Weave 流程编排功能与设计
|
||
|
||
> 版本 0.5 · 2026-09-18。首版功能范围已确认。定义结构、发布校验与不可变版本已实现,见[定义格式](api/workflow-definition-format.md)和[发布API](api/workflow-definitions.md);[实例受理](11-workflow-admission.md)、[结果消费与根推进](12-workflow-runtime.md)、[TIMER与POLL时钟](13-workflow-clock.md)已接入。[信号等待及最终查询竞争](14-workflow-signals.md)已接入内部运行器;完整管理及实例公共API/SDK仍待P4–P5实现验收。
|
||
|
||
## 1. 职责与边界
|
||
|
||
Weave 保存“流程到了哪一步、下一步何时可以开始、正在等待什么”。Pulse 保存“任务交给谁执行、执行权是否有效、能否安全重试、结果是什么”。公共身份、权限、协议、审计和存储由 Orbit 统一提供。
|
||
|
||
Weave 不执行特定业务逻辑,也不把整段业务代码放入平台进程。实际工作通过 Pulse 派给业务 Worker,业务系统负责业务正确性、幂等、外部结果核查与授权。
|
||
|
||
首版由研发通过 Go SDK 描述、发布流程,业务处理器仍在业务 Worker 中执行。技术上建议采用显式流程定义与持久化状态机,根据已保存的定义、步骤结果和信号计算推进,不实现任意 Go 业务函数的执行历史重放。
|
||
|
||
## 2. 已确认的首版能力
|
||
|
||
| 能力 | 行为与边界 |
|
||
| --- | --- |
|
||
| 顺序步骤 | 前一步达到定义的完成条件后,创建下一步任务 |
|
||
| 条件分支 | 基于已保存、经过类型校验的结果或信号选择路径;不执行任意脚本 |
|
||
| 有限并行与汇合 | 建议先支持结构化并行分支、全部成功后汇合;限制分支数,不默认支持任意交叉汇合 |
|
||
| 等待业务信号 | 持久化等待回执、审核结果等外部输入,不长期占用 Worker |
|
||
| 定时等待 | 持久化截止时间,由平台到期索引扫描唤醒,不占业务Worker |
|
||
| 有界重复查询 | 外部业务尚在处理中时按间隔查询,达到次数或总时限后转人工核查;不与 Pulse 执行重试混用 |
|
||
| 暂停与继续 | 暂停后停止推进新步骤,继续接收在途结果;恢复后从已保存进度继续 |
|
||
| 异常与人工恢复 | 保存失败或未知结果,按定义暂停相关推进并核查;干预必须有权限、原因与证据 |
|
||
| 取消 | 阻止新步骤,持久化下游取消意图,等待已开始工作的可确认结果 |
|
||
| 查询与审计 | 查询流程版本、每步输入/结果引用、关联任务、执行次数、查询轮次、等待原因、信号、人工操作与状态转换 |
|
||
| 版本固定 | 实例绑定不可变定义版本及实际生效配置,发布新版本不改变运行实例 |
|
||
|
||
完整审批产品、可视化编辑器、任意循环、动态无限展开、子流程、跨库流程迁移及运行中替换定义不默认进入首版。有界重复查询作为明确受限的节点能力纳入首版,不开放任意回边或无限循环。是否需要补偿步骤及其首版范围另行讨论。
|
||
|
||
首版通过 SDK / 管理 API 提供运行查看与管理能力;后台操作界面可以调用这些 API,完整图形化控制台的交付范围另定。业务人员自由拖拽编排不纳入本次确认范围。
|
||
|
||
人工审核可以由业务系统完成,再提交经过授权的信号。Weave 记录提交者和证据,不代替业务系统判断“谁有权批准这次操作”。
|
||
|
||
## 3. 定义与实例身份
|
||
|
||
研发在代码中通过 Go SDK 描述步骤与规则,定义源码跟随业务项目进行版本管理和评审,再显式发布到 Orbit。业务服务每次启动不应自动覆盖已发布定义。
|
||
|
||
建议 SDK 将流程描述生成为可校验的 JSON 定义,表达步骤、输入映射、结果结构、条件、等待、时限和失败策略。Orbit 不执行上传的任意 Go 函数;业务计算和外部请求通过命名、版本化处理器完成。SDK采用强类型结构及显式引用,schema_version=1已按[定义格式](api/workflow-definition-format.md)实现,发布接口见[手册](api/workflow-definitions.md)。
|
||
|
||
发布前至少验证引用、可达性、顶层无环、分支穷尽性、结构化汇合、类型匹配与资源上限。有界重复查询封装为一个节点,在节点内部保存轮次和截止时间,不将次数上限展开成大量静态节点。定义发布需要独立权限和审计,版本内容不可变;重复发布同版本同内容可幂等确认,不同内容明确冲突。
|
||
|
||
| 身份 | 用途 |
|
||
| --- | --- |
|
||
| `definition_id` / `definition_version` | 稳定定义与不可变版本 |
|
||
| `workflow_id` | 一次流程实例;启动请求重试返回原实例 |
|
||
| `step_id` / `activation_id` | 定义中的步骤与该步骤一次具体激活,区分后续人工恢复 |
|
||
| `task_id` / `attempt_id` | Pulse 的一次任务与执行尝试,不能与流程或步骤身份混用 |
|
||
| `poll_round` | 同一次查询节点激活内的查询轮次;一轮关联一个 Pulse 任务,可包含多次执行尝试 |
|
||
| `signal_id` / 关联键 | 信号去重及匹配指定实例、步骤激活或业务操作 |
|
||
|
||
启动时绑定明确的定义版本、参数版本、处理器兼容要求和策略快照。若允许以“当前版本”启动,首次受理时解析并固定;相同幂等键重报仍返回首次绑定的实例。
|
||
|
||
初次启动的幂等键至少在命名空间和操作类型内唯一。同键不同语义输入必须冲突;不因新定义发布就生成另一份流程。
|
||
|
||
## 4. 建议状态模型
|
||
|
||
流程状态与任务状态分别管理,不能用“最后一个任务成功”替代整个流程的成功条件。
|
||
|
||
| 流程状态 | 含义 |
|
||
| --- | --- |
|
||
| `RUNNING` | 存在可推进步骤或仍在执行/排队/退避的任务 |
|
||
| `WAITING` | 没有可立即推进的步骤,剩余路径等待信号或时间 |
|
||
| `CANCELLING` | 已接受取消意图,正在确认关联工作的停止或结果 |
|
||
| `NEEDS_REVIEW` | 存在阻塞推进的失败、未知效果或需人工处理事项 |
|
||
| `SUCCEEDED` | 所有要求完成的路径和汇合条件已经满足 |
|
||
| `FAILED` | 已确定无法完成,且所有已激活工作均已结清或确认停止 |
|
||
| `CANCELLED` | 取消已完成;不表示历史上已成功的业务效果被撤销 |
|
||
|
||
存在未知副作用时不能进入一个暗示“全部已结清”的终态。建议异常核查优先显示为 `NEEDS_REVIEW`,同时保留取消意图及每个分支的真实状态;状态汇总优先级在协议评审中固定。
|
||
|
||
暂停建议用独立持久化标记 `paused` 与控制版本表达,不覆盖上述执行状态:实例可以同时显示“已暂停”和“有任务执行中”或“待核查”。恢复仅解除暂停,不自动解除核查或撤销取消。具体字段与汇总展示规则仍待协议评审。
|
||
|
||
步骤单独保存等待前置条件、等待任务、等待信号/时间、完成、失败、跳过或待核查等阶段及状态版本。步骤任务排队不代表业务已经运行;详情应展示 Pulse 的实际执行阶段。
|
||
|
||
实例终态不静默回退。对已结束流程重新执行,建议创建带来源关联的新实例,重新校验业务幂等;首版是否支持从已完成步骤继续、以及需要哪些业务证据,另行评审。
|
||
|
||
## 5. Pulse 与 Weave 的事务协作
|
||
|
||
首版两个模块处于同一 MySQL 事务范围,通过应用层接口明确传递事务上下文,不互相任意写表。
|
||
|
||
| 操作 | 原子提交内容 |
|
||
| --- | --- |
|
||
| 启动流程 | 启动幂等记录、实例与首批激活步骤、对应 Pulse 任务、状态事件 |
|
||
| 保存任务结果 | Pulse 任务/尝试结果、额度释放、结果事件及内部交付记录 |
|
||
| 接续任务结果 | 核对实例与步骤激活、消费去重、步骤变化、流程推进、后续任务或等待记录、内部事件处理确认 |
|
||
| 建立定时等待 | 步骤等待条件、截止时间、对应的 Pulse 内部定时任务 |
|
||
| 接收信号 | 幂等记录、信号内容与身份、持久化待处理记录 |
|
||
| 消费信号 / 定时唤醒 | 校验等待条件与状态版本、消费标记、流程推进、后续任务创建 |
|
||
| 查询轮次推进 | 校验暂停/取消、轮次/时间预算,创建唯一轮次记录与对应任务,或保存下一次唤醒 |
|
||
| 暂停 / 继续 | 控制标记与版本、通用执行门控、管理审计、必要的持久化待续推进记录 |
|
||
|
||
内部结果交付可使用公共持久化事件表加 `workflow_inbox` 记录。事件生成与交付记录必须跟随 Pulse 的状态变化一起提交,不能先提交任务再仅通过内存调用 Weave。
|
||
|
||
任务自动重试期间步骤仍关联原任务;任务进入 `NEEDS_REVIEW` 时发送内部状态事件,让流程可见地进入核查。任务后来被核查确认为终态时,再由新的状态版本事件推进。
|
||
|
||
处理事件时校验命名空间、流程、步骤激活、查询轮次、当前任务 ID 与源状态版本。重复事件只能产生一次推进;旧激活或旧轮次的迟到事件保留记录,不启动当前激活的后续步骤。并行汇合在短事务内协调同一实例/汇合点状态,确保后继任务只生成一次。
|
||
|
||
同一实例的一次推进有步骤数和耗时预算。超过预算时原子保存检查点和待续推进记录,再由有界扫描继续;不能提交部分展开状态后只依赖内存继续循环。
|
||
|
||
这套内部交付不经过对外 WS 订阅。WS 用于业务 Worker 通信或业务结果通知,不承担两个模块之间唯一的可靠通道。
|
||
|
||
## 6. 信号与持久化等待
|
||
|
||
### 6.1 信号与时间唤醒
|
||
|
||
信号携带稳定幂等身份、目标实例、信号类型、目标步骤/业务操作关联、参数版本及证据引用。认证身份与提交范围由服务端核验,不能仅凭流程 ID 注入信号。
|
||
|
||
- 实例已经存在但尚未进入等待时,允许将匹配该定义的早到信号持久化;达到匹配条件后再消费。
|
||
- 实例不存在时明确返回未找到,不创建无归属信号。业务侧先完成幂等启动,再通过 Outbox 补交信号。
|
||
- 相同信号 ID、相同语义内容返回原受理结果;不同内容明确冲突。
|
||
- 一次等待默认消费一次匹配信号;广播、多次聚合和跨实例信号不隐式支持。
|
||
- 信号关联必须能区分具体业务操作,不能只按“审核通过”等类型匹配,避免旧业务批次、旧步骤或旧恢复轮次的信号误用。
|
||
- 信号受理成功只表示已可靠保存,消费与步骤推进状态可另外查询。
|
||
|
||
定时等待使用已保存的截止时间和内部定时任务。定时唤醒由平台执行角色处理,不需要业务 Worker 长期占用连接槽位。任务结果与后续等待消费仍遵守幂等和事务规则。
|
||
|
||
信号、超时与取消竞争时,按等待记录的状态版本原子决定结果。采用信号持久化受理时间与等待截止时间判断是否按时到达,不能因消费积压把已经按时受理的信号误判为超时;截止点的包含规则待协议冻结。取消另一条唤醒路径后,迟到事件只留痕,不再次推进。
|
||
|
||
未匹配信号数量、参数大小、保留时间与等待时限必须有上限。到期清理需要可观测且有明确规则,不能悄悄丢掉仍有效的等待依据。
|
||
|
||
### 6.2 有界重复查询
|
||
|
||
**功能已确认**:查询成功但外部业务仍在处理中,由 Weave 等待后发起下一轮;查询请求失败,由 Pulse 在当前轮次内按安全策略重试。达到轮次或总时限上限后转人工核查,不直接认定外部业务失败。
|
||
|
||
以下为实现建议,具体字段与边界待技术评审:
|
||
|
||
| 内容 | 建议约束 |
|
||
| --- | --- |
|
||
| 查询目标 | 固定查询处理器、版本和外部业务操作标识;恢复查询不能重新调用提交接口 |
|
||
| 轮次上限 | `max_rounds` 为有限正整数;创建轮次记录与查询任务时原子计数,不因重复事件或重启重复增加 |
|
||
| 总时限 | 从节点激活时固定 `deadline_at`;建议同时设置轮次与时间上限,先到者阻止新一轮 |
|
||
| 查询间隔 | 建议从上一轮完成且结果仍为处理中时计算下一次时间,可设有上限的退避与抖动;不按错过的间隔集中补跑 |
|
||
| 单轮执行重试 | Pulse 使用独立且有限的尝试预算,自动重试保持该轮任务 ID;受节点剩余时限约束 |
|
||
| 结果映射 | 明确区分处理中、业务确认成功、业务确认失败和需要核查;未知值不能默认为成功或继续循环 |
|
||
|
||
查询任务自身成功表示取得了一份有效结果。其中“处理中”使 Weave 保存等待与下一次唤醒;最终业务结果则结束查询节点,按定义推进或进入失败处理。单轮请求重试耗尽应转核查,不能通过新建一轮绕过已耗尽的重试预算。
|
||
|
||
每轮只创建一个查询任务,以命名空间、实例、步骤激活和轮次形成稳定去重身份。轮次之间释放业务 Worker 槽位,等待依赖数据库记录与平台到期索引扫描;SDK 不在处理器中长期 sleep 或维护内存轮询循环。
|
||
|
||
2026-09-18实现决策:TIMER/POLL直接复用`weave_pending_advances`检查点和后台扫描,替代早期草案的Pulse内部唤醒任务。唤醒只改变流程持久状态,不调用业务处理器,因此无需额外占用任务/尝试/许可记录;业务查询仍由Pulse执行。当前schema使用固定间隔,不提供业务轮次抖动或变长退避,具体冻结和升级行为见[运行约定](13-workflow-clock.md)。
|
||
|
||
发布和受理时校验轮次、单轮尝试、超时和总时限的组合上限,避免两层次数相乘后超过外部渠道或平台预算。未完成上一轮前不得并发启动下一轮。最后一轮仍为处理中、等待到期或当前轮次重试耗尽时,保存核查原因及已知结果。
|
||
|
||
截止时间到达后不再授权新查询或其执行重试;已经授权的请求仍需收集结果。迟到结果可保存为证据,不自动清除到期后的核查状态。建议以结果持久化受理时间而非内部事件消费时间判断是否按时到达,避免消费积压造成误判。
|
||
|
||
若查询期间也允许接收业务最终回执,回执与查询结果竞争同一等待/激活版本,只能完成一次。最终回执胜出后停止后续轮次;在途只读查询仍收集结果并审计,迟到或冲突结果不得再次推进或覆盖已确认结果。
|
||
|
||
## 7. 重试、失败与人工干预
|
||
|
||
### 7.1 暂停与继续
|
||
|
||
**功能已确认**:暂停阻止新步骤推进,保留已完成进度,继续接收在途结果与外部回执;继续操作从持久化进度恢复。暂停不表示已经停止外部业务操作。
|
||
|
||
以下细则为设计建议:
|
||
|
||
- 暂停与继续带预期控制版本、稳定操作身份、操作人及原因;状态与审计一起提交。新步骤创建必须原子检查控制版本。
|
||
- 建议暂停还阻止关联任务的新领取、开始授权和执行重试,包含已经创建但尚未开始的任务。由 Pulse 的通用执行门控与 Weave 控制状态同事务更新,领取/开始时读取权威门控,避免仅暂停流程循环却继续派发旧队列任务。
|
||
- 暂停前已获得开始授权的尝试仍可运行、续租和上报,保留时限与安全约束。暂停与开始竞争按事务顺序决定;“暂停成功”只表示门控已持久化,不表示所有在途请求已停止。
|
||
- 在暂停期间可靠保存任务结果、信号和到期事实,必要时进入核查或结清已有工作;不创建新的业务步骤或查询轮次。即使内部事件已确认消费,也要保存待续推进状态,避免恢复后无事件可推进。
|
||
- 建议暂停不延长原业务截止时间,查询节点、任务时限与信号有效期继续计时。恢复时先核对已受理结果、信号和原截止时间,不能把过期查询重新激活;时间策略在协议冻结前确认。
|
||
- 恢复按配额和推进预算处理积压,不重置已用查询轮次和执行尝试,不补发每一个错过的查询时间点。恢复不改变原流程版本,不清除取消或待核查条件。
|
||
|
||
### 7.2 执行失败与人工恢复
|
||
|
||
一个业务步骤的自动执行重试归 Pulse 管理。Weave 不对 Pulse 的每次暂时失败再创建新任务,也不叠加另一层指数重试。
|
||
|
||
建议步骤最终失败后,按固定策略进入流程核查或结束处理。并行分支部分失败时,不创建依赖该汇合点的后续步骤;按定义停止新派发、请求取消其余活动分支并收集结果。只有所有活动工作均已结清且没有未知效果,才可按策略进入失败终态。
|
||
|
||
对仍处于核查中的流程进行人工重试时,必须通过 Weave 的恢复入口:
|
||
|
||
1. 校验权限、当前状态版本、步骤归属、失败类别与副作用证据。
|
||
2. 确认符合安全重试条件;“未收到响应”本身不构成条件。
|
||
3. 在一个事务内记录管理操作,创建新的步骤激活及关联 Pulse 任务,并固定关联关系。
|
||
4. 保留旧激活与旧任务结果,沿用恰当的业务幂等身份。
|
||
|
||
这是人工恢复的建议模型,具体 API 在评审后冻结。普通任务人工重试入口应拒绝绕过流程管理的关联任务请求。已经确认成功的步骤不能通过“重试流程”随意再执行一次。
|
||
|
||
取消和补偿是不同业务操作。若未来增加补偿,补偿本身也必须是有权限、可审计、可重试或可核查的业务步骤;不能宣称撤销流程就能撤回已经生效的外部业务操作。
|
||
|
||
## 8. 通用接入示例
|
||
|
||
以下只展示模块协作,不替代接入方的业务规则与审核:
|
||
|
||
```text
|
||
业务系统提交外部作业处理流程
|
||
→ Pulse 执行输入校验任务
|
||
→ Weave 按结果进入业务审核信号等待
|
||
→ Pulse 执行数据准备任务(业务侧保证同一操作幂等)
|
||
→ Pulse 执行外部作业提交任务
|
||
→ Weave 等待回执信号,或通过有界重复查询节点获取最终结果
|
||
→ 根据业务确认的最终结果完成 / 进入核查
|
||
```
|
||
|
||
“外部作业提交任务成功”可能仅代表渠道受理,不能直接等同于外部作业最终成功。首版有界重复查询节点负责受限轮询,业务方也可以在平台外负责回执采集,再以信号推进流程。查询和核查围绕原外部操作身份进行,不能因没有最终结果就重复提交外部作业。
|
||
|
||
## 9. 容量、版本与验收
|
||
|
||
租户数不等于流程并行分支数。禁止将大规模跨租户批处理塞入一个无界流程;按业务单元创建受限实例,批量启动也要配额、背压和逐项幂等。
|
||
|
||
限制实例步骤数、并行度、查询轮次、单轮重试、每次推进量、输入/输出大小、信号积压与历史保留量。长时间等待只保留持久化状态;扫描依赖到期索引和待处理记录,不能全表遍历所有等待实例。
|
||
|
||
旧定义、参数解释与处理器版本在仍有运行实例时必须保持可用,或明确进入可观测的版本不兼容等待;升级不能悄悄把旧实例转到新逻辑。
|
||
|
||
功能范围已确认。实施前仍需评审:SDK 构建 API、定义 Schema、分支表达式、并行失败策略、暂停门控及计时规则、轮询预算与截止边界、人工恢复身份模型、协议字段、资源上限与保留周期。验收覆盖 [生产验收](05-production-acceptance.md) 的流程场景,尤其是暂停竞争、轮次恢复、查询与回执竞争及版本发布。
|
||
|
||
## 10. 决策记录
|
||
|
||
- 0.1:提出流程功能草案,Weave 首版范围待讨论。
|
||
- 0.2:确认研发通过 Go SDK 定义发布,确认顺序、分支、并行汇合、信号和定时等待,将有界重复查询纳入首版;确认暂停/继续、取消、人工核查恢复、版本固定与全程追踪。具体技术细则保留为建议,尚未通过实现验证。
|
||
|
||
公共数据约束见 [可靠性与数据模型](04-reliability-and-data.md),对外接口草案见 [HTTP 与 WS 协议](03-http-websocket-protocol.md)。
|