feat: persist workflow controls and settle stopped branches
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# 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实现验收。
|
||||
> 版本 0.6 · 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)已接入内部运行器;[暂停/继续/取消与停止结清](15-workflow-controls.md)已实现内部链路;人工核查及实例公共API/SDK仍待P4–P5实现验收。
|
||||
|
||||
## 1. 职责与边界
|
||||
|
||||
@@ -152,7 +152,7 @@ Weave 不执行特定业务逻辑,也不把整段业务代码放入平台进
|
||||
|
||||
**功能已确认**:暂停阻止新步骤推进,保留已完成进度,继续接收在途结果与外部回执;继续操作从持久化进度恢复。暂停不表示已经停止外部业务操作。
|
||||
|
||||
以下细则为设计建议:
|
||||
以下细则已按[控制运行约定](15-workflow-controls.md)冻结并实现内部链路,公共HTTP/SDK仍待交付:
|
||||
|
||||
- 暂停与继续带预期控制版本、稳定操作身份、操作人及原因;状态与审计一起提交。新步骤创建必须原子检查控制版本。
|
||||
- 建议暂停还阻止关联任务的新领取、开始授权和执行重试,包含已经创建但尚未开始的任务。由 Pulse 的通用执行门控与 Weave 控制状态同事务更新,领取/开始时读取权威门控,避免仅暂停流程循环却继续派发旧队列任务。
|
||||
|
||||
@@ -203,4 +203,8 @@ Wait新增SignalName和PayloadVersion两个中文注释字段;correlation_key
|
||||
|
||||
## 信号身份与赢家增量(000020)
|
||||
|
||||
Signal新增payload_version、target_activation_sequence、evidence_ref、disposition、available_at;Wait新增winner_signal_id。当前35个实体、含公共Record的301个直接持久化字段声明,全部中文注释。新信号精确关联最多512字节,存储兼容历史764字节;过期检查退避不改变expires_at。赢家唯一约束只防重复,实例/等待/激活/信号归属及不可变受理证明仍由事务验证,外键保持0。历史不完整身份隔离和升级回填见[信号约定](14-workflow-signals.md)。
|
||||
Signal新增payload_version、target_activation_sequence、evidence_ref、disposition、available_at;Wait新增winner_signal_id。截至000020为35个实体、含公共Record的301个直接持久化字段声明,全部中文注释。新信号精确关联最多512字节,存储兼容历史764字节;过期检查退避不改变expires_at。赢家唯一约束只防重复,实例/等待/激活/信号归属及不可变受理证明仍由事务验证,外键保持0。历史不完整身份隔离和升级回填见[信号约定](14-workflow-signals.md)。
|
||||
|
||||
## 停止意图增量(000021)
|
||||
|
||||
Instance新增StopKind和StopRequestedAt,冻结首次用户取消或失败结清目标;CancelRequestedAt仍只表示用户显式取消。成对CHECK防止半条意图,任务所有者索引支持双向归属核验。当前35个实体、303个直接持久化字段声明,均有中文注释。历史停止实例关闭门控并恢复根接续,不改变原截止、预算、控制版本或终态数据;保持零外键,详见[控制约定](15-workflow-controls.md)。
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
| 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)已接入后台,顺序/分支/并行及真实进程恢复已验证;[TIMER与后续POLL轮次](13-workflow-clock.md)已接入;[信号消费和最终查询竞争](14-workflow-signals.md)已接入内部运行器;完整控制和实例公共API/SDK继续开发 |
|
||||
| P5 Weave 恢复与查询 | 有界查询、暂停继续、取消、人工核查恢复、控制门控与审计 | 轮次与尝试独立预算;暂停/开始/回执/超时竞争;恢复保留预算;未知结果不盲目重复 | 有界查询轮次/尝试独立预算及原截止恢复已接入内部运行器;最终信号竞争及在途查询结清已接入;完整控制/人工恢复及公共API/SDK继续开发 |
|
||||
| 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)已接入;[信号消费和最终查询竞争](14-workflow-signals.md)已接入内部运行器;[内部控制与停止结清](15-workflow-controls.md)已接入;人工恢复和实例公共API/SDK继续开发 |
|
||||
| P5 Weave 恢复与查询 | 有界查询、暂停继续、取消、人工核查恢复、控制门控与审计 | 轮次与尝试独立预算;暂停/开始/回执/超时竞争;恢复保留预算;未知结果不盲目重复 | 有界查询轮次/尝试独立预算及原截止恢复已接入内部运行器;最终信号竞争及在途查询结清已接入;内部暂停/继续/取消与失败结清已接入;人工恢复及公共API/SDK继续开发 |
|
||||
| P6 生产验证与运维 | 完整监控、凭据轮换、备份恢复、滚动升级、运行手册、可复现负载和故障工具 | 对照生产验收清单执行,报告环境/指标/遗留项;容量、RPO/RTO 按真实拓扑验证 | 待开发 |
|
||||
| P7 首版交付核对 | SDK 兼容与发布准备、完整 API 手册、场景示例、全量回归及交付清单 | 新接入者按文档跑通全部示例;所有首版能力可追溯到实现与测试;报告实际生产边界 | 待开发 |
|
||||
|
||||
@@ -39,8 +39,8 @@ P4/P5定时等待与后续查询轮次的实现及回归记录见[时钟报告](
|
||||
|
||||
### P4/P5 下一步实施顺序
|
||||
|
||||
1. 完成FAIL_AFTER_SETTLED与显式取消的分支结清:持久取消意图、复用Pulse取消、收集已发出查询/任务结果、等待全部已激活工作结清后才进入失败或取消终态。效果未知仍保留核查。
|
||||
2. 完成实例暂停/继续/取消内部操作,以control_revision、操作幂等身份、明确原因及审计保护控制决定;暂停不延长原截止,继续不覆盖核查或取消状态。
|
||||
1. 已实现FAIL_AFTER_SETTLED与显式取消的内部分支结清,见[控制报告](reports/phase-5-controls.md):持久取消意图、复用Pulse取消、收集已发出查询/任务结果、等待全部已激活工作结清后才进入失败或取消终态。效果未知仍保留核查。
|
||||
2. 已实现实例暂停/继续/取消内部操作,以control_revision、操作幂等身份、明确原因及审计保护控制决定;暂停不延长原截止,继续不覆盖核查或取消状态。
|
||||
3. 完成人工核查恢复与旧激活隔离,保留原预算、结果和证据,不能通过换激活/新键绕过未知效果或执行上限。
|
||||
4. 同步开放实例/步骤/信号/来源/审计HTTP、独立SDK和端到端场景,覆盖原键恢复、权限、版本冲突、竞争与进程全停;公共能力逐项记录实际验收结果。
|
||||
5. 转入P6/P7的生产故障、容量、运维、发布与全部文档核对。内部存储阶段通过不会提前勾选公共接口或生产验收。
|
||||
|
||||
@@ -74,7 +74,7 @@ v16及以前的未处理记录缺少冻结来源,升级后统一标为QUARANTI
|
||||
|
||||
## 4. 后续存储适配必须满足的条件
|
||||
|
||||
以下保留存储运行器的完整要求。第1项已按[受理报告](reports/phase-4-admission.md)验证;第2–4项结果消费和根接续已接入[实际运行器](12-workflow-runtime.md),第5项的TIMER/POLL已接入[时钟运行器](13-workflow-clock.md),第5项的信号等待已接入[信号运行器](14-workflow-signals.md),完整控制、接口和SDK仍继续实现:
|
||||
以下保留存储运行器的完整要求。第1项已按[受理报告](reports/phase-4-admission.md)验证;第2–4项结果消费和根接续已接入[实际运行器](12-workflow-runtime.md),第5项的TIMER/POLL已接入[时钟运行器](13-workflow-clock.md),第5项的信号等待已接入[信号运行器](14-workflow-signals.md),内部控制与结清已接入[控制运行器](15-workflow-controls.md),人工恢复、接口和SDK仍继续实现:
|
||||
|
||||
1. 启动时认证、固定不可变版本/输入和策略、校验全部队列、计算实例截止,并在同事务创建实例、门控、首批激活/任务及审计回执。相同身份返回原实例。
|
||||
2. 消费者领取内部事件后核对命名空间、来源任务版本、激活/轮次及当前步骤版本;消费确认、步骤变化、后续任务或持久化待续记录同事务提交。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Weave 实例受理与首批工作
|
||||
|
||||
状态:内部Go服务与MySQL存储适配已实现实例Start/Get/Steps、固定版本、首批决策落库和可靠结果交付。[后台Inbox消费和根待续扫描](12-workflow-runtime.md)已接通。**尚未开放实例HTTP路由、启动SDK或命令行入口;完整控制仍继续开发;[信号运行器](14-workflow-signals.md)已接入。** Weave相关公开SDK目前仅支持定义发布。[TIMER和后续POLL轮次](13-workflow-clock.md)已接入,TASK及组合节点已可自动推进,不能将此解释成全部等待/控制能力已实现。
|
||||
状态:内部Go服务与MySQL存储适配已实现实例Start/Get/Steps、固定版本、首批决策落库和可靠结果交付。[后台Inbox消费和根待续扫描](12-workflow-runtime.md)已接通。**尚未开放实例HTTP路由、启动SDK或命令行入口;[内部控制和结清](15-workflow-controls.md)已接入,人工恢复继续开发;[信号运行器](14-workflow-signals.md)已接入。** Weave相关公开SDK目前仅支持定义发布。[TIMER和后续POLL轮次](13-workflow-clock.md)已接入,TASK及组合节点已可自动推进,不能将此解释成全部等待/控制能力已实现。
|
||||
|
||||
## 1. 受理事务
|
||||
|
||||
@@ -49,7 +49,7 @@ Get返回当前实例视图;Start重报返回受理时冻结的原始视图,
|
||||
| 活跃实例 | 每个namespace最多10000个RUNNING/WAITING/CANCELLING/NEEDS_REVIEW实例;终态不计入;满额仍可恢复原受理回执 |
|
||||
| 信号关联 | 新受理最多512字节;数据库兼容旧191字符最长764字节,升级不截断历史 |
|
||||
| 截止 | 数据库时间生成;任务、查询与等待均不超过实例总截止 |
|
||||
| 自动运行 | Inbox消费、根待续、TIMER到期及后续POLL轮次已接入;SIGNAL与最终查询竞争已接入,完整控制仍待实现 |
|
||||
| 自动运行 | Inbox消费、根待续、TIMER到期及后续POLL轮次已接入;SIGNAL与最终查询竞争已接入,内部控制与结清已接入,人工恢复仍待实现 |
|
||||
|
||||
迁移000018为Wait增加signal_name和payload_version两个带中文注释的可空字段;NULL仅表示TIMER或尚未核实的历史元数据,未来消费者不得把历史NULL自动解释为有效的新信号等待。correlation_key转为精确字节存储;实例business_key改为utf8mb4_0900_bin。该迁移时为35个实体、含公共Record的295个直接持久化字段声明,全部有中文注释,继续保持零外键。
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Weave 结果消费与自动推进
|
||||
|
||||
状态:内部实例的TASK结果消费、顺序、分支、有限并行汇合和根检查点接续已接入Orbit后台运行器。[定时等待和后续查询轮次](13-workflow-clock.md)也已接入。[信号等待与最终查询竞争](14-workflow-signals.md)已接入。实例公共HTTP/SDK仍未开放,失败后的分支取消结清及人工恢复继续开发,不能将本阶段等同于完整Weave交付。
|
||||
状态:内部实例的TASK结果消费、顺序、分支、有限并行汇合和根检查点接续已接入Orbit后台运行器。[定时等待和后续查询轮次](13-workflow-clock.md)也已接入。[信号等待与最终查询竞争](14-workflow-signals.md)已接入。实例公共HTTP/SDK仍未开放,[失败后的分支取消结清与内部控制](15-workflow-controls.md)已接入,人工恢复继续开发,不能将本阶段等同于完整Weave交付。
|
||||
|
||||
## 1. 后台运行和事务边界
|
||||
|
||||
@@ -43,7 +43,7 @@ flowchart LR
|
||||
|
||||
后继创建使用SAVEPOINT隔离本轮结构变更。多后继中任何一个遇到队列或应用满额,全部本轮后继和对应额度预占回滚;已接受的来源结果及步骤完成仍能与ROOT待续记录一起提交。下一次尝试从当前图重新计算,不能留下部分激活、重复后继或多扣用量。持续满额仅移动检查时间,不逐秒制造相同业务审计。
|
||||
|
||||
暂停、关闭门控或停用应用/命名空间时,继续收集已经落库的结果,但不激活新步骤;若还有后继,将其保存为待续。重新允许推进后,从持久记录继续。测试通过直接设置控制状态验证该行为;暂停/继续公共接口尚未交付。
|
||||
暂停、关闭门控或停用应用/命名空间时,继续收集已经落库的结果,但不激活新步骤;若还有后继,将其保存为待续。重新允许推进后,从持久记录继续。测试通过直接设置控制状态验证该行为;内部暂停/继续控制已按[控制运行约定](15-workflow-controls.md)实现,公共HTTP/SDK尚未交付。
|
||||
|
||||
已过实例总截止时不创建后继,未能全部完成则进入核查。最后的有效任务结果在截止前已由Pulse接受,而消费发生较晚时,可以整理完整结果并完成实例。暂停或重启不延长截止。TIMER与POLL的时钟已接入;[SIGNAL及其超期/最终查询裁决](14-workflow-signals.md)已接入。
|
||||
|
||||
@@ -56,7 +56,7 @@ flowchart LR
|
||||
- 轮次耗尽、查询截止、未知/非法值或单轮请求失败:进入核查,不新建轮次绕过Pulse重试预算。
|
||||
- 业务明确失败:按固定实例失败策略处理;REVIEW进入核查,FAIL_AFTER_SETTLED进入CANCELLING并关闭门控。
|
||||
|
||||
下一轮查询派发及到期扫描已实现,详见[时钟、预算与恢复](13-workflow-clock.md)。**尚未实现FAIL_AFTER_SETTLED的剩余分支取消/收集/失败终态判定。** CANCELLING保留未结清事实,不提前宣称FAILED。信号抢先到达时保留当前查询,实际结果结清及竞争见[信号运行约定](14-workflow-signals.md)。
|
||||
下一轮查询派发及到期扫描已实现,详见[时钟、预算与恢复](13-workflow-clock.md)。**FAIL_AFTER_SETTLED的剩余分支取消/收集/失败终态判定已接入[停止运行器](15-workflow-controls.md)。** CANCELLING保留未结清事实,只有全部已知结清后才能进入FAILED。信号抢先到达时保留当前查询,实际结果结清及竞争见[信号运行约定](14-workflow-signals.md)。
|
||||
|
||||
## 5. 回归与后续工作
|
||||
|
||||
@@ -64,4 +64,4 @@ flowchart LR
|
||||
|
||||
进程回归由`make integration`构建二进制后显式执行。缺少一次性数据库或`ORBIT_TEST_SERVER_BINARY`时测试会跳过;跳过不构成进程恢复证据。验证记录见[本阶段报告](reports/phase-4-runtime.md)。
|
||||
|
||||
持久化信号等待及查询最终信号竞争已按[信号运行约定](14-workflow-signals.md)实现。下一步仍包括完整控制与人工恢复、实例/来源公共API、独立SDK和通用端到端场景。P4整体及P5–P7继续按[完整计划](08-development-plan.md)执行。
|
||||
持久化信号等待及查询最终信号竞争已按[信号运行约定](14-workflow-signals.md)实现。内部控制及停止结清也已接入。下一步仍包括人工恢复、实例/来源公共API、独立SDK和通用端到端场景。P4整体及P5–P7继续按[完整计划](08-development-plan.md)执行。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Weave 持久化定时等待与查询轮次
|
||||
|
||||
状态:TIMER到期推进和POLL后续业务轮次已接入Orbit后台运行器。复用MySQL和既有待续索引,不增加外部调度服务或数据库外键。[SIGNAL消费与查询最终信号竞争](14-workflow-signals.md)已进一步接入;实例公共HTTP/SDK以及完整控制/人工恢复仍未交付。
|
||||
状态:TIMER到期推进和POLL后续业务轮次已接入Orbit后台运行器。复用MySQL和既有待续索引,不增加外部调度服务或数据库外键。[SIGNAL消费与查询最终信号竞争](14-workflow-signals.md)已进一步接入;内部控制及停止结清已按[控制约定](15-workflow-controls.md)接入;实例公共HTTP/SDK以及人工恢复仍未交付。
|
||||
|
||||
## 1. 时钟和恢复身份
|
||||
|
||||
@@ -60,4 +60,4 @@ TIMER由待续表直接唤醒,不创建Pulse业务任务,也不占Worker执
|
||||
|
||||
[存储回归](../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)。
|
||||
SIGNAL早到/重复/超期处理及最终查询竞争已接入;内部失败分支结清和控制已接入;下一阶段继续人工恢复、公共控制及实例SDK,完整范围见[持续计划](08-development-plan.md)。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Weave 外部信号与最终查询结果
|
||||
|
||||
状态:内部 Go 信号受理/查询、SIGNAL 等待、早到保存、截止处理及 POLL 最终信号竞争已接入 MySQL 和后台运行器。**实例与信号的公共 HTTP/独立 SDK 尚未开放**;完整控制、人工恢复和失败分支结清继续按[持续计划](08-development-plan.md)实现。定义发布 SDK 不等于实例运行 SDK。
|
||||
状态:内部 Go 信号受理/查询、SIGNAL 等待、早到保存、截止处理及 POLL 最终信号竞争已接入 MySQL 和后台运行器。**实例与信号的公共 HTTP/独立 SDK 尚未开放**;内部控制和失败分支结清已按[控制约定](15-workflow-controls.md)接入;人工恢复继续按[持续计划](08-development-plan.md)实现。定义发布 SDK 不等于实例运行 SDK。
|
||||
|
||||
## 1. 受理身份与权限
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
|
||||
## 4. 存储升级和运行边界
|
||||
|
||||
[迁移000020](../internal/storage/mysql/migrations/000020_workflow_signal_identity.up.sql)增加信号契约/代次/证据/处置/到期检查时间,以及等待的赢家引用。名称扩至128字符,关联保持精确字节,并兼容历史764字节值。35个实体、301个直接持久化字段声明均提供中文说明;数据库无外键、无级联删除。
|
||||
[迁移000020](../internal/storage/mysql/migrations/000020_workflow_signal_identity.up.sql)增加信号契约/代次/证据/处置/到期检查时间,以及等待的赢家引用。名称扩至128字符,关联保持精确字节,并兼容历史764字节值。截至000020为35个实体、301个直接持久化字段声明,均提供中文说明;数据库无外键、无级联删除。
|
||||
|
||||
历史信号没有足够身份和受理证明:旧PENDING标记REJECTED/LEGACY_UNVERIFIED,保留原载荷和时间;已消费历史不被重新解释。旧NULL等待元数据不能推测成有效新契约。迁移为当前SIGNAL等待回填原截止的检查点,保留已有检查点,排除终态实例及旧激活。
|
||||
|
||||
@@ -65,4 +65,4 @@
|
||||
|
||||
[受理回归](../internal/storage/mysql/workflow_signals_integration_test.go)、[消费回归](../internal/storage/mysql/workflow_signal_runtime_integration_test.go)、[真实v19升级](../internal/storage/mysql/workflow_signal_upgrade_integration_test.go)和[实际进程恢复](../internal/storage/mysql/workflow_runtime_process_integration_test.go)对应受理/并发/故障/升级边界,实际运行结果记录在[阶段报告](reports/phase-4-signals.md)。
|
||||
|
||||
下一步完成失败分支取消结清、实例暂停/继续/取消/人工核查恢复,再交付实例与信号HTTP、独立SDK及完整场景。当前内部存储测试不替代尚未开放的公共接口验收,也不替代生产MySQL切换与容量测试。
|
||||
内部失败分支取消结清、实例暂停/继续/取消已接入。下一步完成人工核查恢复,再交付实例与信号HTTP、独立SDK及完整场景。当前内部存储测试不替代尚未开放的公共接口验收,也不替代生产MySQL切换与容量测试。
|
||||
|
||||
63
docs/15-workflow-controls.md
Normal file
63
docs/15-workflow-controls.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Weave 控制与停止结清
|
||||
|
||||
状态:内部Go暂停、继续、取消服务及后台失败/取消结清运行器已接入。**公共实例/控制HTTP与独立SDK尚未开放,人工核查恢复仍在后续交付范围**。本文说明已实现的持久化规则,不把内部存储回归当作全部Weave或生产验收。
|
||||
|
||||
## 1. 控制操作
|
||||
|
||||
[内部控制契约](../weave/control/service.go)使用`Apply(token, workflowID, idempotencyKey, input)`,显式授权`workflows:control`。每次读取当前命名空间、固定定义版本及其全部队列权限,原键恢复也重新核验权限。actor由认证凭据确定,输入只包含以下字段:
|
||||
|
||||
| 字段 | 语义 |
|
||||
| --- | --- |
|
||||
| operation | PAUSE、RESUME或CANCEL |
|
||||
| expected_control_revision | 调用者观察到的控制版本,正整数,对外JSON为十进制字符串 |
|
||||
| reason | 必填操作原因,最多1024个Unicode字符,写入不可变审计 |
|
||||
|
||||
后台结果会增加实例revision,不能使操作者观察到的control_revision失效。成功控制操作同时增加两个版本;同键相同内容返回首次冻结回执,不再次增加版本或改时间。同键不同内容冲突,其他键携带过期控制版本也冲突。新操作不接受终态实例;已提交原键仍可恢复原回执。
|
||||
|
||||
认证 → 应用额度 → 原操作身份 → 排序队列 → 实例 → 门控的持锁顺序与受理、运行器一致。控制标记、版本、门控、必要的根检查点、事件、审计和回执同事务提交。审计失败时整个操作回滚。
|
||||
|
||||
## 2. 暂停与继续
|
||||
|
||||
PAUSE设置实例paused并关闭Pulse执行门控。已创建但尚未开始的任务不能新领取或取得开始授权;已经获得开始授权的尝试保留许可,按原租约继续上报。暂停与开始竞争由同一个应用/队列/门控事务顺序裁决。
|
||||
|
||||
暂停期间继续保存任务结果、信号与到期事实,不启动新步骤或新查询轮次;待推进工作保存根检查点。RESUME仅解除paused,并保存根接续;实例处于核查或已有停止意图时,门控仍关闭。它不清除未知结果、不撤回取消、不改变固定定义,也不重置截止、轮次或尝试预算。
|
||||
|
||||
已暂停时使用新键再次PAUSE、未暂停时RESUME、已接受用户取消后使用新键再次CANCEL都返回状态冲突;网络未确认时应使用原键核对。原控制回执不会因为稍后的后台结果变化而变成当前视图,最新状态用实例Get读取。
|
||||
|
||||
## 3. 首次停止意图
|
||||
|
||||
停止意图与执行状态独立保存,进入NEEDS_REVIEW后仍能继续结清其他已发出的工作。
|
||||
|
||||
| 字段 | 语义 |
|
||||
| --- | --- |
|
||||
| stop_kind | CANCEL为用户请求,FAILURE为固定FAIL_AFTER_SETTLED策略触发;首次保存后不覆盖 |
|
||||
| stop_requested_at | 首次停止意图的数据库时间,不随重报、核查或后来的控制操作变化 |
|
||||
| cancel_requested_at | 用户显式请求取消的时间;自动失败结清不冒充用户请求 |
|
||||
|
||||
用户取消先提交时,最终按CANCEL目标结清;失败策略先触发时,后来的用户取消仍保留FAILURE目标,最终已知结清后为FAILED。两个时间和操作审计都保留,不用后到命令改写早先失败事实。
|
||||
|
||||
REVIEW策略继续保留核查状态和已发出结果;FAIL_AFTER_SETTLED在失败或核查条件出现时冻结停止意图,阻止新工作并请求其他分支结束。未知效果、非法结果和冲突证据始终保留NEEDS_REVIEW,不能为进入终态自动判定业务成功或失败。
|
||||
|
||||
## 4. 结清过程
|
||||
|
||||
停止使用既有ROOT检查点恢复。每个短事务最多发出一个Pulse任务取消,保持结果流锁取得之后不再锁另一任务;步骤收尾最多32项,超出保存根接续。候选由数据库到期索引读取,多个节点竞争仍只提交一次状态变化。
|
||||
|
||||
1. 核对任务实际所有者、激活、步骤、队列、门控及POLL轮次,不能仅凭gate_id授权取消。未开始的任务复用Pulse取消规则立即结清;执行中的任务只记录取消意图,保留执行许可。
|
||||
2. 收集内部Inbox结果。已成功步骤及输出保留;已知失败或取消保留实际状态;未知结果转核查。查询成功返回PENDING时,停止中的POLL结清为取消,不再发下一轮请求。
|
||||
3. 尚未激活步骤记为SKIPPED,不创建新任务。取消前可靠受理的匹配信号先保留为已收到事实;新的信号保存WORKFLOW_STOPPING拒绝。未结清的纯等待由停止运行器关闭,稍后超时扫描不能覆盖已提交的停止意图。
|
||||
4. 全部活动叶子结清后才关闭尚未完成的组合节点。终态前核验全部历史任务双向归属、结果确认、未结束尝试和未释放许可;不只看当前步骤或当前激活。
|
||||
5. 全部工作已知结清且没有核查条件时,根与实例进入FAILED或CANCELLED,关闭门控、清除待续并保存审计。存在未知或核查条件时保持NEEDS_REVIEW和原停止意图,平台已无有效执行授权时不再空转,后续人工核查操作负责接续;租约失效或UNKNOWN不证明外部执行确实已经结束。
|
||||
|
||||
历史核验按原有限流程上限限制为最多10000条任务元数据,使用一次集合查询和索引关联,避免逐任务数据库往返。门控与所有者双向检查包括旧激活;损坏关联拒绝推进和终结,不依赖外键补救。此上限及每事务一个取消的吞吐仍需按P6实际负载验证,当前不作生产容量承诺。
|
||||
|
||||
CANCELLED仅表示本次流程停止已结清,不撤销先前成功的业务效果。停止回执中的CANCELLING也不表示外部执行已结束;必须通过后续实例、步骤与执行历史判断当前事实。
|
||||
|
||||
## 5. 升级与验证
|
||||
|
||||
[迁移000021](../internal/storage/mysql/migrations/000021_workflow_stop_intent.up.sql)新增两个带中文说明的停止字段及成对CHECK,增加任务所有者查询索引。35个实体、303个直接持久化字段声明,继续禁止数据库外键及级联删除。
|
||||
|
||||
历史显式取消保留cancel_requested_at;历史失败结清用原updated_at建立兼容停止边界。旧停止中的实例关闭门控并回填或提前根检查点;不更改control_revision、定义、输入、原截止或预算,终态及无停止条件的实例保持原样。升级顺序仍为停止旧写入节点 → 执行全部迁移 → 启动新版,不能让旧节点忽略新增停止字段继续写入。
|
||||
|
||||
[控制及结清回归](../internal/storage/mysql/workflow_controls_integration_test.go)覆盖控制版本、权限重报、开始竞争、失败/未知、审计回滚、信号与查询及超过32步骤接续;[真实v20升级](../internal/storage/mysql/workflow_stop_upgrade_integration_test.go)验证兼容回填;[实际Orbit进程回归](../internal/storage/mysql/workflow_runtime_process_integration_test.go)覆盖停止意图和结果在全停期间保存后由两个新进程接续。实际结果见[阶段报告](reports/phase-5-controls.md)。
|
||||
|
||||
下一步仍需完成人工核查恢复、公共实例/控制/信号/审计接口、独立SDK及可运行场景,再完成P6–P7生产故障、性能、运维和发布验收。当前测试不替代生产MySQL复制、故障切换、备份恢复或RPO/RTO验证。
|
||||
53
docs/reports/phase-5-controls.md
Normal file
53
docs/reports/phase-5-controls.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# P5 控制与停止结清回归
|
||||
|
||||
日期:2026-09-18。范围为内部Go控制服务、停止模型和后台结清运行器。公共HTTP/独立SDK、人工核查恢复及P6–P7仍未完成,持续目标继续。
|
||||
|
||||
## 已实现范围
|
||||
|
||||
- PAUSE/RESUME/CANCEL显式授权,稳定操作身份与独立control_revision;后台结果不使原控制版本失效。
|
||||
- 门控、控制标记、停止意图、事件、审计、冻结回执及必要根接续同事务。
|
||||
- 首次stop_kind和stop_requested_at保存CANCEL或FAILURE目标;进入核查不丢失,后来的用户取消不改写原失败目标。
|
||||
- FAIL_AFTER_SETTLED与用户取消收集并行分支及已有任务结果;运行中执行保留许可,未知保持核查。
|
||||
- 停止前信号保留、停止后信号拒绝;POLL停止后PENDING不消耗新业务轮次;停止与晚到超时由原意图隔离。
|
||||
- 超过32个步骤继续通过根检查点恢复;终态前检查所有历史任务归属、未结束尝试与许可。
|
||||
- 迁移000021增加两个中文注释字段和一个查询索引,实体仍35个,直接持久化字段303个,无外键。
|
||||
|
||||
详细约定见[控制与结清文档](../15-workflow-controls.md)。每次事务最多一个任务取消,其余步骤收尾最多32项;P6仍须验证真实负载和积压下的吞吐与延迟。
|
||||
|
||||
## 环境与结果
|
||||
|
||||
本机darwin/arm64、Go 1.27.1、Docker MySQL 8.4.10,临时隔离数据库,未接入业务或生产数据库。
|
||||
|
||||
| 检查 | 结果 |
|
||||
| --- | --- |
|
||||
| 首轮真实MySQL专项 | 控制18组及原信号/TIMER/POLL/结果运行器/Pulse取消/新建结构/v7/v9升级通过,`-race`,56.012秒 |
|
||||
| 基础回归 | 最终修订后再次运行`make fmt test vet build`通过,退出0 |
|
||||
| 修订后专项与实际进程 | 23组控制场景、真实v20升级及完整流程进程测试通过,`-race`,46.556秒;流程进程27.09秒、升级4.14秒 |
|
||||
| 全量隔离MySQL、流程进程、SDK与示例 | 修订后完整脚本通过,退出0;存储191.691秒,实际流程进程27.731秒,Worker SDK 94.897秒,最终SDK进程故障组94.033秒;19个SDK示例和2个独立业务示例全部通过 |
|
||||
| 数据结构与文档 | 当前MySQL外键0、无COMMENT字段0;303个直接持久化字段声明均有中文注释;891个本地文档链接、53段JSON检查通过 |
|
||||
|
||||
定向入口:
|
||||
|
||||
```sh
|
||||
go test -race -count=1 -run '^TestIntegration(WorkflowControls|WorkflowStopUpgrade|WorkflowRuntime|WorkflowClock|WorkflowSignalRuntime|WorkerCancellation|SchemaAndConstraints|NoForeignKeysUpgrade|ApplicationResourcesUpgrade)$' -v ./internal/storage/mysql
|
||||
go build -o /tmp/orbit-control-test-server ./cmd/orbit
|
||||
ORBIT_TEST_SERVER_BINARY=/tmp/orbit-control-test-server go test -race -count=1 -run '^TestIntegrationWorkflowRuntimeProcess$' -v ./internal/storage/mysql
|
||||
```
|
||||
|
||||
命令必须配合一次性`ORBIT_TEST_MYSQL_DSN`。跳过不代表通过。[全量脚本](../../scripts/test-mysql.sh)负责隔离数据库、构建实际二进制并显式运行流程进程回归。
|
||||
|
||||
首轮控制专项验证暂停时继续接收结果、使用原control_revision恢复、12个同键控制只形成一条审计、旧控制版本及撤销权限后的原键拒绝、控制/结清审计失败完全回滚,及运行中任务分别成功/失败/取消/未知时的最终事实。并行FAIL_AFTER_SETTLED在兄弟分支真实结清后才失败,UNKNOWN始终NEEDS_REVIEW;纯等待、停止前信号、业务PENDING查询不启动后继;60步骤的剩余59项通过有限批次收尾。
|
||||
|
||||
修订后专项及全量已验证开始与取消的8轮并发竞争、已领取未开始的暂停/继续、无合法反向归属的额外门控任务不能被取消、取消后原截止到达不改写意图,以及真实v20升级。v20用例只证明真实旧结构的数据迁移,实际执行恢复由独立进程测试验证。全量流程进程用例本体26.43秒:并行失败意图和在途兄弟任务经历全停后,仅在收集真实结果后进入FAILED;用户取消后的UNKNOWN由两个新进程恢复为NEEDS_REVIEW,不发出后继,也不产生错误终态。
|
||||
|
||||
完整脚本还通过旧v7外键移除、新建结构、结果订阅、Inbox/Outbox和SDK节点强杀恢复,临时MySQL容器已由脚本清理。移除外键后的000009–000021迁移没有重新引入外键;当前结构实查为0。
|
||||
|
||||
首次全量存储回归中两个新增测试使用内部错误名GATE_CLOSED作为协议码而失败,服务端实际按既有契约返回EXECUTION_PAUSED。已修正测试断言,生产门控规则未放宽;该次失败不计为全量通过,最终结果以修订后重跑为准。
|
||||
|
||||
## 剩余范围
|
||||
|
||||
1. 人工核查恢复及旧激活/原预算保护,不能将解除paused当成解除核查。
|
||||
2. 公共实例/步骤/控制/信号/来源/审计接口、独立SDK和端到端通用示例。
|
||||
3. 完整监控与故障矩阵、性能容量、MySQL高可用/备份恢复、运维与发布核对。
|
||||
|
||||
通过本阶段只能证明相应内部状态与单MySQL进程恢复行为,不能据此宣称整个平台生产验收完成。
|
||||
Reference in New Issue
Block a user