feat: consume workflow results and resume durable advances
This commit is contained in:
67
docs/12-workflow-runtime.md
Normal file
67
docs/12-workflow-runtime.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# Weave 结果消费与自动推进
|
||||
|
||||
状态:内部实例的TASK结果消费、顺序、分支、有限并行汇合和根检查点接续已接入Orbit后台运行器。实例公共HTTP/SDK仍未开放。信号/定时等待、下一轮查询、失败后的分支取消结清及人工恢复仍继续开发,不能将本阶段等同于完整Weave交付。
|
||||
|
||||
## 1. 后台运行和事务边界
|
||||
|
||||
每个Orbit进程每秒调用一次`WorkflowRuntime.Tick`,一批最多100个候选、调用超时5秒。候选来自`weave_inbox`的PENDING到期索引和`weave_pending_advances`的到期索引,各候选独立事务。选择候选不授予执行权;同一应用繁忙时跳过,后续扫描重读数据库。
|
||||
|
||||
事务锁顺序是身份共享锁 → 应用额度排他锁 → 固定版本涉及的排序队列 → 实例 → 执行门控 → 激活/步骤及消费记录。不能先领取并持有Inbox锁,再倒过来锁应用或任务。运行器不向业务系统发请求,不需要Redis或额外消息队列;业务执行仍由Pulse授权Worker。
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A[读取到期Inbox或根检查点] --> B[锁定并核验实例图]
|
||||
B --> C[读取冻结结果并校验来源]
|
||||
C --> D[更新步骤和计算有限决策]
|
||||
D --> E[创建后继工作或保存待续]
|
||||
E --> F[确认消费并写审计]
|
||||
F --> G[同一事务提交]
|
||||
```
|
||||
|
||||
每轮最多32个结构变更。达到预算时保留根步骤版本及ROOT检查点,由后续节点继续;后续计算仍使用固定版本、原输入和已保存结果。旧检查点只能基于当前持锁快照重新计算,不能覆盖更高步骤版本;超前版本或错误根身份拒绝执行。
|
||||
|
||||
## 2. 结果、去重与审计
|
||||
|
||||
消费只使用内部Inbox的独立结果快照。校验结构版本、任务和队列、来源状态版本、原事件身份/类型/版本、激活所属实例和步骤、Pulse所有者及门控、尝试归属;POLL额外校验原轮次。任务当前结果不能替换历史快照。
|
||||
|
||||
| 情况 | 处理 |
|
||||
| --- | --- |
|
||||
| 已确认或已隔离的记录再次被扫描 | 不再次更新步骤、创建任务或写相同消费审计 |
|
||||
| 旧激活、已处理的旧轮次或低于已处理结果版本 | 保留来源,确认并记录稳定分类,不推动当前工作 |
|
||||
| 已结清步骤收到其他历史结果 | 保留处理历史,不重开步骤或改变已完成业务结果 |
|
||||
| 来源身份或结构矛盾 | QUARANTINED;未终结实例转NEEDS_REVIEW并关闭新执行门控 |
|
||||
| SQL/连接或事务异常 | 整笔回滚;仍保留PENDING。扫描器按原记录版本延后30秒,不能覆盖其他节点刚完成的确认 |
|
||||
| 正常TASK成功 | 验证固定输出契约,保存SUCCEEDED后有限推进 |
|
||||
| TASK确认取消 | 步骤保留CANCELLED和来源证据,不能改写为FAILED或启动正常后继 |
|
||||
| TASK失败、未知效果或不合契约的成功结果 | 停止依赖推进,保留原任务结果及稳定核查原因 |
|
||||
|
||||
每个成功提交的消费或实际根推进写系统审计,actor为`system:weave:<node_id>`。审计使用独立操作身份,元信息保存来源Inbox/检查点ID、节点、实例版本及原因;同一个ROOT检查点可分批产生多次真实推进。每次历史变更取得新的实例revision,避免迟到证据与先前事件的唯一身份冲突。
|
||||
|
||||
审计失败会回滚消费确认、步骤状态和新任务。对外任务结果订阅继续使用原链路,内部消费不需要锁订阅或外部结果流。
|
||||
|
||||
## 3. 满额、暂停和截止
|
||||
|
||||
后继创建使用SAVEPOINT隔离本轮结构变更。多后继中任何一个遇到队列或应用满额,全部本轮后继和对应额度预占回滚;已接受的来源结果及步骤完成仍能与ROOT待续记录一起提交。下一次尝试从当前图重新计算,不能留下部分激活、重复后继或多扣用量。持续满额仅移动检查时间,不逐秒制造相同业务审计。
|
||||
|
||||
暂停、关闭门控或停用应用/命名空间时,继续收集已经落库的结果,但不激活新步骤;若还有后继,将其保存为待续。重新允许推进后,从持久记录继续。测试通过直接设置控制状态验证该行为;暂停/继续公共接口尚未交付。
|
||||
|
||||
已过实例总截止时不创建后继,未能全部完成则进入核查。最后的有效任务结果在截止前已由Pulse接受,而消费发生较晚时,可以整理完整结果并完成实例。暂停或重启不延长截止。纯等待实例到期及信号裁决仍需后续等待扫描器。
|
||||
|
||||
## 4. POLL与失败策略的当前边界
|
||||
|
||||
已实现当前轮次的结果消费:
|
||||
|
||||
- 查询请求成功但业务PENDING:保存WAITING、清除当前任务并按原事件时间加间隔保存`next_poll_at`,受原查询截止限制;不将PENDING输出交给后继。
|
||||
- DONE等已声明成功值:按固定契约完成节点;如有最终信号等待,一并结清。
|
||||
- 轮次耗尽、查询截止、未知/非法值或单轮请求失败:进入核查,不新建轮次绕过Pulse重试预算。
|
||||
- 业务明确失败:按固定实例失败策略处理;REVIEW进入核查,FAIL_AFTER_SETTLED进入CANCELLING并关闭门控。
|
||||
|
||||
**尚未实现下一轮查询派发及其到期索引扫描,也未实现FAIL_AFTER_SETTLED的剩余分支取消/收集/失败终态判定。** CANCELLING保留未结清事实,不提前宣称FAILED。信号抢先完成时与当前在途查询的结清竞争,也属于后续必须实现的功能。
|
||||
|
||||
## 5. 回归与后续工作
|
||||
|
||||
[存储回归](../internal/storage/mysql/workflow_runtime_integration_test.go)覆盖重复消费者、精确结果、并行汇合、部分后继满额回滚、审计回滚、暂停与停用接续、分批根恢复、来源隔离、旧激活/旧版本、失败/截止和POLL分类;[进程回归](../internal/storage/mysql/workflow_runtime_process_integration_test.go)强杀唯一Orbit进程,确认死亡后提交任务结果,再启动两个新进程接续。
|
||||
|
||||
进程回归由`make integration`构建二进制后显式执行。缺少一次性数据库或`ORBIT_TEST_SERVER_BINARY`时测试会跳过;跳过不构成进程恢复证据。验证记录见[本阶段报告](reports/phase-4-runtime.md)。
|
||||
|
||||
下一步仍包括持久化定时/信号等待、轮询后续轮次、完整控制与人工恢复、实例/来源公共API、独立SDK和通用端到端场景。P4整体及P5–P7继续按[完整计划](08-development-plan.md)执行。
|
||||
Reference in New Issue
Block a user