feat: persist workflow timers and bounded poll rounds
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Weave 流程编排功能与设计
|
||||
|
||||
> 版本 0.3 · 2026-09-18。首版功能范围已确认。定义结构、发布校验与不可变版本已实现,见[定义格式](api/workflow-definition-format.md)和[发布API](api/workflow-definitions.md);已补[步骤决策与内部结果交付](10-workflow-engine-core.md),[实例受理与元数据查询存储](11-workflow-admission.md)已实现;事件消费、等待运行器、公共API/SDK与管理仍待P4–P5实现验收。
|
||||
> 版本 0.4 · 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)已接入。信号、完整管理及实例公共API/SDK仍待P4–P5实现验收。
|
||||
|
||||
## 1. 职责与边界
|
||||
|
||||
@@ -18,7 +18,7 @@ Weave 不执行特定业务逻辑,也不把整段业务代码放入平台进
|
||||
| 条件分支 | 基于已保存、经过类型校验的结果或信号选择路径;不执行任意脚本 |
|
||||
| 有限并行与汇合 | 建议先支持结构化并行分支、全部成功后汇合;限制分支数,不默认支持任意交叉汇合 |
|
||||
| 等待业务信号 | 持久化等待回执、审核结果等外部输入,不长期占用 Worker |
|
||||
| 定时等待 | 持久化截止时间,通过 Pulse 的内部定时任务唤醒 |
|
||||
| 定时等待 | 持久化截止时间,由平台到期索引扫描唤醒,不占业务Worker |
|
||||
| 有界重复查询 | 外部业务尚在处理中时按间隔查询,达到次数或总时限后转人工核查;不与 Pulse 执行重试混用 |
|
||||
| 暂停与继续 | 暂停后停止推进新步骤,继续接收在途结果;恢复后从已保存进度继续 |
|
||||
| 异常与人工恢复 | 保存失败或未知结果,按定义暂停相关推进并核查;干预必须有权限、原因与证据 |
|
||||
@@ -136,7 +136,9 @@ Weave 不执行特定业务逻辑,也不把整段业务代码放入平台进
|
||||
|
||||
查询任务自身成功表示取得了一份有效结果。其中“处理中”使 Weave 保存等待与下一次唤醒;最终业务结果则结束查询节点,按定义推进或进入失败处理。单轮请求重试耗尽应转核查,不能通过新建一轮绕过已耗尽的重试预算。
|
||||
|
||||
每轮只创建一个查询任务,以命名空间、实例、步骤激活和轮次形成稳定去重身份。轮次之间释放业务 Worker 槽位,等待依赖数据库记录与 Pulse 内部定时唤醒;SDK 不在处理器中长期 sleep 或维护内存轮询循环。
|
||||
每轮只创建一个查询任务,以命名空间、实例、步骤激活和轮次形成稳定去重身份。轮次之间释放业务 Worker 槽位,等待依赖数据库记录与平台到期索引扫描;SDK 不在处理器中长期 sleep 或维护内存轮询循环。
|
||||
|
||||
2026-09-18实现决策:TIMER/POLL直接复用`weave_pending_advances`检查点和后台扫描,替代早期草案的Pulse内部唤醒任务。唤醒只改变流程持久状态,不调用业务处理器,因此无需额外占用任务/尝试/许可记录;业务查询仍由Pulse执行。当前schema使用固定间隔,不提供业务轮次抖动或变长退避,具体冻结和升级行为见[运行约定](13-workflow-clock.md)。
|
||||
|
||||
发布和受理时校验轮次、单轮尝试、超时和总时限的组合上限,避免两层次数相乘后超过外部渠道或平台预算。未完成上一轮前不得并发启动下一轮。最后一轮仍为处理中、等待到期或当前轮次重试耗尽时,保存核查原因及已知结果。
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
| weave | `InboxEvent` | `weave_inbox` |
|
||||
| weave | `PendingAdvance` | `weave_pending_advances` |
|
||||
|
||||
`orbit_events` 保存原始状态事件,`orbit_result_events` 使用相同事件 ID 保存队列、提交序号和冻结快照,`orbit_event_streams` 串行分配命名空间内的结果序号;对外投递使用 `orbit_deliveries`,内部流程结果已原子写入 `weave_inbox`及其独立冻结快照(实例消费推进尚未实现)。`weave_pending_advances` 保存暂停或分批推进后的续接检查点。
|
||||
`orbit_events` 保存原始状态事件,`orbit_result_events` 使用相同事件 ID 保存队列、提交序号和冻结快照,`orbit_event_streams` 串行分配命名空间内的结果序号;对外投递使用 `orbit_deliveries`,内部流程结果原子写入 `weave_inbox`及其独立冻结快照,已接入[实例消费推进](12-workflow-runtime.md)。`weave_pending_advances` 保存根步骤续接和TIMER/POLL时钟检查点。
|
||||
|
||||
## 4. 已落实的数据库约束
|
||||
|
||||
@@ -196,3 +196,7 @@ delay_ms是普通/批量提交命令字段,首次事务以同一个数据库
|
||||
## 实例受理与等待身份(000018)
|
||||
|
||||
Wait新增SignalName和PayloadVersion两个中文注释字段;correlation_key转为VARBINARY(764),新受理仍限制512字节,兼容历史191个四字节字符而不截断。实例business_key使用utf8mb4_0900_bin保留精确尾部空格;仍无外键和级联。35个实体,含公共Record的295个直接持久化字段声明均有中文注释。内部`$root`步骤作为实例级待续检查点,不属于定义静态节点或公共步骤列表。具体初始事务、预算和未接通的运行边界见[实例受理](11-workflow-admission.md)。
|
||||
|
||||
## 等待时钟回填(000019)
|
||||
|
||||
复用PendingAdvance保存ROOT、TIMER、POLL检查点;新增内部JSON结构字段均有中文注释,不新增持久化列或实体,仍为35个实体/295个直接持久化字段。TIMER/POLL检查点固定激活ID,实际推进核验同命名空间归属、原截止及剩余预算。迁移只回填历史有效等待的唤醒身份和时间,保留已有检查点;无外键、无级联,见[时钟运行约定](13-workflow-clock.md)。
|
||||
|
||||
@@ -28,13 +28,15 @@
|
||||
| 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及六类节点定义例子已实现,已通过[子项验收](reports/phase-4-definitions.md);已补[有限决策器及内部结果交付](reports/phase-4-engine-core.md);[实例受理及首批事务](reports/phase-4-admission.md)已实现;[结果消费和根接续](reports/phase-4-runtime.md)已接入后台,顺序/分支/并行及真实进程恢复已验证;持久化等待、完整控制和实例公共API/SDK继续开发 |
|
||||
| P5 Weave 恢复与查询 | 有界查询、暂停继续、取消、人工核查恢复、控制门控与审计 | 轮次与尝试独立预算;暂停/开始/回执/超时竞争;恢复保留预算;未知结果不盲目重复 | 待开发 |
|
||||
| P4 Weave 主流程 | SDK 定义构建与发布校验、实例、顺序/分支/结构化并行汇合、信号/定时等待、版本绑定 | 重启接续、早到/重复信号、并行竞争、内部事件重放、发布版本兼容;端到端通用流程 | 定义格式/词法类型校验、不可变发布、独立SDK及六类节点定义例子已实现,已通过[子项验收](reports/phase-4-definitions.md);已补[有限决策器及内部结果交付](reports/phase-4-engine-core.md);[实例受理及首批事务](reports/phase-4-admission.md)已实现;[结果消费和根接续](reports/phase-4-runtime.md)已接入后台,顺序/分支/并行及真实进程恢复已验证;[TIMER与后续POLL轮次](13-workflow-clock.md)已接入;信号、完整控制和实例公共API/SDK继续开发 |
|
||||
| P5 Weave 恢复与查询 | 有界查询、暂停继续、取消、人工核查恢复、控制门控与审计 | 轮次与尝试独立预算;暂停/开始/回执/超时竞争;恢复保留预算;未知结果不盲目重复 | 有界查询轮次/尝试独立预算及原截止恢复已接入内部运行器;信号竞争、完整控制/人工恢复及公共API/SDK继续开发 |
|
||||
| P6 生产验证与运维 | 完整监控、凭据轮换、备份恢复、滚动升级、运行手册、可复现负载和故障工具 | 对照生产验收清单执行,报告环境/指标/遗留项;容量、RPO/RTO 按真实拓扑验证 | 待开发 |
|
||||
| P7 首版交付核对 | SDK 兼容与发布准备、完整 API 手册、场景示例、全量回归及交付清单 | 新接入者按文档跑通全部示例;所有首版能力可追溯到实现与测试;报告实际生产边界 | 待开发 |
|
||||
|
||||
SDK、文档与示例随 P1–P5 同步开发,P7 是全量核对,不是最后才开始补文档。
|
||||
|
||||
P4/P5定时等待与后续查询轮次的实现及回归记录见[时钟报告](reports/phase-4-clock.md)。实例公共入口继续与信号/控制能力同步交付,不能将内部存储链路作为完整SDK验收。
|
||||
|
||||
### P3 功能范围核对
|
||||
|
||||
可靠订阅链路完成后,重新对照 [原功能范围](01-functional-spec.md) 和 [事务衔接设计](04-reliability-and-data.md),以下原定首版能力已按核对结果补齐;进一步发现的相对延迟与改参数关联示例也已交付。[P3验收](reports/phase-3.md)逐项保留实现证据及尚待P4–P7完成的原范围,不按已有模块反推全平台完成。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Weave 执行决策与内部结果交付
|
||||
|
||||
状态:P4 内部基础已实现。已接通Pulse结果到Weave持久化Inbox,并提供有限步骤决策器;[实例受理和首批存储适配](11-workflow-admission.md)已补齐。[Inbox消费推进及根检查点运行器](12-workflow-runtime.md)已接入;定时/信号运行器及实例公共API/SDK仍待实现。不能把本页能力解释成完整公开端到端流程已交付。
|
||||
状态:P4 内部基础已实现。已接通Pulse结果到Weave持久化Inbox,并提供有限步骤决策器;[实例受理和首批存储适配](11-workflow-admission.md)已补齐。[Inbox消费推进及根检查点运行器](12-workflow-runtime.md)已接入;[定时和查询时钟](13-workflow-clock.md)已接入,信号运行器及实例公共API/SDK仍待实现。不能把本页能力解释成完整公开端到端流程已交付。
|
||||
|
||||
## 1. 为什么结果要独立持久化
|
||||
|
||||
@@ -74,7 +74,7 @@ v16及以前的未处理记录缺少冻结来源,升级后统一标为QUARANTI
|
||||
|
||||
## 4. 后续存储适配必须满足的条件
|
||||
|
||||
以下保留存储运行器的完整要求。第1项已按[受理报告](reports/phase-4-admission.md)验证;第2–4项结果消费和根接续已接入[实际运行器](12-workflow-runtime.md),第5–7项的完整等待、控制、接口和SDK仍继续实现:
|
||||
以下保留存储运行器的完整要求。第1项已按[受理报告](reports/phase-4-admission.md)验证;第2–4项结果消费和根接续已接入[实际运行器](12-workflow-runtime.md),第5项的TIMER/POLL已接入[时钟运行器](13-workflow-clock.md),其余信号、完整控制、接口和SDK仍继续实现:
|
||||
|
||||
1. 启动时认证、固定不可变版本/输入和策略、校验全部队列、计算实例截止,并在同事务创建实例、门控、首批激活/任务及审计回执。相同身份返回原实例。
|
||||
2. 消费者领取内部事件后核对命名空间、来源任务版本、激活/轮次及当前步骤版本;消费确认、步骤变化、后续任务或持久化待续记录同事务提交。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Weave 实例受理与首批工作
|
||||
|
||||
状态:内部Go服务与MySQL存储适配已实现实例Start/Get/Steps、固定版本、首批决策落库和可靠结果交付。[后台Inbox消费和根待续扫描](12-workflow-runtime.md)已接通。**尚未开放实例HTTP路由、启动SDK或命令行入口;等待运行器、后续轮询和完整控制仍继续开发。** Weave相关公开SDK目前仅支持定义发布。TASK及组合节点已可自动推进,不能将此解释成全部等待/控制能力已实现。
|
||||
状态:内部Go服务与MySQL存储适配已实现实例Start/Get/Steps、固定版本、首批决策落库和可靠结果交付。[后台Inbox消费和根待续扫描](12-workflow-runtime.md)已接通。**尚未开放实例HTTP路由、启动SDK或命令行入口;信号运行器和完整控制仍继续开发。** Weave相关公开SDK目前仅支持定义发布。[TIMER和后续POLL轮次](13-workflow-clock.md)已接入,TASK及组合节点已可自动推进,不能将此解释成全部等待/控制能力已实现。
|
||||
|
||||
## 1. 受理事务
|
||||
|
||||
@@ -49,14 +49,14 @@ Get返回当前实例视图;Start重报返回受理时冻结的原始视图,
|
||||
| 活跃实例 | 每个namespace最多10000个RUNNING/WAITING/CANCELLING/NEEDS_REVIEW实例;终态不计入;满额仍可恢复原受理回执 |
|
||||
| 信号关联 | 新受理最多512字节;数据库兼容旧191字符最长764字节,升级不截断历史 |
|
||||
| 截止 | 数据库时间生成;任务、查询与等待均不超过实例总截止 |
|
||||
| 自动运行 | Inbox消费和根待续扫描已接入;信号消费、定时到期处理及后续轮询仍待实现 |
|
||||
| 自动运行 | Inbox消费、根待续、TIMER到期及后续POLL轮次已接入;信号消费及完整控制仍待实现 |
|
||||
|
||||
迁移000018为Wait增加signal_name和payload_version两个带中文注释的可空字段;NULL仅表示TIMER或尚未核实的历史元数据,未来消费者不得把历史NULL自动解释为有效的新信号等待。correlation_key转为精确字节存储;实例business_key改为utf8mb4_0900_bin。35个实体、含公共Record的295个直接持久化字段声明,全部有中文注释,继续保持零外键。
|
||||
|
||||
## 5. 下一步接入
|
||||
|
||||
1. 结果消费与根待续运行器已按[运行器报告](reports/phase-4-runtime.md)验证;继续补齐数据库时间驱动的信号/定时等待。
|
||||
2. 已有扫描核验暂停、截止与所属应用停用;继续后续轮次派发、回执竞争及失败分支结清,恢复保留原截止和次数。
|
||||
1. 结果消费与根待续运行器已按[运行器报告](reports/phase-4-runtime.md)验证;[定时和查询时钟](13-workflow-clock.md)已接入,继续补齐信号等待。
|
||||
2. 已有扫描核验暂停、截止与所属应用停用;继续信号/查询回执竞争及失败分支结清,恢复保留原截止和次数。
|
||||
3. 接通实例公共HTTP、独立SDK、来源查询和可运行端到端场景,同时实施真实节点退出与接管回归。
|
||||
|
||||
本阶段验证见[实例受理回归记录](reports/phase-4-admission.md)。纯受理测试不是流程运行验收,P4–P7仍按[完整计划](08-development-plan.md)推进。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Weave 结果消费与自动推进
|
||||
|
||||
状态:内部实例的TASK结果消费、顺序、分支、有限并行汇合和根检查点接续已接入Orbit后台运行器。实例公共HTTP/SDK仍未开放。信号/定时等待、下一轮查询、失败后的分支取消结清及人工恢复仍继续开发,不能将本阶段等同于完整Weave交付。
|
||||
状态:内部实例的TASK结果消费、顺序、分支、有限并行汇合和根检查点接续已接入Orbit后台运行器。[定时等待和后续查询轮次](13-workflow-clock.md)也已接入。实例公共HTTP/SDK仍未开放,信号、失败后的分支取消结清及人工恢复继续开发,不能将本阶段等同于完整Weave交付。
|
||||
|
||||
## 1. 后台运行和事务边界
|
||||
|
||||
@@ -45,7 +45,7 @@ flowchart LR
|
||||
|
||||
暂停、关闭门控或停用应用/命名空间时,继续收集已经落库的结果,但不激活新步骤;若还有后继,将其保存为待续。重新允许推进后,从持久记录继续。测试通过直接设置控制状态验证该行为;暂停/继续公共接口尚未交付。
|
||||
|
||||
已过实例总截止时不创建后继,未能全部完成则进入核查。最后的有效任务结果在截止前已由Pulse接受,而消费发生较晚时,可以整理完整结果并完成实例。暂停或重启不延长截止。纯等待实例到期及信号裁决仍需后续等待扫描器。
|
||||
已过实例总截止时不创建后继,未能全部完成则进入核查。最后的有效任务结果在截止前已由Pulse接受,而消费发生较晚时,可以整理完整结果并完成实例。暂停或重启不延长截止。TIMER与POLL的时钟已接入;SIGNAL及其超期裁决仍需后续实现。
|
||||
|
||||
## 4. POLL与失败策略的当前边界
|
||||
|
||||
@@ -56,7 +56,7 @@ flowchart LR
|
||||
- 轮次耗尽、查询截止、未知/非法值或单轮请求失败:进入核查,不新建轮次绕过Pulse重试预算。
|
||||
- 业务明确失败:按固定实例失败策略处理;REVIEW进入核查,FAIL_AFTER_SETTLED进入CANCELLING并关闭门控。
|
||||
|
||||
**尚未实现下一轮查询派发及其到期索引扫描,也未实现FAIL_AFTER_SETTLED的剩余分支取消/收集/失败终态判定。** CANCELLING保留未结清事实,不提前宣称FAILED。信号抢先完成时与当前在途查询的结清竞争,也属于后续必须实现的功能。
|
||||
下一轮查询派发及到期扫描已实现,详见[时钟、预算与恢复](13-workflow-clock.md)。**尚未实现FAIL_AFTER_SETTLED的剩余分支取消/收集/失败终态判定。** CANCELLING保留未结清事实,不提前宣称FAILED。信号抢先完成时与当前在途查询的结清竞争,也属于后续必须实现的功能。
|
||||
|
||||
## 5. 回归与后续工作
|
||||
|
||||
@@ -64,4 +64,4 @@ flowchart LR
|
||||
|
||||
进程回归由`make integration`构建二进制后显式执行。缺少一次性数据库或`ORBIT_TEST_SERVER_BINARY`时测试会跳过;跳过不构成进程恢复证据。验证记录见[本阶段报告](reports/phase-4-runtime.md)。
|
||||
|
||||
下一步仍包括持久化定时/信号等待、轮询后续轮次、完整控制与人工恢复、实例/来源公共API、独立SDK和通用端到端场景。P4整体及P5–P7继续按[完整计划](08-development-plan.md)执行。
|
||||
下一步仍包括持久化信号等待及查询最终信号竞争、完整控制与人工恢复、实例/来源公共API、独立SDK和通用端到端场景。P4整体及P5–P7继续按[完整计划](08-development-plan.md)执行。
|
||||
|
||||
63
docs/13-workflow-clock.md
Normal file
63
docs/13-workflow-clock.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Weave 持久化定时等待与查询轮次
|
||||
|
||||
状态:TIMER到期推进和POLL后续业务轮次已接入Orbit后台运行器。复用MySQL和既有待续索引,不增加外部调度服务或数据库外键。实例公共HTTP/SDK、SIGNAL消费、查询最终信号竞争以及完整控制/人工恢复仍未交付。
|
||||
|
||||
## 1. 时钟和恢复身份
|
||||
|
||||
`weave_pending_advances`同时保存ROOT、TIMER、POLL三类检查点。唯一范围为命名空间、实例和步骤;时钟检查点额外固定当前激活ID,避免旧激活唤醒新工作。扫描只提供候选,实际推进仍须持锁核验固定版本、父记录、步骤/激活状态、任务所有者、门控和原始预算。
|
||||
|
||||
| 检查点 | 到期时间来源 | 推进结果 |
|
||||
| --- | --- | --- |
|
||||
| ROOT | 分批推进或暂停/满额后的下一检查时间 | 重新计算最多32项步骤变更 |
|
||||
| TIMER | 激活时保存的等待截止 | 完成原等待或记录超期核查,再有限推进 |
|
||||
| POLL当前轮次仍在途 | 查询节点的原绝对截止 | 保留结果收集或关闭新执行门控,不启动重叠轮次 |
|
||||
| POLL上一轮业务PENDING | 上一轮权威结果发生时间加固定间隔,受查询截止限制 | 若允许且有额度,同事务创建下一轮任务 |
|
||||
|
||||
每个候选遵守[运行器事务顺序](12-workflow-runtime.md):身份、应用额度、排序队列、实例、门控和子记录。多个Orbit节点竞争同一数据库记录,不能凭本地时间或内存缓存取得推进权。扫描失败回滚并按候选版本延后重查,既有结果和预算仍保留。
|
||||
|
||||
TIMER由待续表直接唤醒,不创建Pulse业务任务,也不占Worker执行许可。旧模型的`wake_task_id`当前保持空;后续若改变这一约定,需要独立迁移与兼容验证。
|
||||
|
||||
## 2. 定时等待
|
||||
|
||||
激活时保存开始时间及`min(开始时间 + delay_ms, 实例总截止)`。恢复时重新验证这条等式,不能从重启或继续时间重新计时。
|
||||
|
||||
- 原计划等待时长能在实例总截止内结束:到期保存SATISFIED及步骤SUCCEEDED,输出为JSON `null`。
|
||||
- 后续步骤才激活TIMER,导致剩余实例时长不足:到总截止保存EXPIRED、步骤及实例NEEDS_REVIEW,不能把被截短的等待当作成功。
|
||||
- 暂停期间已到期的等待仍可收集完成;后继保留ROOT待续,直到控制状态允许。暂停不延长截止。
|
||||
- 全部进程停止后才被扫描:使用原到期时间。若整个流程已能由有效的到期事实完成,可以整理完成;若还需启动新步骤且实例总截止已过,则进入核查。
|
||||
|
||||
等待结清、步骤状态、后继任务或ROOT检查点、事件和审计同事务。审计失败不会留下已完成等待或部分后继。
|
||||
|
||||
## 3. 有界查询与请求重试
|
||||
|
||||
一次业务查询轮次对应一个Pulse任务。当前任务成功返回PENDING后,内部结果事务保存WAITING、清除`current_task_id`、记录`next_poll_at`并更新POLL检查点。成功查询仍在处理和请求执行失败使用不同预算:
|
||||
|
||||
| 场景 | 业务轮次 | Pulse尝试 |
|
||||
| --- | --- | --- |
|
||||
| 已知可重试请求失败 | 不增加,仍为原任务 | 按该任务冻结策略增加 |
|
||||
| 查询成功返回PENDING且未耗尽预算 | 到固定间隔后创建下一任务,增加1 | 新一轮从自身首次尝试开始 |
|
||||
| DONE等声明成功结果 | 结清当前查询节点 | 不再启动下一轮 |
|
||||
| 单轮失败/效果未知/非法结果/业务核查值 | 停止正常推进并保存核查事实 | 不通过创建新轮次绕过原尝试上限 |
|
||||
| 轮次耗尽或总截止到达 | 不增加,进入核查 | 原在途任务仍需收集实际结果 |
|
||||
|
||||
创建下一轮前校验轮次连续、当前无在途任务、上一轮已经确认为POLL_PENDING。复用首轮已解析的精确输入、业务键、资源互斥键以及固定版本的处理器、契约、优先级和重试策略;不重新解释已完成步骤的表达式。任务绝对截止仍取自身时限、查询总截止和实例总截止的较早者。
|
||||
|
||||
新任务、所有者和门控、轮次记录、已用轮数、当前任务、步骤状态、下一检查点、事件及审计同事务。插入轮次或审计失败会连同任务及额度一起回滚。应用/队列满额、暂停或身份停用仅延后检查;不消耗新轮次,不改变原截止。
|
||||
|
||||
## 4. 截止与已落库结果的竞争
|
||||
|
||||
截止扫描发现当前任务已经有终态或核查结果,但Inbox还未消费时,保留时钟并优先等Inbox按原事件时间裁决。不能用扫描发生时间否定已按时可靠受理的成功结果。
|
||||
|
||||
当前任务仍在途且查询总截止已到时,实例转NEEDS_REVIEW并关闭新执行门控;步骤保持ACTIVE、轮次保持当前任务引用,继续收集Pulse结果。时钟不释放执行许可,也不假定外部请求已经停止。Pulse恢复将失联执行记录为UNKNOWN后,内部消费再结清当前查询记录,保留核查状态。
|
||||
|
||||
最终信号与在途查询的竞争尚未实现。定义可以描述`final_signal`并建立等待,但当前只能通过查询结果结清;不能据此承诺外部信号已经可以消费。
|
||||
|
||||
## 5. 升级和验证
|
||||
|
||||
[迁移000019](../internal/storage/mysql/migrations/000019_workflow_clock_checkpoints.up.sql)仅回填旧实例当前激活的TIMER/POLL检查点:定时等待使用原deadline,等待查询使用原next_poll_at,在途查询使用原查询deadline。已有检查点不覆盖,终态实例及旧激活不回填;不新增表、字段、索引、外键或级联。
|
||||
|
||||
升级顺序为停止旧写入节点 → 应用全部迁移 → 启动新节点。旧节点可能消费PENDING结果却不会创建新的时钟检查点,因此不能与新版混跑。历史结构损坏或缺少完整定义的记录即使形成候选,也必须经运行器校验才能推进。
|
||||
|
||||
[存储回归](../internal/storage/mysql/workflow_clock_integration_test.go)覆盖到期、竞争、预算、暂停/满额、回滚、归属损坏与未知结果;[v18升级回归](../internal/storage/mysql/workflow_clock_upgrade_integration_test.go)验证回填及原预算保留;[真实进程回归](../internal/storage/mysql/workflow_runtime_process_integration_test.go)覆盖全部控制进程退出后的定时和查询接续。执行记录见[阶段报告](reports/phase-4-clock.md)。
|
||||
|
||||
下一阶段继续SIGNAL早到/重复/超期处理、信号与查询竞争、失败分支结清、公共控制及实例SDK,完整范围见[持续计划](08-development-plan.md)。
|
||||
@@ -21,6 +21,7 @@
|
||||
| [10 Weave决策与交付](10-workflow-engine-core.md) | 有限步骤决策和内部结果Inbox |
|
||||
| [11 Weave实例受理](11-workflow-admission.md) | 固定版本、初始图和首批任务事务 |
|
||||
| [12 Weave结果消费与推进](12-workflow-runtime.md) | 后台消费、根接续、事务与进程恢复,及尚未完成的等待/控制边界 |
|
||||
| [13 Weave定时等待与查询轮次](13-workflow-clock.md) | 原截止、轮次/尝试预算、时钟检查点、升级与全停恢复 |
|
||||
| [接口手册](api/README.md) | 实际接口状态、调用说明与后续接口规划 |
|
||||
| [SDK 与场景](sdk/README.md) | 可运行示例、接入方法及分阶段 SDK 交付 |
|
||||
|
||||
|
||||
53
docs/reports/phase-4-clock.md
Normal file
53
docs/reports/phase-4-clock.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# P4/P5 定时等待与查询轮次回归
|
||||
|
||||
日期:2026-09-18。范围为内部持久化等待运行器;SIGNAL、完整管理控制、实例公共API/SDK和生产验证继续按原计划执行。
|
||||
|
||||
## 实现范围
|
||||
|
||||
- TIMER与POLL复用待续表到期索引和当前激活身份;首批创建、结果消费、时钟推进及审计同事务。
|
||||
- 原等待时间、总截止、已用轮次和单轮尝试预算不因暂停、满额或重启重置。
|
||||
- 后续查询复用首轮精确输入、业务键、互斥键、处理器与冻结策略;上一轮必须已经成功查询并分类为PENDING。
|
||||
- 截止扫描让已落库Inbox结果先完成裁决;仍在途时保留步骤ACTIVE与当前任务,由Pulse收集实际结果和释放许可。
|
||||
- 迁移000019从真实v18结构回填等待时钟,不覆盖原检查点、不改变预算、不回填终态实例或旧激活;无新增实体、列、索引或外键。
|
||||
|
||||
具体语义见[定时与查询文档](../13-workflow-clock.md)。模型维持35个实体、295个直接持久化字段声明,中文注释保留;内部检查点JSON字段同步提供中文说明。
|
||||
|
||||
## 环境与证据
|
||||
|
||||
本机darwin/arm64、Go 1.27.1、Docker MySQL 8.4.10。全部数据库为临时隔离测试库,未连接业务库或远端生产库。
|
||||
|
||||
| 检查 | 结果 |
|
||||
| --- | --- |
|
||||
| `make fmt test vet build` | 已通过,退出0,覆盖服务端、SDK与独立示例module |
|
||||
| 时钟及相关真实MySQL定向回归 | 14组时钟场景、v18升级、原运行器/实例受理、新建结构及v7无外键升级通过,`-race`,44.745秒 |
|
||||
| 真实Orbit进程恢复 | 已通过,15.093秒;强杀/全停后由两个新进程接续原结果、到期TIMER及下一轮POLL |
|
||||
| 全量隔离集成回归 | 已通过,退出0;全存储160.211秒、流程进程14.928秒、Worker SDK 92.976秒、SDK进程故障94.972秒;19个SDK示例和2个独立业务示例全部通过 |
|
||||
|
||||
定向入口:
|
||||
|
||||
```sh
|
||||
go test -race -count=1 -run '^TestIntegration(WorkflowClock|WorkflowClockUpgrade|WorkflowRuntime|WorkflowInstanceAdmission|SchemaAndConstraints|NoForeignKeysUpgrade)$' -v ./internal/storage/mysql
|
||||
go build -o /tmp/orbit-clock-test-server ./cmd/orbit
|
||||
ORBIT_TEST_SERVER_BINARY=/tmp/orbit-clock-test-server go test -race -count=1 -run '^TestIntegrationWorkflowRuntimeProcess$' -v ./internal/storage/mysql
|
||||
```
|
||||
|
||||
以上命令须设置`ORBIT_TEST_MYSQL_DSN`指向一次性数据库;未配置时用例跳过,不能据此声称通过。[全量脚本](../../scripts/test-mysql.sh)负责隔离MySQL、构建二进制并显式运行进程测试。
|
||||
|
||||
数据库直接复核外键0、缺少COMMENT的业务字段0;代码复核295个直接持久化字段声明均含中文注释。文档复核847个本地链接和53个JSON代码块,错误0;`git diff --check`通过。
|
||||
|
||||
存储测试覆盖12个并发定时消费者只创建一个后继、8个并发查询消费者只增加一轮、暂停/满额保留预算、等待被总截止截短、延迟消费已到期事实、审计及轮次写入故障回滚、单轮重试与业务轮次区分、超时收集已落库结果、在途UNKNOWN结清、首轮输入及所有者损坏拒绝。v7升级验证70个历史外键全部移除,323项原索引组件和任务数据保留,额外添加外键时启动检查拒绝。
|
||||
|
||||
进程测试先确认所有控制进程已经退出,再让TIMER自然到期或提交查询PENDING结果;启动两个全新进程后核对原唤醒时间/绝对截止未改变、无重复任务,查询只产生两轮后由DONE完成。业务任务由真实Pulse执行存储授权与结束,实例使用内部Start;这不替代尚未开放的实例HTTP/SDK端到端回归。
|
||||
|
||||
开发过程中修正了两个测试夹具问题:业务键保留尾部空格而互斥键禁止首尾空格,因此互斥键改用实例ID;带互斥键的任务同时占用多类许可,因此核验原许可数量未变并在Pulse结清后归零。生产输入校验与许可规则未因此放宽。
|
||||
|
||||
首次全量存储回归因新故障注入用例未恢复原任务所有者而失败:后续全局租约恢复扫描正确拒绝了这条损坏关联。已为输入/所有者故障注入补齐退出恢复,最终完整重跑通过;不放宽生产关联校验,也不将首次失败计为通过。最后基础检查也已重跑通过,上表全量记录包含该修订。
|
||||
|
||||
## 剩余原定范围
|
||||
|
||||
1. SIGNAL早到、重复、超时、契约与关联校验;最终信号和在途查询竞争。
|
||||
2. FAIL_AFTER_SETTLED分支取消/收集/终态判断,以及暂停、继续、取消和人工恢复公共操作。
|
||||
3. 实例、步骤、来源、信号和审计HTTP/独立SDK、通用场景示例。
|
||||
4. P6–P7监控、完整故障矩阵、性能容量、MySQL高可用与备份恢复、SDK发布核对。
|
||||
|
||||
这些回归验证单个MySQL下的状态与进程故障恢复,不给出生产容量、RPO/RTO或数据库高可用承诺。
|
||||
Reference in New Issue
Block a user