feat: add standalone Worker protocol SDK and ACK-loss regression
This commit is contained in:
@@ -26,7 +26,7 @@
|
||||
| --- | --- | --- | --- |
|
||||
| P0 基础与数据模型 | Go workspace、独立 SDK module、公共/Pulse/Weave 模型、MySQL 迁移、配置、健康检查 | 编译/竞态/静态检查;真实 MySQL 建表、隔离、唯一性、预算、不可变版本、迁移失败防护;SDK 健康调用 | 已完成并通过阶段回归(见 P0 报告) |
|
||||
| P1 任务受理闭环 | 应用凭据与作用域权限、队列、幂等提交、查询、待执行取消、受理事件;SDK 客户端 | API/SDK 创建查询闭环;重复键与内容冲突、响应未确认重报、跨命名空间拒绝、参数边界 | 已完成并通过阶段回归(见 P1 报告;真实断路/提交 ACK 丢失注入留后续故障阶段) |
|
||||
| P2 Worker 执行闭环 | WSS 接入、能力/容量、领取与开始、租约、续租、结果确认、排空与恢复;Worker SDK | 真 Worker 执行;失联/重连/重复确认/旧尝试拒绝;业务效果未知转核查;节点故障接管 | 开发中:服务端执行事务和 WSS 已通过阶段内回归;Worker SDK 自动运行/重连/退出及完整验收待完成 |
|
||||
| P2 Worker 执行闭环 | WSS 接入、能力/容量、领取与开始、租约、续租、结果确认、排空与恢复;Worker SDK | 真 Worker 执行;失联/重连/重复确认/旧尝试拒绝;业务效果未知转核查;节点故障接管 | 开发中:服务端、独立 SDK 底层协议及实际 ACK 丢失恢复回归通过;文本执行示例可运行;自动运行/重连/退出、查询与完整验收待完成 |
|
||||
| P3 Pulse 完整能力 | 安全重试、延时、Cron/固定间隔、漏跑策略、计划版本、并发许可、配额/背压、可靠结果订阅 | 多实例领取/触发竞争、重试上限、取消竞争、队列隔离、积压恢复、事件重复交付 | 待开发 |
|
||||
| P4 Weave 主流程 | SDK 定义构建与发布校验、实例、顺序/分支/结构化并行汇合、信号/定时等待、版本绑定 | 重启接续、早到/重复信号、并行竞争、内部事件重放、发布版本兼容;端到端通用流程 | 待开发 |
|
||||
| P5 Weave 恢复与查询 | 有界查询、暂停继续、取消、人工核查恢复、控制门控与审计 | 轮次与尝试独立预算;暂停/开始/回执/超时竞争;恢复保留预算;未知结果不盲目重复 | 待开发 |
|
||||
@@ -74,3 +74,4 @@ SDK、文档与示例随 P1–P5 同步开发,P7 是全量核对,不是最
|
||||
- [P0 验证记录](reports/phase-0.md)
|
||||
- [P1 验证记录](reports/phase-1.md)
|
||||
- [P2 服务端阶段记录](reports/phase-2-server.md)
|
||||
- [P2 SDK 协议阶段记录](reports/phase-2-sdk-protocol.md)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
- 文档版本:0.2
|
||||
- 整理日期:2026-09-17
|
||||
- 阶段:P0/P1 已完成,P2 服务端执行/WSS 已通过阶段内回归,Worker SDK 继续开发;尚未完成生产验收
|
||||
- 阶段:P0/P1 已完成,P2 服务端与 Worker 底层 SDK 已通过阶段内回归,自动 Worker 运行器继续开发;尚未完成生产验收
|
||||
- 适用范围:Orbit 统一平台,包含 Pulse 任务调度模块、Weave 流程编排模块与公共能力。平台面向多个业务系统复用。
|
||||
|
||||
## 阅读顺序
|
||||
@@ -56,7 +56,7 @@ Orbit 不内置特定行业规则;Pulse 管理执行,Weave 管理步骤依
|
||||
| --- | --- | --- |
|
||||
| HTTP / WS 的最终字段、路径、错误码 | 以本稿作为协议草案,评审后冻结 v1 | [协议](03-http-websocket-protocol.md) |
|
||||
| Weave 技术细则 | 功能范围已确认;SDK/定义 Schema、暂停门控与计时、查询预算、并行失败策略、人工恢复身份仍需评审 | [流程](06-workflow-spec.md) |
|
||||
| WS 库及后续依赖版本 | 当前基础使用 Go 1.27.1、MySQL 8.4+ 与显式 SQL;WS 库随 P2 实现锁定 | [模型基线](07-data-model.md) |
|
||||
| WS 库及后续依赖版本 | 当前基础使用 Go 1.27.1、MySQL 8.4+ 与显式 SQL;WS 已锁定 coder/websocket v1.8.15,后续依赖需单独验证 | [模型基线](07-data-model.md) |
|
||||
| 人工重试的任务身份 | 建议创建关联的新任务,自动重试保持原任务 ID | [功能](01-functional-spec.md) |
|
||||
| Cron、固定间隔与夏令时细节 | 建议五段 Cron、固定间隔首版采用 fixed-rate;夏令时行为需明确 | [功能](01-functional-spec.md) |
|
||||
| 批量大小、消息上限、心跳、租约、扫描周期 | 均需设置有限上限;数值通过原型与压测确定 | [验收](05-production-acceptance.md) |
|
||||
@@ -79,4 +79,4 @@ Orbit 不内置特定行业规则;Pulse 管理执行,Weave 管理步骤依
|
||||
|
||||
2026-09-17,文档更新至 0.2:用户确认研发定义发布流程及 Weave 首版功能,明确纳入有界重复查询和暂停/继续等生产管理能力。技术细则与参数继续按建议或待定标注,未将功能确认等同于实现或验收通过。
|
||||
|
||||
持续开发目标已建立。当前实现和验收进度以 [开发计划](08-development-plan.md)、[P0 报告](reports/phase-0.md)、[P1 报告](reports/phase-1.md)、[P2 服务端记录](reports/phase-2-server.md) 为准;早期设计稿中的“未实现”描述保留其编写阶段语境。
|
||||
持续开发目标已建立。当前实现和验收进度以 [开发计划](08-development-plan.md)、[P0 报告](reports/phase-0.md)、[P1 报告](reports/phase-1.md)、[P2 服务端记录](reports/phase-2-server.md)、[P2 SDK 协议记录](reports/phase-2-sdk-protocol.md) 为准;早期设计稿中的“未实现”描述保留其编写阶段语境。
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
| `/v1/tasks` 提交、查询、分页与待执行取消 | P1 已实现 | [任务接口](tasks.md) |
|
||||
| `/v1/queues` 创建与查询 | P1 已实现 | [队列接口](queues.md) |
|
||||
| 凭据校验与初始化 CLI | P1 已实现 | [鉴权](authentication.md) |
|
||||
| `/v1/worker/connect` | P2 服务端已实现,Worker SDK 仍在开发 | [Worker 契约](worker.md) |
|
||||
| `/v1/worker/connect` | P2 服务端及底层 SDK 已实现,自动 Worker 运行器开发中 | [Worker 契约](worker.md) |
|
||||
| `/v1/schedules` 与计划管理 | 计划 P3,尚未实现 | [协议草案](../03-http-websocket-protocol.md) |
|
||||
| `/v1/events/connect` | 计划 P3,尚未实现 | [协议草案](../03-http-websocket-protocol.md) |
|
||||
| `/v1/workflows` 与流程管理 | 计划 P4–P5,尚未实现 | [流程接口规划](workflows.md) |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Worker 通信与执行契约 v1(开发中)
|
||||
|
||||
已实现服务端执行事务、WebSocket 接入和真实 WSS 回归。**P2 尚未完成**:独立 Go SDK 的 Worker 运行器、自动重连/续租、处理器生命周期与优雅退出还在开发。本页记录当前可验证的服务端契约,不把测试客户端当作可交付 Worker SDK。
|
||||
已实现服务端执行事务、WebSocket 接入、[独立 Go 底层协议 SDK](../sdk/worker.md) 及真实 WSS/ACK 丢失回归。**P2 尚未完成**:自动 Worker 运行器、自动重连/续租、处理器生命周期与优雅退出还在开发。本页记录当前可验证的协议;底层 SDK 不自动管理处理器。
|
||||
|
||||
## 1. 接入与身份
|
||||
|
||||
@@ -76,7 +76,7 @@ worker.welcome 返回 session_id、epoch、server_time、expires_at、lease_dura
|
||||
| worker.capacity | sequence 字符串、capacity 0–256、drain bool | 更新后的 welcome 字段 |
|
||||
| task.assign | 服务端主动发送 | task 完整任务、attempt_id、epoch、lease_secret、lease_until、server_time |
|
||||
|
||||
capacity 使用单调递增序号和覆盖值。同序号同内容可重复,同序号不同内容或旧序号冲突;capacity=0 不释放已有任务的并发许可。drain=true 是进程级持久化排空,重连保留,不能通过后续消息清除;新进程使用新实例身份。
|
||||
capacity 使用单调递增序号和覆盖值。同序号同内容可重复,同序号不同内容或旧序号冲突;capacity=0 不释放已有任务的并发许可。drain=true 是进程级持久化排空,重连保留;后续必须保持 drain=true,尝试清除返回 STATE_CONFLICT。新进程使用新实例身份。
|
||||
|
||||
一个 Worker 进程当前绑定一个队列。可以运行多个 Worker 进程或后续 SDK 实例消费不同队列;不能通过重连静默切换队列。
|
||||
|
||||
|
||||
@@ -19,6 +19,15 @@
|
||||
- 异常:凭据失效、权限不足、内容冲突、版本竞争和未知网络结果,见 [任务接口](../api/tasks.md)。
|
||||
- 清理:示例以取消结束;任务和审计历史保留。重复运行会生成独立示例任务。
|
||||
|
||||
## 已可运行:文本规范化执行
|
||||
|
||||
- 源码:[Worker 底层协议示例](../../sdk/go/examples/worker-protocol/main.go)。
|
||||
- 前置:专用 Worker 凭据,启动步骤见 [Worker SDK 文档](../sdk/worker.md)。
|
||||
- 输入与步骤:提交 `{"text":" Hello Orbit "}` → 注册/容量 → 领取 → 开始授权 → 实际处理 → 确认结果 → 查询 → 排空。
|
||||
- 预期:SUCCEEDED、一次尝试、结果 `{"text":"HELLO ORBIT"}`。
|
||||
- 异常:控制 ACK 丢失使用原身份有限重报;业务函数不随重连再次调用;迟到证据不能当作成功结果。自动续租与持续消费仍待运行器实现。
|
||||
- 清理:任务历史保留;运行结束确认排空并关闭连接。每次示例使用独立任务/处理器身份。
|
||||
|
||||
## 计划场景与验收标准
|
||||
|
||||
| 场景 | 输入与步骤 | 预期结果 | 必测异常 | 状态 |
|
||||
|
||||
55
docs/reports/phase-2-sdk-protocol.md
Normal file
55
docs/reports/phase-2-sdk-protocol.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# P2 Worker SDK 协议阶段回归
|
||||
|
||||
日期:2026-09-17。此记录覆盖独立 SDK 的底层连接和一次性执行闭环,**不代表 P2 完成,也不代表自动 Worker 运行器已交付**。
|
||||
|
||||
## 实现范围
|
||||
|
||||
- 独立 module 内实现 WS/WSS 注册、容量/心跳、派发读取、Start、Renew、Finish、Resume;不引用服务端模型/存储。
|
||||
- 固定子协议、授权头、受信任 TLS、禁用重定向/压缩、握手/控制/读取时限及缓冲上限。
|
||||
- 并发 ACK 关联、稳定消息身份、公开错误分类;秘密和业务结果在默认格式化输出中隐藏。
|
||||
- 当前租约与原回执分离,保守单调时钟期限;精确 JSON 数字及字符串 uint64 版本。
|
||||
- 可运行的纯文本规范化示例,有限手动重连核对控制操作,不重复调用处理器。
|
||||
- 新增字段均有中文契约注释;无持久化模型或迁移变更。
|
||||
|
||||
## 验证环境与命令
|
||||
|
||||
macOS arm64,Go 1.27.1,Docker 隔离 MySQL 8.4.10。连接依赖锁定 `github.com/coder/websocket v1.8.15`。
|
||||
|
||||
```sh
|
||||
make test
|
||||
make vet
|
||||
make build
|
||||
make integration
|
||||
cd sdk/go
|
||||
GOWORK=off go test -race ./...
|
||||
GOWORK=off go vet ./...
|
||||
GOWORK=off go test -run '^$' -fuzz FuzzWorkerJSON -fuzztime=15s .
|
||||
```
|
||||
|
||||
测试脚本在一次性数据库先执行原服务端迁移、任务、执行、WSS 回归,再启动真实 orbit 命令及独立凭据,用 SDK 接入该服务;随后执行真实示例。测试不连接已有业务库,凭据不放入 URL、命令参数或输出。WSS 故障网关使用 `httptest.NewTLSServer` 及受信任测试证书,没有跳过证书校验。
|
||||
|
||||
## 通过的场景
|
||||
|
||||
| 测试层 | 场景与断言 |
|
||||
| --- | --- |
|
||||
| SDK 单元/WSS | 派发与 ACK 交错,多个请求逆序响应仍正确关联;业务整数/高精度小数和 uint64 版本不转为 float64 |
|
||||
| SDK 授权判断 | 数据库墙钟偏差 24 小时不改变本地有效窗口;扣除全请求耗时和 250 毫秒余量;历史 RUNNING 回执和自行解码的 Lease 均不能授权 |
|
||||
| SDK 有界传输 | 32 个未确认控制请求后拒绝新增;同 ID 同时在途拒绝;取消让所有等待者退出;派发缓冲耗尽关闭;关闭后不返回缓存任务 |
|
||||
| SDK 协议防护 | 重定向不转交凭据;非法/未知回复、错误会话控制、失效凭据错误关闭;拒绝重复键、非法 Unicode、过深 JSON;默认格式化隐藏秘密 |
|
||||
| 真实服务 + MySQL + WSS 故障网关 | 服务端完成 start 后丢 ACK;新连接 Resume 并重报原 start ID 得到原回执,原尝试保持不变 |
|
||||
| 真实服务 + MySQL + WSS 故障网关 | 服务端完成 finish 后丢 ACK;新连接核对原结果,保持 SUCCEEDED、一次尝试及原始精确数值;旧 start ACK 不能再次授权 |
|
||||
| 真实服务 + MySQL | 同消息续租返回原版本/期限;冲突结果只保存 EVIDENCE_ONLY;持久化排空跨重连,尝试清除被拒绝 |
|
||||
| 真实服务 + MySQL | 短尝试时限驱动本地 context 到期;过期后旧回执不授权、迟到报告仅证据;服务端恢复为 NEEDS_REVIEW,不生成第二次尝试 |
|
||||
| 真实命令行示例 | 提交文本 → 开始授权 → 实际规范化 → 上报 → 查询 → 排空;输出 SUCCEEDED、attempts=1、HELLO ORBIT |
|
||||
|
||||
15 秒 JSON 模糊测试本次执行 738,707 个输入,通过。实际执行数只描述本次运行,不是稳定吞吐或性能基准。完整隔离回归中原服务端测试通过,SDK 故障测试通过,三类 SDK 示例通过。
|
||||
|
||||
首次新增集成测试把“已排空后发送 Drain=false”误写为可成功但保持排空;实际服务端按既定契约返回 STATE_CONFLICT。已修正测试为确认拒绝,再以 Drain=true 心跳验证,重新执行完整隔离回归通过。没有为通过测试放宽服务端排空语义。
|
||||
|
||||
## 尚未覆盖与下一步
|
||||
|
||||
本轮故障恢复由测试驱动器/示例显式调用底层 SDK,不应描述为自动重连。业务函数调用一次的断言限定在示例驱动流程,不能推导任意外部系统的 exactly-once 效果。
|
||||
|
||||
下一步实现自动 Worker 运行器:处理器注册与并发限制、自动心跳/续租、单调期限取消、同进程断线恢复、稳定结果重报、处理器 panic/未知效果分类、非协作处理器与有界排空退出。之后继续补齐尝试/证据查询、完整 WS Schema 和 P2 阶段验收。
|
||||
|
||||
进程崩溃、宿主故障、数据库故障转移、生产 TLS 终止及高并发容量验证仍在后续范围。本地受控 WSS 中断不等同于跨故障域高可用验收。
|
||||
@@ -1,8 +1,8 @@
|
||||
# Go SDK 接入说明
|
||||
|
||||
已实现健康查询、任务提交/查询/分页/待执行取消、队列创建/查询。Worker 和流程构建接口按 [开发计划](../08-development-plan.md) 继续实现。
|
||||
已实现健康查询、任务提交/查询/分页/待执行取消、队列创建/查询,以及 [Worker 底层协议 SDK](worker.md)。自动 Worker 运行器和流程构建接口按 [开发计划](../08-development-plan.md) 继续实现。
|
||||
|
||||
module:`git.yuntuo.hk/k2safe/orbit/sdk/go`。SDK 使用独立 go.mod,当前仅依赖 Go 标准库,不引用服务端模型或数据库实现。
|
||||
module:`git.yuntuo.hk/k2safe/orbit/sdk/go`。SDK 使用独立 go.mod,依赖 Go 标准库与 `github.com/coder/websocket v1.8.15`,不引用服务端模型或数据库实现。
|
||||
|
||||
## 1. 从初始化到运行示例
|
||||
|
||||
@@ -133,4 +133,4 @@ go mod tidy
|
||||
|
||||
## 6. 后续交付
|
||||
|
||||
P2 提供 Worker 注册、WSS、能力/容量、执行确认、续租和排空;P3 提供计划与结果订阅;P4–P5 提供流程构建发布、信号、等待、轮询与人工恢复。每项随实现同步交付可运行示例及异常回归。
|
||||
P2 已提供 Worker 底层注册、WSS、能力/容量、执行确认、续租、恢复和排空接口及 [可运行示例](worker.md),继续开发自动 Worker 运行器;P3 提供计划与结果订阅;P4–P5 提供流程构建发布、信号、等待、轮询与人工恢复。每项随实现同步交付可运行示例及异常回归。
|
||||
|
||||
123
docs/sdk/worker.md
Normal file
123
docs/sdk/worker.md
Normal file
@@ -0,0 +1,123 @@
|
||||
# Go Worker 底层协议 SDK
|
||||
|
||||
更新:2026-09-17。已实现可独立构建的 `WorkerConnection`,配合真实 Orbit 服务和 MySQL 通过控制操作、WSS、ACK 丢失与租约过期回归。**自动 Worker 运行器仍在开发**:本页的方法不会自动启动处理器、心跳、续租、重连或排空。需要持续消费的接入方应等待运行器交付,不能把一次性示例当作完整托管运行时。
|
||||
|
||||
源码:[连接与控制方法](../../sdk/go/worker_connection.go)、[中文注释的数据契约](../../sdk/go/worker_types.go)。传输字段、权限和事务语义见 [Worker 接口](../api/worker.md)。SDK 独立 module,只依赖标准库和锁定版本的 `github.com/coder/websocket v1.8.15`,不导入服务端包。
|
||||
|
||||
## 1. 可运行的文本规范化示例
|
||||
|
||||
需要已完成迁移、已启动的 Orbit 和具有 `workers:connect` / `workers:consume` 权限的专用凭据。在仓库根目录运行:
|
||||
|
||||
```sh
|
||||
mkdir -p .local
|
||||
chmod 700 .local
|
||||
go run ./cmd/orbit-admin bootstrap \
|
||||
--application worker-example --namespace default --environment development \
|
||||
--queue normalization --worker-access --output .local/worker.credentials.json
|
||||
cd sdk/go
|
||||
ORBIT_URL=http://127.0.0.1:8080 \
|
||||
ORBIT_CREDENTIALS_FILE=../../.local/worker.credentials.json \
|
||||
go run ./examples/worker-protocol
|
||||
```
|
||||
|
||||
预期输出:
|
||||
|
||||
```text
|
||||
task=<32位任务ID> final_state=SUCCEEDED attempts=1 result={"text":"HELLO ORBIT"}
|
||||
```
|
||||
|
||||
[完整源码](../../sdk/go/examples/worker-protocol/main.go) 实际提交 `{"text":" Hello Orbit "}`,领取并取得开始授权,执行去首尾空格/转大写,报告结果、查询当前状态并排空。没有生成文件或调用外部服务。每次运行创建独立任务与临时处理器名,避免消费前次示例遗留任务;历史和审计保留,不硬删除。
|
||||
|
||||
示例最多对开始/结果操作重连重报两次,保持原进程身份、尝试证明、消息 ID 和内容;业务函数只在首次取得有效开始确认后调用一次。网络结果仍不明时非零退出,不能推断服务端回滚。身份与待确认结果只保留在当前进程内,进程被终止后的未知结果由服务端回收进入核查。本示例处理很短的纯计算,不演示长任务自动续租。
|
||||
|
||||
## 2. 创建进程身份与连接
|
||||
|
||||
以下为接入函数内片段;完整错误处理见示例。
|
||||
|
||||
```go
|
||||
registration, err := orbit.NewWorkerRegistration(queueID, 4, []orbit.WorkerCapability{
|
||||
{Handler: "text.normalize", HandlerVersion: "v1", PayloadVersion: "v1"},
|
||||
})
|
||||
if err != nil { return err }
|
||||
|
||||
conn, err := client.DialWorker(ctx, registration)
|
||||
if err != nil { return err }
|
||||
defer conn.Close()
|
||||
```
|
||||
|
||||
同一进程只生成一次 registration;重连复用,进程重启换新值。它固定凭据、队列、能力集合和实例秘密。不要把身份和秘密复制给另一个活跃进程:新会话会隔离旧会话。
|
||||
|
||||
`DialWorker` 的 ctx 只控制握手,最长 8 秒,调用方配置的 HTTP 超时可以更短;成功返回后需主动 Close。URL 基于 `NewClient` 的 HTTP(S) 地址,分别建立 WS/WSS,禁止重定向,不关闭 TLS 证书校验,不把 token 放入 URL。只支持 `pulse.worker.v1` 子协议,禁用压缩。
|
||||
|
||||
`Welcome()` 返回首次连接快照;`Done()` 关闭表示读取循环已退出;`Err()` 返回关闭原因。`Close()` 立即停止传输,不撤销外部已发出的请求,也不代替排空确认。
|
||||
|
||||
注册和尝试证明包含秘密,JSON 序列化只用于协议。SDK 的 `String` / `GoString` 隐藏注册、尝试、派发和结果中的秘密/业务数据;直接读字段、JSON 日志和调试器仍可能泄露,接入方应只记录任务 ID、尝试 ID 和错误分类。
|
||||
|
||||
## 3. 方法清单
|
||||
|
||||
除 Welcome/Done/Err/Close,所有连接操作第一个参数都是 context。控制操作同时要求调用方提供 32 位小写十六进制 message ID。
|
||||
|
||||
| 方法 | 输入 | 返回 | 注意事项 |
|
||||
| --- | --- | --- | --- |
|
||||
| `NewWorkerRegistration` | queueID、capacity、capabilities | WorkerRegistration | 生成随机进程身份与秘密,复制/排序能力,拒绝重复能力 |
|
||||
| `NewWorkerMessageID` | 无 | string | 只为新的逻辑操作生成;未知结果重报复用旧值 |
|
||||
| `client.DialWorker` | registration | *WorkerConnection | 握手后尚未启用派发 |
|
||||
| `conn.Capacity` | messageID、WorkerCapacity | WorkerWelcome | 总容量覆盖值;同时续期会话 |
|
||||
| `conn.NextAssignment` | ctx | WorkerAssignment | 只表示预占,不能直接运行处理器 |
|
||||
| `conn.Start` | messageID、WorkerAttempt | WorkerCommandResult | 持久化开始后确认,检查 Lease 的当前授权 |
|
||||
| `conn.Renew` | messageID、WorkerAttempt | WorkerCommandResult | 新续租用新消息;原消息只核对原操作 |
|
||||
| `conn.Finish` | messageID、WorkerFinish | WorkerCommandResult | 区分权威结果 APPLIED 与证据 EVIDENCE_ONLY |
|
||||
| `conn.Resume` | messageID、WorkerAttempt | WorkerLease | 重连核对原尝试,不创建尝试、不延长租约 |
|
||||
|
||||
同连接内 `Capacity.Sequence` 从 1 开始递增;同序号必须同容量/排空标志,不能用增量值。容量为零停止新领取,不释放在途许可。首次确认容量才开启派发,所以重连时可以先 Resume 所有已知尝试,再发布容量。会话与任务续期是两件事:Capacity 不延长任务租约,Renew 不代替会话心跳。
|
||||
|
||||
排空使用 `Drain:true`。排空在同进程重连后保留,后续心跳也必须带 true;尝试清除会返回 `STATE_CONFLICT`。排空不禁止收集已发请求结果。
|
||||
|
||||
## 4. 当前授权与本地期限
|
||||
|
||||
```go
|
||||
assignment, err := conn.NextAssignment(ctx)
|
||||
if err != nil { return err }
|
||||
ref := assignment.Attempt()
|
||||
startID, err := orbit.NewWorkerMessageID()
|
||||
if err != nil { return err }
|
||||
started, err := conn.Start(ctx, startID, ref)
|
||||
if err != nil { return err }
|
||||
deadline, active := started.Lease.ExecutionDeadline()
|
||||
if !active { return errors.New("attempt has no current execution authority") }
|
||||
work, cancel := context.WithDeadline(ctx, deadline)
|
||||
defer cancel()
|
||||
// 将 work 与业务输入传给处理器,不传执行秘密。
|
||||
```
|
||||
|
||||
`ExecutionDeadline()` 只认可 `Active=true`、`State=RUNNING` 和仍未到期的本地期限。SDK 以服务端 `lease_until-server_time` 为窗口,扣除从调用开始起的全部耗时(含等待写入)及 250 毫秒安全余量,用本地单调时钟表示。数据库墙钟与客户端相差一天也不会额外获得一天授权。
|
||||
|
||||
只有 SDK 控制响应会设置内部本地期限;自行构造/JSON 解码的 WorkerLease 不会得到执行授权。旧 start 回执即使包含历史 RUNNING 和未来 lease_until,也不能越过当前 Lease 的失效判断。
|
||||
|
||||
此底层接口不会替调用方更新处理器上下文。长任务必须有独立的续租与到期取消机制,断线期间也要在最后确认的本地期限停止推进。新的 Resume/Start 回执不能复活一个已因租约到期而停止的处理器。Go 无法强杀不理会 context 的 goroutine,SDK 更不能撤回外部请求;业务幂等/执行代次隔离仍需在接入方落实。
|
||||
|
||||
## 5. 重报与结果分类
|
||||
|
||||
| 情况 | 正确处理 |
|
||||
| --- | --- |
|
||||
| Start 请求结果不明,业务尚未开始 | 保留 startID;重连后 Resume,再用原 startID 核对;核验当前授权后最多开始一次 |
|
||||
| 处理器已在当前进程运行,随后断线 | 不再次调用处理器;保留它的已确认租约期限,重连核对原尝试 |
|
||||
| Finish 请求结果不明 | 保留原 finishID、Outcome、Result、ErrorCode,重连核对后原样重报 |
|
||||
| 明确业务成功 | `WorkerSucceeded`,不带 ErrorCode |
|
||||
| 可确认的业务失败 | `WorkerFailed`,带稳定 ErrorCode |
|
||||
| 超时、失联或不能确认外部效果 | `WorkerUnknown`,带稳定 ErrorCode,进入核查 |
|
||||
| `Disposition=EVIDENCE_ONLY` | 内容已留作证据;不能当作任务成功,另查 GetTask 的权威状态 |
|
||||
|
||||
Result 是不超过 256 KiB 的非 null JSON,可传对象引用;原始异常不应写入稳定错误分类。SDK 拒绝非法 Unicode、重复键和过深 JSON,保留数字文本;数值范围仍由服务端最终校验。
|
||||
|
||||
## 6. 错误与有界行为
|
||||
|
||||
- 握手 HTTP 拒绝返回 `*HTTPError`;业务控制拒绝返回 `*WorkerError`,通过 Code 分支处理。Error() 只显示分类,避免未知错误正文进入日志。
|
||||
- 传输中断返回 `ErrWorkerDisconnected`;消息格式/版本不兼容返回 `ErrWorkerProtocol`;主动关闭为 `ErrWorkerClosed`;超时/取消支持标准 context 错误。
|
||||
- 最多 32 个在途控制请求,达到上限返回 `ErrWorkerBusy`,请求未发送。同一消息 ID 已在途时也拒绝第二个并发等待者。
|
||||
- 派发缓冲最多 8 条;读取不及时会以 `ErrWorkerBackpressure` 关闭连接。持久化预占由服务端恢复,不无限积压内存。
|
||||
- 控制操作最长 10 秒,包含排队、发送与等待 ACK;调用方 context 可以缩短。已发送后取消/超时会关闭连接,操作是否提交需用原身份核对。
|
||||
- `NextAssignment` 的 context 取消只停止等待,不关闭连接。已关闭连接不会继续交付缓冲中的派发。
|
||||
- 入站单帧最多 512 KiB;读空闲期限 60 秒。需要调用方持续心跳,不能用此期限代替默认 45 秒会话期限。
|
||||
|
||||
以上是实现上限与正确性保护,不是容量承诺。测试命令与真实覆盖见 [P2 SDK 协议回归](../reports/phase-2-sdk-protocol.md)。
|
||||
Reference in New Issue
Block a user