feat: persist workflow controls and settle stopped branches
This commit is contained in:
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验证。
|
||||
Reference in New Issue
Block a user