Files
orbit/docs/10-workflow-engine-core.md

8.4 KiB
Raw Blame History

Weave 执行决策与内部结果交付

状态:P4 内部基础已实现。已接通Pulse结果到Weave持久化Inbox,并提供有限步骤决策器;实例受理和首批存储适配已补齐。Inbox消费推进及根检查点运行器已接入;定时和查询时钟已接入,信号运行器及实例公共API/SDK仍待实现。不能把本页能力解释成完整公开端到端流程已交付。

1. 为什么结果要独立持久化

任务已执行成功之后,流程节点可能立即退出。依赖进程内回调会丢失后继工作;从可变任务当前状态读取历史结果,也可能把后来的核查决定误当成旧事件。

当前结果事务顺序如下,任何一步失败均回滚:

flowchart LR
  A[更新Pulse任务和尝试] --> B[结算执行许可与用量]
  B --> C[写入原始状态事件]
  C --> D[核验流程激活归属]
  D --> E[写入Weave Inbox和冻结快照]
  E --> F[锁定对外结果流并写入结果日志]
  F --> G[写入审计和执行回执]
  G --> H[提交事务]

普通任务和计划任务仍使用原有结果链路,不产生Weave Inbox。流程任务使用owner_kind=workflow_activation、owner_id=激活ID;TASK直接关联激活task_id,POLL通过轮次记录关联。所有关系均限定同一命名空间,核对步骤、实例、门控、固定定义和版本,不使用外键。

已实现的内部交付触发为task.succeeded、task.failed、task.cancelled、task.needs_review。任务暂时失败并等待自动重试,不新增流程激活或内部结果事件。相同完成回执重报不产生第二个事件;同一来源任务状态版本还有独立唯一约束。

发布后使用旧激活的在途结果仍保留原激活身份;生产者不自行判定是否推进当前激活。当前消费者识别旧激活/旧轮次并留痕,不能将其用于当前工作。

生产者在现有结果快照查询中一起读取所有者和关联标记;普通结果不增加一次单独网络查询。流程关联核验使用只读关联查询,不在已持有任务锁后再锁实例、步骤或对外订阅。内部Inbox写入发生在外部结果流行锁之前,保持既有锁顺序。

2. 数据模型与升级

迁移000017_workflow_result_inbox为weave_inbox新增四个中文注释字段:

字段 含义
source_task_id 来源Pulse任务
source_activation_id 事件发生时的流程激活
source_revision 来源任务的状态版本,大于零
snapshot schema_version=1的独立结果JSON文本,最多512 KiB,保留原始数字精度

snapshot包含任务/队列ID、当时的状态与版本、结果、效果不确定标记和当前尝试ID;命名空间及实例由Inbox行固定。快照不依赖对外orbit_result_events的保留时间,也不从后来的任务结果重建。

(namespace_id,event_id)沿用原去重约束,新增(namespace_id,source_task_id,source_revision)唯一键。有效待处理记录必须四项完整且快照为合法JSON;只有迁移前的PROCESSED/QUARANTINED历史记录可以四项均为空。没有外键或级联。

v16及以前的未处理记录缺少冻结来源,升级后统一标为QUARANTINED,原租约清空、代次保留,error_code为LEGACY_RESULT_UNVERIFIED;已处理历史保持原状态。迁移不使用当前任务倒推旧结果,不赋予旧记录新的执行权。

新字段对应weave/model/InboxEvent,Go与SQL均有中文注释。原有扫描索引(state,available_at,namespace_id,id)保留,后续消费仍按持久化待处理状态和有限批次驱动。

关联丢失或类型异常时拒绝提交权威任务结果,不能悄悄丢掉内部交付后返回成功。此类持续异常需要修复存储关系后原身份核对;本阶段尚未提供自动修复工具。

3. 纯步骤决策器

weave/engine.Compile校验并独立拷贝已发布的结构版本1定义。Program可并发读取,调用方修改原定义或取出的步骤副本不会改变它。

