# Worker v1 机器可读契约 子协议为 `pulse.worker.v1`,消息中 `protocol_version` 为 `"1"`。完整文件:[worker.schema.json](../../protocol/workerv1/worker.schema.json),使用 JSON Schema Draft 2020-12。业务含义、超时及恢复方式见 [Worker 接口手册](worker.md)。 文件中的 $id 是契约标识,不表示该 URL 已部署下载服务。仓库文件是当前发布载体;回归使用本地嵌入文件,不访问远程 Schema。 ## 校验入口 Schema 根接受双向消息,调用方应根据方向选择更严格的定义: | JSON Pointer | 用途 | | --- | --- | | `#/$defs/clientFrame` | Worker → 服务端的所有请求 | | `#/$defs/serverFrame` | 服务端 → Worker 的所有报文 | | `#/$defs/helloFrame` | 注册请求,不允许 session_id、reply_to 或 error | | `#/$defs/capacityFrame` | 容量及排空声明,sequence/capacity/drain 均必填 | | `#/$defs/resumeFrame` | 尝试归属恢复请求 | | `#/$defs/startFrame`、`renewFrame`、`finishFrame` | 开始、续租、结果报告 | | `#/$defs/welcomeFrame`、`assignmentFrame` | 注册确认与主动派发 | | `#/$defs/cancellationFrame` | 已选择通知的连接接收 task.cancel,无 reply_to | | `#/$defs/ackFrame`、`errorFrame` | 操作确认与公开错误 | 除首条 hello 外,请求必须提供当前 session_id。请求不得包含响应专用字段,包括 `reply_to:""` 或 `error:null`。主动派发没有 reply_to;操作响应通过 reply_to 关联原消息。error 在注册失败时不带 session_id;会话内错误带 session_id,主动致命错误不带 reply_to。 ACK 的 body 根据原请求选择:worker.capacity → welcome,worker.resume → lease,task.start/renew/finish → commandResult。Schema 可以检查三个 body 形状,消息关联与正确分支由连接状态检查;不能仅凭一个独立 ACK 判断它是否对应调用。 ## 字段和兼容规则 - 已声明对象使用 additionalProperties=false,业务 payload/result 内部字段由接入方定义。 - 结构体必填字段必须显式提供,包括 capacity=0、drain=false;缺少字段不能被解释为调用者明确选择零值。 - epoch、sequence、revision 为规范十进制字符串:范围 1–18446744073709551615,无前导零和正号。SDK 使用 uint64,线上使用字符串。 - instance_secret/lease_secret 必须是 32 字节秘密的严格无填充 base64url,长度 43;知道资源 ID 无法替代秘密。 - 结果为非 null JSON;FAILED/UNKNOWN/CANCELLED 必须携带稳定 error_code;SUCCEEDED 省略或使用空 error_code。 - hello.cancellation_notifications 可选且默认 false;Lease 可返回 cancel_requested_at。CANCELLED 需要事务核验已保存意图;通知、取消后执行边界与升级顺序见 [取消契约](cancellation.md)。 - hello.concurrency_keys 可选且默认 false,未声明时不派发带资源键任务;task.assign.task.concurrency_key 与非零字符串 concurrency_token 必须同时出现。Schema 检查字段配对,SDK 另核验支持声明和键格式,事务维护许可;见 [资源键契约](keyed-concurrency.md)。 - finish.retryable 为可选布尔值,默认 false;true 仅允许 FAILED,Schema 与服务端都校验。派发任务可带 effect_uncertain=true,表示此前授权执行的效果尚未核实。业务重试条件见 [安全重试](retries.md)。 - 返回时间使用 UTC RFC 3339,最多微秒精度。验证器应开启 format 断言以校验实际日历日期。 - task.assign.task.retry_of为可选原任务ID,表示人工重试的直接来源;SDK校验合法ID及非自身关联。旧SDK忽略未知响应字段,使用旧版严格Schema的客户端需更新Schema;业务幂等身份不因新taskID变化,见[人工恢复](task-recovery.md)。 - task.assign.task.priority 为可选 0–9 整数,零值省略;平台在实际到期后结合等待时间排序,详见 [优先级与公平派发](priority-and-fairness.md)。 P2 收紧了开发期此前允许的省略控制字段、非规范计数字符串和数组内字段别名。当前 SDK 一直发送完整规范字段,不需迁移;其他自研客户端应按本文件更新。SDK 尚未发布首个版本。将来扩展消息类型或改变字段语义必须同时更新 Schema、服务端、SDK 与兼容回归。 ## Schema 与运行时的边界 Schema 检查已解析的 JSON 结构。以下约束必须在原始字节或持久化事务层另外校验: | 约束 | 实际执行位置 | | --- | --- | | 文本帧、512 KiB 总帧限制 | WS 读写与解码入口 | | 重复键、无效 UTF-8、孤立代理项、32 层嵌套 | 严格 JSON 扫描器,不能先交给会替换非法字符的解析器 | | 结果 256 KiB、精确数字文本/指数范围 | 结果校验器;JSON Schema 的字符数不等于编码字节数 | | JSON 整数字段的文本形式 | Go 类型解码,例如 1.0 不作为整数控制字段接受 | | 当前会话、reply_to 与原操作匹配 | WS 会话及 SDK 控制请求表 | | 身份、权限、队列、租约、版本及时间先后关系 | 数据库事务与执行状态机 | | 原始回执与当前执行权分离 | CommandResult.receipt 与 lease;历史回执不能复活执行 | 通过 Schema 只说明报文形状合法,不能证明请求已获授权、操作已经提交或业务副作用只发生一次。 ## 可复现的验证 ```sh go test -race ./internal/transport/httpserver -run TestWorkerPublishedContract make integration ``` 契约测试对合法消息及变异消息同时运行 Schema 和实际应用输入校验,包含数组内字段别名、缺少字段、错误方向、容量边界、计数溢出、非规范秘密及结果分类。真实 MySQL/WSS 测试在发送和接收时校验实际报文,并覆盖注册、容量、派发、开始、续租、恢复、结果及错误。 测试使用固定版本 [santhosh-tekuri/jsonschema v6.0.2](https://pkg.go.dev/github.com/santhosh-tekuri/jsonschema/v6@v6.0.2),显式开启 AssertFormat。这个验证器只用于测试工具包,不进入 Orbit 服务二进制或独立 SDK 的依赖图;运行平台仍只要求 MySQL。