feat: validate Worker protocol and verify process crash recovery
This commit is contained in:
@@ -13,7 +13,7 @@
|
||||
| `/v1/tasks/{task_id}/attempts/{attempt_id}/evidence` 与证据详情 | P2 已实现 | [执行历史](execution-history.md) |
|
||||
| `/v1/queues` 创建与查询 | P1 已实现 | [队列接口](queues.md) |
|
||||
| 凭据校验与初始化 CLI | P1 已实现 | [鉴权](authentication.md) |
|
||||
| `/v1/worker/connect` | P2 服务端、底层 SDK 与自动 Worker 已实现;完整阶段验收继续推进 | [Worker 契约](worker.md) |
|
||||
| `/v1/worker/connect` | P2 已实现并通过阶段验收 | [Worker 契约](worker.md)、[Schema](worker-schema.md) |
|
||||
| `/v1/schedules` 与计划管理 | 计划 P3,尚未实现 | [协议草案](../03-http-websocket-protocol.md) |
|
||||
| `/v1/events/connect` | 计划 P3,尚未实现 | [协议草案](../03-http-websocket-protocol.md) |
|
||||
| `/v1/workflows` 与流程管理 | 计划 P4–P5,尚未实现 | [流程接口规划](workflows.md) |
|
||||
|
||||
62
docs/api/worker-schema.md
Normal file
62
docs/api/worker-schema.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# 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/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 必须携带稳定 error_code;SUCCEEDED 省略或使用空 error_code。
|
||||
- 返回时间使用 UTC RFC 3339,最多微秒精度。验证器应开启 format 断言以校验实际日历日期。
|
||||
|
||||
本轮收紧了开发期此前允许的省略控制字段、非规范计数字符串和数组内字段别名。当前 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。
|
||||
@@ -1,6 +1,6 @@
|
||||
# Worker 通信与执行契约 v1(开发中)
|
||||
# Worker 通信与执行契约 v1
|
||||
|
||||
已实现服务端执行事务、WebSocket 接入、[独立 Go 底层协议 SDK](../sdk/worker.md)、[自动 Worker 运行器](../sdk/worker-runtime.md) 与 [尝试/证据查询](execution-history.md),通过真实 WSS、自动续租、ACK 丢失/持续断网恢复、有界退出及历史权限/分页回归。**P2 尚未完成**:完整协议 Schema 与完整阶段验收继续推进。底层 WorkerConnection 不自动管理处理器;NewWorker / Run 提供自动管理。
|
||||
已实现服务端执行事务、WebSocket 接入、[独立 Go 底层协议 SDK](../sdk/worker.md)、[自动 Worker 运行器](../sdk/worker-runtime.md) 与 [尝试/证据查询](execution-history.md),通过 [P2 阶段验收](../reports/phase-2.md),包含真实 WSS、协议 Schema、自动续租、ACK 丢失/断网恢复及进程强杀后的节点接管。底层 WorkerConnection 不自动管理处理器;NewWorker / Run 提供自动管理。
|
||||
|
||||
## 1. 接入与身份
|
||||
|
||||
@@ -22,6 +22,8 @@ go run ./cmd/orbit-admin bootstrap \
|
||||
|
||||
只接受 JSON 文本帧;单帧最多 512 KiB,业务结果最多 256 KiB。重复键、未知字段、无效 Unicode 和非法数值按 HTTP 相同规则拒绝。
|
||||
|
||||
机器可读契约及各方向定义见 [JSON Schema 说明](worker-schema.md)。控制字段必须显式提供;epoch/sequence 等计数使用无前导零的规范十进制字符串。请求禁止响应字段,空字符串/null 也不例外。
|
||||
|
||||
```json
|
||||
{
|
||||
"protocol_version":"1",
|
||||
@@ -143,4 +145,4 @@ receipt 是原操作的不可变确认;lease 是本次重新核验的执行权
|
||||
|
||||
这些是有界的开发基线,不代表经过容量压测的生产参数。当前同队列操作使用较粗的行锁协调,吞吐与公平性需要 P6 按负载验证。服务退出会显式关闭被 HTTP Upgrade 接管的连接;断开不会直接撤销外部已发出的请求。
|
||||
|
||||
运行中取消、完整 WS JSON Schema、凭据轮换和多节点进程级故障演练尚未全部完成。SDK 已实现自动重连/续租、非协作处理器的有界退出与状态报告;实际证据见 [P2 服务端阶段记录](../reports/phase-2-server.md) 和 [自动运行器回归](../reports/phase-2-worker-runtime.md)。
|
||||
协议 Schema 和真实进程强杀恢复已通过回归,见 [P2 阶段验收](../reports/phase-2.md)。运行中取消属于 P3;凭据轮换、数据库故障切换、跨主机演练与容量验收属于后续生产验证。自动运行器对非协作处理器提供有界退出与状态报告,不能强制停止其外部副作用。
|
||||
|
||||
Reference in New Issue
Block a user