Program.Plan(snapshot, limit)接受事务内读取、已校验归属的当前步骤快照,返回最多1–32个ACTIVATE、COMPLETE或SKIP决策。它不执行HTTP、业务Go函数、数据库写入,也不读取当前时间。绝对截止、许可与执行授权继续由存储及Pulse负责。

能力 已实现的决策行为
顺序 仅消费已成功步骤输出;后继不会提前读取结果
分支 首次按条件选择,保存case索引;再次推进复用选择,未选择路径分批标为SKIPPED
并行 分支分别使用进入节点前的数据,全部完成才产生组合输出;兄弟结果通过命名汇合读取
TASK 解析输入与追踪/资源键,按Pulse运行数据边界检查;返回待持久化任务参数,不授予执行权
SIGNAL 解析并冻结非空业务关联、名称与参数版本,返回等待命令
TIMER 返回持久化等待命令,不分配业务Worker
POLL 解析固定查询输入及可选回执关联;成功查询结果有独立分类器,PENDING不等于节点成功
暂停门控 AllowNew=false时不激活新业务工作,允许整理已有组合结果;不替代数据库门控校验
有限推进 More=true时说明本轮变更预算耗尽,必须由适配层保存待续记录;已有活动分支仍继续校验,不能仅安排内存回调

只在已保存的SUCCEEDED投影上读取输出;类型不匹配、未知/失败状态、不可达的执行、已完成组合下仍有未结清子节点、伪造组合输出等都会拒绝整轮决策。不返回可以部分应用的错误结果。

引用与对象/数组构造保留JSON原始数值,输出及累计构造有大小上限;数字条件使用精确有理数比较。相邻大整数、长小数和科学计数法不会先转成float64。规则不提供任意脚本、动态时间或随机数据。

ClassifyPoll仅处理“查询请求成功”的业务结果,返回PENDING、SUCCEEDED、FAILED或NEEDS_REVIEW;未知值/类型错误拒绝。即使快照将POLL标为SUCCEEDED,结果仍在处理中、失败或待核查时也不能推进后继。

4. 后续存储适配必须满足的条件

以下保留存储运行器的完整要求。第1项已按受理报告验证;第2–4项结果消费和根接续已接入实际运行器,第5项的TIMER/POLL已接入时钟运行器,第5项的信号等待已接入信号运行器,内部控制与结清已接入控制运行器,核查与TASK新激活已接入;独立SIGNAL/TIMER等待重建、接口和SDK仍继续实现:

  1. 启动时认证、固定不可变版本/输入和策略、校验全部队列、计算实例截止,并在同事务创建实例、门控、首批激活/任务及审计回执。相同身份返回原实例。
  2. 消费者领取内部事件后核对命名空间、来源任务版本、激活/轮次及当前步骤版本;消费确认、步骤变化、后续任务或持久化待续记录同事务提交。
  3. Plan返回值只有存储事务提交后才生效。额度不足或事务失败不能留下孤立激活/许可;重启从持久化快照重新计算,不重复创建已有任务。
  4. AllowNew来自权威实例状态、控制版本、取消、总截止和门控。程序参数本身不是权限证明。任务deadline不得超过实例或查询节点绝对截止。
  5. 数据库时间驱动真实等待与超时,按可靠受理时间裁决信号/结果,原截止和预算在恢复时保持。单轮重试与查询轮次不能互相补充次数。
  6. 完成实例前核对所有活动工作结清和未知效果;失败/取消需要停止新派发并收集在途结果。人工恢复通过新激活保留历史。
  7. 增加流程来源查询、实例/步骤/信号/操作HTTP和独立SDK、可运行端到端场景、真实节点强杀和竞争回归。其中未完成项继续属于P4–P5剩余工作。

本页的结果交付专用测试夹具通过SQL构造流程关联,只验证结果事务边界;后续受理测试已使用真实内部Start创建实例,两者均不代表公共实例API或完整运行器已经存在。纯决策器的JSON往返测试验证可从快照重算,也不等同于真实进程恢复验收。