7.6 KiB
Weave 执行决策与内部结果交付
状态:P4 内部基础已实现。已接通Pulse结果到Weave持久化Inbox,并提供有限步骤决策器;实例启动、实例存储适配、Inbox消费推进、定时/信号运行器及对应公共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. 后续存储适配必须满足的条件
此处是尚待实现的要求,不能按纯单测宣称已完成:
- 启动时认证、固定不可变版本/输入和策略、校验全部队列、计算实例截止,并在同事务创建实例、门控、首批激活/任务及审计回执。相同身份返回原实例。
- 消费者领取内部事件后核对命名空间、来源任务版本、激活/轮次及当前步骤版本;消费确认、步骤变化、后续任务或持久化待续记录同事务提交。
- Plan返回值只有存储事务提交后才生效。额度不足或事务失败不能留下孤立激活/许可;重启从持久化快照重新计算,不重复创建已有任务。
- AllowNew来自权威实例状态、控制版本、取消、总截止和门控。程序参数本身不是权限证明。任务deadline不得超过实例或查询节点绝对截止。
- 数据库时间驱动真实等待与超时,按可靠受理时间裁决信号/结果,原截止和预算在恢复时保持。单轮重试与查询轮次不能互相补充次数。
- 完成实例前核对所有活动工作结清和未知效果;失败/取消需要停止新派发并收集在途结果。人工恢复通过新激活保留历史。
- 增加流程来源查询、实例/步骤/信号/操作HTTP和独立SDK、可运行端到端场景、真实节点强杀和竞争回归。以上均属于P4–P5剩余工作。
当前测试夹具通过SQL构造流程关联,只验证结果事务边界;它不代表公共实例API或运行器已经存在。纯决策器的JSON往返测试验证可从快照重算,也不等同于真实进程恢复验收。