Files
orbit/docs/14-workflow-signals.md

7.5 KiB
Raw Blame History

Weave 外部信号与最终查询结果

状态:内部 Go 信号受理/查询、SIGNAL 等待、早到保存、截止处理及 POLL 最终信号竞争已接入 MySQL 和后台运行器。实例与信号的公共 HTTP/独立 SDK 尚未开放;完整控制、人工恢复和失败分支结清继续按持续计划实现。定义发布 SDK 不等于实例运行 SDK。

1. 受理身份与权限

内部契约为 Send(token, workflowID, idempotencyKey, input) 与 Get(token, workflowID, signalID)。输入绑定固定定义中的信号名称、内容版本、步骤键、显式目标激活序号和精确操作关联,附内容、受理原因与可选证据引用。

输入 限制及语义
name / payload_version 定义中冻结的名称/内容契约;ASCII,最多128/32字符
target_step_key 固定定义的目标步骤,最多64字符,必须为SIGNAL或带最终信号的POLL
target_activation_sequence 显式正数;首次和早到信号为1,旧信号不能跟随人工恢复后的新激活;尚不存在的未来代次拒绝
correlation_key 1至512字节UTF8,精确匹配,保留尾部空格;不由调用者随意省略
payload 固定类型的精确JSON,最多256KiB;显式null与缺失不同;POLL最终信号不能是PENDING
reason / evidence_ref 必填原因最多1024字符;可选证据引用最多512字符、不含空白/控制符;平台不访问引用地址

提交要求显式 workflows:signal 权限;查询要求 workflows:read。两者都核对当前凭据、命名空间、实例固定版本及全部相关队列权限。actor来自认证凭据,不能请求自报。现有bootstrap的定义发布授权不会自动授予信号操作权限。

提交按认证 → 应用额度 → 原幂等身份 → 排序队列 → 实例/门控/步骤持锁。首次受理将信号、检查点、事件、审计和冻结回执同事务写入。审计包含原请求摘要、受理时间和总截止;运行器会核对受理证明,参数被替换时转核查,数据库连接/SQL错误则保留原来源并退避重试。

同一实例最多保存1024条信号,包含拒绝及终结历史;原幂等身份恢复先于上限检查。同键同内容返回首次冻结回执,同键不同内容冲突。重报仍校验当前权限。受理回执中的PENDING不跟随消费变化,当前状态用Get读取。

2. 早到、迟到与消费

目标步骤尚未激活时,信号保持PENDING;步骤激活会创建立即到期的检查点扫描早到信号。每个等待固定名称、版本、操作关联、激活序号和原截止,消费选择按受理时间、信号ID排序的第一条匹配记录。

  • 信号必须在等待截止之前受理,等于截止不算按时。按时受理但控制进程稍后恢复,可以继续收集该事实。
  • 暂停或应用停用仍可收集结果;后继工作受原门控、额度及实例总截止约束。
  • 已激活时的关联不符、旧代次、已结清步骤或实例会保存明确拒绝原因;内容类型/定义契约无效的请求直接拒绝,不产生有效信号。
  • 同一等待只记录一个winner_signal_id;其余同代次信号保存WAIT_SETTLED或QUERY_SETTLED等原因。所有关联由事务核验,不使用外键。
  • SIGNAL在没有按时匹配信号的情况下到期,将等待标为EXPIRED、步骤和实例转NEEDS_REVIEW,并关闭新执行门控。

信号的expires_at固定为首次受理时的实例总截止。尚未匹配的早到信号通过单独到期索引结清;available_at仅表示下次检查时间,故障退避不能改变expires_at、accepted_at或等待截止。若实例已过总截止且仍需新工作,保留已收到事实并进入核查。

消费确认、等待赢家、步骤结果、后继任务或根检查点及审计同事务。审计失败不会留下“信号已消费但后继未保存”的部分状态。

3. 最终信号与POLL查询竞争

查询请求由Pulse执行,最终信号和查询结果由同一个实例事务裁决。PENDING只是一次成功查询观察,不争夺最终结果;请求失败也不允许创建新业务轮次绕过Pulse尝试预算。

条件 处理
最终查询结果早于信号受理,且在原查询截止内 查询结果胜出,信号保存QUERY_SETTLED;精度相同的时间优先查询
已有最终信号,当前无在途查询 结清POLL,不再创建下一轮查询
最终信号先到,查询尚未开始 保存信号赢家,使用Pulse取消规则结清未开始任务,再收集其Inbox结果
最终信号先到,查询正在执行 保存赢家和取消意图;保留当前任务、ACTIVE步骤及执行许可,等待Pulse实际结果
在途查询随后返回PENDING、相同最终结果或已知失败/取消 收集该查询结清后采用信号结果,不新增查询轮次
在途查询效果未知、结果不合法或返回不同最终结果 保留信号和查询证据,转NEEDS_REVIEW;不能让信号覆盖未知事实
原查询总截止已到,查询仍在途 关闭新执行门控,保留当前任务等待结清;后续结果不能自动清除已建立的核查状态

CONSUMED表示信号已被等待采用,不表示整个实例成功。带在途查询时,即使等待记录为SATISFIED,步骤仍保持ACTIVE直到Pulse确认结束。取消复用Pulse既有许可释放逻辑,不在Weave中实现另一套释放计数。

控制时钟发现查询结果已落库但未消费时,读取原Inbox事件参与裁决;不由扫描器先后决定赢家,也不绕过Inbox故障退避。结果、信号和许可预算均在MySQL持久保存,进程重启不重新选择已保存的赢家。

4. 存储升级和运行边界

迁移000020增加信号契约/代次/证据/处置/到期检查时间,以及等待的赢家引用。名称扩至128字符,关联保持精确字节,并兼容历史764字节值。35个实体、301个直接持久化字段声明均提供中文说明;数据库无外键、无级联删除。

历史信号没有足够身份和受理证明:旧PENDING标记REJECTED/LEGACY_UNVERIFIED,保留原载荷和时间;已消费历史不被重新解释。旧NULL等待元数据不能推测成有效新契约。迁移为当前SIGNAL等待回填原截止的检查点,保留已有检查点,排除终态实例及旧激活。

升级仍采用停止旧写入节点 → 应用全部迁移 → 启动新版;新版信号字段和运行语义不支持与旧节点混跑。后台扫描三类候选:结果Inbox、根/等待检查点和未匹配信号到期;每类最多100项,最终批次最多100项,每个候选短事务处理。

5. 验证与后续

受理回归、消费回归、真实v19升级和实际进程恢复对应受理/并发/故障/升级边界,实际运行结果记录在阶段报告。

下一步完成失败分支取消结清、实例暂停/继续/取消/人工核查恢复,再交付实例与信号HTTP、独立SDK及完整场景。当前内部存储测试不替代尚未开放的公共接口验收,也不替代生产MySQL切换与容量测试。