feat: deliver authenticated task APIs, SDK and P1 regression
This commit is contained in:
@@ -26,7 +26,7 @@
|
||||
| 状态 | Go 类型常量 + SQL `CHECK`;状态版本独立于时间戳 |
|
||||
| CAS | `revision` 从 1 开始;服务层必须带期望版本条件更新并检查受影响行数 |
|
||||
| 暂停 | 实例执行状态与 `paused` 分开,控制版本与通用门控同事务协调 |
|
||||
| 参数 | 版本化 JSON 文档或业务侧引用;平台不内置行业字段 |
|
||||
| 参数 | 版本化 JSON 文档或业务侧引用;业务内容使用 MEDIUMTEXT + JSON_VALID 保留数字精度,平台元数据使用原生 JSON |
|
||||
| 删除 | 关联数据默认 `RESTRICT`,没有级联删除执行历史 |
|
||||
| 不可变历史 | 流程版本、计划版本、状态事件、审计事件的 `UPDATE` 被数据库触发器拒绝 |
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
|
||||
## 5. 仍需服务层事务保证的条件
|
||||
|
||||
外键与 `CHECK` 无法代替执行引擎。以下属于后续服务实现与回归目标:
|
||||
外键与 `CHECK` 无法代替执行引擎。P1 已完成 HTTP 动作/队列授权、幂等摘要与原回执、受理事件,以及待执行取消的 CAS/审计事务。执行相关的以下条件继续分阶段实现:
|
||||
|
||||
1. 权限验证、凭据校验、命名空间过滤和队列消费授权。
|
||||
2. 同一次事务更新任务、尝试、租约、并发许可、事件与流程交付记录。
|
||||
@@ -94,7 +94,7 @@
|
||||
6. 查询轮次、预算、下一任务创建同事务提交;未知结果按证据核查。
|
||||
7. 不可变版本发布前的流程图校验、表达式类型与结构化汇合验证。
|
||||
|
||||
当前模型方法只校验局部状态或预算,不能被当作已经实现了执行授权和业务幂等。
|
||||
局部模型方法不能被当作已经实现了 Worker 执行授权和业务效果幂等。P1 已实现范围与剩余边界见 [P1 报告](reports/phase-1.md)。
|
||||
|
||||
## 6. 迁移与回归
|
||||
|
||||
@@ -102,4 +102,6 @@
|
||||
|
||||
已应用的迁移不得修改。后续使用新的前向迁移;回归环境使用独立临时数据库。初始迁移尚未在生产部署。
|
||||
|
||||
000002_task_api 增加任务分页索引,将业务参数、结果、回执、流程定义/输入/输出等字段改为校验过的 JSON 文本,避免原生 JSON 数字重编码。公共 Go JSON 扫描类型保持兼容,原模型职责不变。响应 DTO 与持久化模型分开;SQL 空结果先扫描到可空字节切片再转换,避免驱动与 json.RawMessage 的可空类型不兼容。
|
||||
|
||||
命令与验证记录见 [开发计划](08-development-plan.md) 和 [基础阶段验证报告](reports/phase-0.md)。
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
| 阶段 | 开发内容 | 回归与完成标准 | 当前状态 |
|
||||
| --- | --- | --- | --- |
|
||||
| P0 基础与数据模型 | Go workspace、独立 SDK module、公共/Pulse/Weave 模型、MySQL 迁移、配置、健康检查 | 编译/竞态/静态检查;真实 MySQL 建表、隔离、唯一性、预算、不可变版本、迁移失败防护;SDK 健康调用 | 已完成并通过阶段回归(见 P0 报告) |
|
||||
| P1 任务受理闭环 | 应用凭据与作用域权限、队列、幂等提交、查询、待执行取消、受理事件;SDK 客户端 | API/SDK 创建查询闭环;重复键与内容冲突、响应丢失后重报、跨命名空间拒绝、参数边界 | 待开发 |
|
||||
| P1 任务受理闭环 | 应用凭据与作用域权限、队列、幂等提交、查询、待执行取消、受理事件;SDK 客户端 | API/SDK 创建查询闭环;重复键与内容冲突、响应未确认重报、跨命名空间拒绝、参数边界 | 已完成并通过阶段回归(见 P1 报告;真实断路/提交 ACK 丢失注入留后续故障阶段) |
|
||||
| P2 Worker 执行闭环 | WSS 接入、能力/容量、领取与开始、租约、续租、结果确认、排空与恢复;Worker SDK | 真 Worker 执行;失联/重连/重复确认/旧尝试拒绝;业务效果未知转核查;节点故障接管 | 待开发 |
|
||||
| P3 Pulse 完整能力 | 安全重试、延时、Cron/固定间隔、漏跑策略、计划版本、并发许可、配额/背压、可靠结果订阅 | 多实例领取/触发竞争、重试上限、取消竞争、队列隔离、积压恢复、事件重复交付 | 待开发 |
|
||||
| P4 Weave 主流程 | SDK 定义构建与发布校验、实例、顺序/分支/结构化并行汇合、信号/定时等待、版本绑定 | 重启接续、早到/重复信号、并行竞争、内部事件重放、发布版本兼容;端到端通用流程 | 待开发 |
|
||||
@@ -72,3 +72,4 @@ SDK、文档与示例随 P1–P5 同步开发,P7 是全量核对,不是最
|
||||
- [通用场景示例](examples/README.md)
|
||||
- [生产验收总清单](05-production-acceptance.md)
|
||||
- [P0 验证记录](reports/phase-0.md)
|
||||
- [P1 验证记录](reports/phase-1.md)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
- 文档版本:0.2
|
||||
- 整理日期:2026-09-17
|
||||
- 阶段:基础骨架与数据模型已实现,平台完整功能按持续计划开发;尚未完成生产验收
|
||||
- 阶段:P0 模型基础与 P1 任务受理/SDK 已实现,平台完整功能按持续计划开发;尚未完成生产验收
|
||||
- 适用范围:Orbit 统一平台,包含 Pulse 任务调度模块、Weave 流程编排模块与公共能力。平台面向多个业务系统复用。
|
||||
|
||||
## 阅读顺序
|
||||
@@ -79,4 +79,4 @@ Orbit 不内置特定行业规则;Pulse 管理执行,Weave 管理步骤依
|
||||
|
||||
2026-09-17,文档更新至 0.2:用户确认研发定义发布流程及 Weave 首版功能,明确纳入有界重复查询和暂停/继续等生产管理能力。技术细则与参数继续按建议或待定标注,未将功能确认等同于实现或验收通过。
|
||||
|
||||
持续开发目标已建立。当前实现和验收进度以 [开发计划](08-development-plan.md) 与 [验证报告](reports/phase-0.md) 为准;早期设计稿中的“未实现”描述保留其编写阶段语境。
|
||||
持续开发目标已建立。当前实现和验收进度以 [开发计划](08-development-plan.md)、[P0 报告](reports/phase-0.md)、[P1 报告](reports/phase-1.md) 为准;早期设计稿中的“未实现”描述保留其编写阶段语境。
|
||||
|
||||
@@ -8,17 +8,19 @@
|
||||
| --- | --- | --- |
|
||||
| `GET /health/live` | 已实现 | [健康检查](health.md) |
|
||||
| `GET /health/ready` | 已实现,仅验证数据库与迁移记录 | [健康检查](health.md) |
|
||||
| `/v1/tasks` 与任务管理 | 计划 P1–P3,尚未实现 | [任务接口规划](tasks.md) |
|
||||
| `/v1/tasks` 提交、查询、分页与待执行取消 | P1 已实现 | [任务接口](tasks.md) |
|
||||
| `/v1/queues` 创建与查询 | P1 已实现 | [队列接口](queues.md) |
|
||||
| 凭据校验与初始化 CLI | P1 已实现 | [鉴权](authentication.md) |
|
||||
| `/v1/worker/connect` | 计划 P2,尚未实现 | [协议草案](../03-http-websocket-protocol.md) |
|
||||
| `/v1/schedules` 与计划管理 | 计划 P3,尚未实现 | [协议草案](../03-http-websocket-protocol.md) |
|
||||
| `/v1/events/connect` | 计划 P3,尚未实现 | [协议草案](../03-http-websocket-protocol.md) |
|
||||
| `/v1/workflows` 与流程管理 | 计划 P4–P5,尚未实现 | [流程接口规划](workflows.md) |
|
||||
|
||||
当前服务对未实现路由返回 404。健康检查就绪不表示任务调度、鉴权或流程引擎已经可用。
|
||||
未实现路由返回 404。健康检查就绪不表示任务执行、定时调度或流程引擎已经可用。
|
||||
|
||||
## 业务接口统一要求
|
||||
|
||||
下述业务契约尚在实现阶段细化,不能用于声称当前已有业务 API:
|
||||
P1 业务接口已遵守下述约定,后续接口继续沿用:
|
||||
|
||||
- 生产使用 HTTPS/WSS,凭据通过授权头或受控握手传递,不放入 URL。
|
||||
- 应用身份、命名空间和操作权限分别校验;知道资源 ID 不等于拥有权限。
|
||||
@@ -27,7 +29,7 @@
|
||||
- 时间为 UTC RFC 3339,时长字段带单位;查询和批量操作有上限。
|
||||
- 错误码、字段、分页游标和限制值在对应阶段实现及回归后冻结。
|
||||
|
||||
健康接口目前直接返回状态对象。业务接口计划使用 `request_id` + `data` / `error` 信封,详见 [通信协议](../03-http-websocket-protocol.md)。
|
||||
健康接口直接返回状态对象。已实现的业务接口使用 `request_id` + `data` / `error` 信封;当前实际字段以本目录手册为准,其他尚未实现的接口见 [通信协议草案](../03-http-websocket-protocol.md)。
|
||||
|
||||
## 每个正式接口的文档模板
|
||||
|
||||
|
||||
53
docs/api/authentication.md
Normal file
53
docs/api/authentication.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# 凭据、权限与初始化
|
||||
|
||||
状态:P1 已实现。业务接口每次在数据库事务内校验凭据摘要、撤销/到期、应用与命名空间启停,以及动作和队列范围。授权与写入使用同一事务;管理变更与已经获得授权锁的请求按事务先后次序生效。
|
||||
|
||||
## 初始化一个新的接入应用
|
||||
|
||||
前置:专用 MySQL 数据库已经执行 orbit-migrate up,使用持有初始化权限的数据库管理连接。此命令创建新应用、命名空间、队列和凭据,不会覆盖现有同名应用。
|
||||
|
||||
```sh
|
||||
mkdir -p .local
|
||||
chmod 700 .local
|
||||
go run ./cmd/orbit-admin bootstrap \
|
||||
--application sample-app \
|
||||
--namespace default \
|
||||
--environment development \
|
||||
--queue files \
|
||||
--output .local/development.credentials.json
|
||||
```
|
||||
|
||||
ORBIT_MYSQL_DSN 通过环境注入,命令不读取 .env。所有名称必填,以字母/数字开头,后续允许字母、数字、`_ . : -`;environment 最长 32,其余最长 128。输出文件必须不存在,以 0600 创建;原始凭据不会打印到 stdout/stderr。`.local/` 和 `*.credentials.json` 已被 Git 忽略。
|
||||
|
||||
输出 JSON 包含 application_id / namespace_id / queue_id / credential_id / token / expires_at。初始凭据有效期为 30 天,权限包括当前命名空间内的五个 P1 动作和全部队列。初始队列 max_concurrency=4、rate_per_second=10;这是开发初始配置,执行限流随 P2–P3 落地。
|
||||
|
||||
资源、凭据摘要和初始化审计在一个事务中提交。交付文件先写入并同步到磁盘,成功后再提交事务。如果文件写入失败则回滚并移除文件;如果已经交付后提交无法确认,保留文件并报错,应使用其中凭据核对结果,不能直接覆盖或重复创建。
|
||||
|
||||
初始文件包含真实秘密,应保管在受限目录或导入秘密管理系统。运行账户与迁移/初始化账户分开;生产只通过 HTTPS 使用凭据。凭据管理 HTTP API、轮换与细粒度运维命令在后续阶段实现,当前 bootstrap 主要用于完成独立接入与开发验证。
|
||||
|
||||
## 凭据格式与作用域
|
||||
|
||||
```text
|
||||
orb1.<namespace_id>.<credential_id>.<32-byte-base64url-secret>
|
||||
```
|
||||
|
||||
服务端仅保存 SHA-256 秘密摘要。ID 不是授权证明,秘密不进入 URL。客户端请求:
|
||||
|
||||
```text
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
权限存储格式如下,当前由受控初始化及管理侧写入,不能通过普通任务请求修改:
|
||||
|
||||
```json
|
||||
{
|
||||
"actions":["tasks:submit","tasks:read","tasks:cancel","queues:read","queues:manage"],
|
||||
"queues":["*"]
|
||||
}
|
||||
```
|
||||
|
||||
actions 不支持通配符;queues 可列出队列 ID,星号仅表示当前命名空间内全部队列。创建队列必须具有 queues:manage 和全部队列范围。请求不接受自定义 namespace_id 来跨越隔离边界。
|
||||
|
||||
原始秘密错误、凭据撤销/过期、应用或命名空间停用统一返回 401。合法身份缺少动作权限返回 403。读取不在范围内的单个资源返回 404,避免披露资源内容。
|
||||
|
||||
SDK 使用 `orbit.Options{Token: token}`。健康查询不发送凭据。当前不启用业务权限缓存,撤销校验不依赖缓存过期。
|
||||
@@ -42,4 +42,4 @@ curl -i http://127.0.0.1:8080/health/ready
|
||||
|
||||
对应 `Client.Liveness(ctx)` 和 `Client.Readiness(ctx)`,见 [SDK 接入](../sdk/README.md)。HTTP 503 返回 `*orbit.HTTPError`。
|
||||
|
||||
此阶段的 ready 只表示数据库与迁移基础可用;尚无任务、Worker、流程或业务鉴权服务。SDK 默认请求超时为 10 秒,调用方可通过 context 设置更短期限。
|
||||
ready 只表示数据库与迁移基础可用;不检查 Worker、任务积压、流程执行或业务效果。P1 启动时先校验迁移,缺失或 dirty 会拒绝启动;运行后数据库不可用时 ready 返回 503。SDK 默认请求超时为 10 秒,调用方可通过 context 设置更短期限。
|
||||
|
||||
51
docs/api/queues.md
Normal file
51
docs/api/queues.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# 队列接口 v1
|
||||
|
||||
状态:P1 已实现创建与查询。更新、暂停、实际派发并发与速率控制随 P2–P3 实现;当前参数是后续执行所需的持久化配置。
|
||||
|
||||
## POST /v1/queues
|
||||
|
||||
需要 queues:manage 和当前命名空间内全部队列范围。鉴权、请求体、幂等键及错误信封与 [任务接口](tasks.md) 一致。
|
||||
|
||||
| 字段 | 类型 | 要求 |
|
||||
| --- | --- | --- |
|
||||
| name | string | 1–128 字符,以 ASCII 字母/数字开头,其后允许字母、数字、`_ . : -`;命名空间内唯一 |
|
||||
| max_concurrency | uint32 | 必填,1–100000 |
|
||||
| rate_per_second | uint32 | 必填,1–1000000 |
|
||||
|
||||
```sh
|
||||
curl "$ORBIT_URL/v1/queues" \
|
||||
-H "Authorization: Bearer $ORBIT_TOKEN" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Idempotency-Key: queue-images-v1' \
|
||||
--data '{"name":"images","max_concurrency":8,"rate_per_second":100}'
|
||||
```
|
||||
|
||||
首次 201:
|
||||
|
||||
```json
|
||||
{
|
||||
"request_id":"44444444444444444444444444444444",
|
||||
"data":{
|
||||
"deduplicated":false,
|
||||
"queue":{
|
||||
"id":"11111111111111111111111111111111",
|
||||
"namespace_id":"33333333333333333333333333333333",
|
||||
"name":"images","paused":false,"max_concurrency":8,"rate_per_second":100,"revision":"1"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
同键同内容返回 200、deduplicated=true。同键不同内容返回 409 IDEMPOTENCY_CONFLICT;换键创建同名队列返回 409 STATE_CONFLICT。创建、幂等记录和管理审计同事务提交。
|
||||
|
||||
SDK:`Client.CreateQueue(ctx, key, orbit.CreateQueueRequest{...})`。
|
||||
|
||||
## GET /v1/queues/{queue_id}
|
||||
|
||||
权限:queues:read 和对应队列范围。200 的 data 直接为上方 queue 对象;资源不存在或单资源范围不匹配返回 404。
|
||||
|
||||
```sh
|
||||
curl "$ORBIT_URL/v1/queues/$ORBIT_QUEUE_ID" -H "Authorization: Bearer $ORBIT_TOKEN"
|
||||
```
|
||||
|
||||
SDK:`Client.GetQueue(ctx, queueID)`。范围限制、重复创建和同名冲突已纳入 [P1 回归](../reports/phase-1.md)。这些配置上限不是生产容量承诺。
|
||||
@@ -1,16 +1,187 @@
|
||||
# 任务接口规划
|
||||
# 任务接口 v1
|
||||
|
||||
状态:计划 P1–P3,尚未实现。以下为后续落地清单;实际字段与可运行请求将在相应阶段补齐。
|
||||
状态:P1 已实现并通过真实 MySQL 与 SDK 回归。当前提供受理、查询、分页和待执行取消;Worker 执行与自动重试在 P2–P3 实现。
|
||||
|
||||
| 操作 | 候选接口 | 关键行为 |
|
||||
| --- | --- | --- |
|
||||
| 提交 | `POST /v1/tasks` | 携带稳定 `Idempotency-Key`,受理提交完成后响应 |
|
||||
| 批量提交 | `POST /v1/tasks:batchSubmit` | 每项独立幂等与结果;顶层成功不代表全部成功 |
|
||||
| 查询 | `GET /v1/tasks/{task_id}` | 校验命名空间和权限,返回当前状态与结果 |
|
||||
| 执行历史 | `GET /v1/tasks/{task_id}/attempts` | 分页返回历史尝试,不展示执行秘密凭据 |
|
||||
| 取消 | `POST /v1/tasks/{task_id}:cancel` | 待执行时取消生效;在途工作先记录取消意图 |
|
||||
| 人工重试 | `POST /v1/tasks/{task_id}:retry` | 带原因与权限;流程关联任务通过 Weave 恢复 |
|
||||
## 公共约定
|
||||
|
||||
提交契约需要队列、处理器/参数版本、业务输入或引用、执行时间、时限、恢复安全等级和重试策略。业务参数内容由接入方解释。
|
||||
业务接口需要 `Authorization: Bearer <token>`;写入需要 `Content-Type: application/json` 和稳定的 `Idempotency-Key`。凭据决定命名空间,请求体不能覆盖它。详见 [鉴权与初始化](authentication.md)。
|
||||
|
||||
P1 回归完成前,此页不提供看似可调用的 SDK 方法或 HTTP 请求体。接口实现后同步增加完整请求/响应、错误码及文件转换场景。
|
||||
请求体上限 512 KiB。拒绝未知字段、大小写别名、重复 JSON 键、无效 UTF-8、孤立 Unicode 代理项和超过 32 层的嵌套。除可空时间外,字段不能显式传 null。请求追踪 ID 由服务端生成,与幂等键分开。
|
||||
|
||||
响应使用 `{"request_id":"…","data":…}`;X-Request-ID 与正文一致。revision 是十进制字符串;ID 是 32 位小写十六进制字符串。时间使用 RFC 3339,返回 UTC,最多微秒精度。
|
||||
|
||||
## POST /v1/tasks
|
||||
|
||||
权限:tasks:submit,并有目标队列的访问范围。首次提交返回 201,同键相同内容返回 200。两者均只表示**数据库已受理**,不表示业务处理完成。
|
||||
|
||||
| 字段 | 类型 | 必填 / 默认 | 含义与限制 |
|
||||
| --- | --- | --- | --- |
|
||||
| queue_id | string | 必填 | 同一命名空间内的队列 ID |
|
||||
| handler | string | 必填 | 处理器名称,1–128 字符 |
|
||||
| handler_version | string | 必填 | 固定处理器版本,1–64 字符 |
|
||||
| payload_version | string | 必填 | 输入契约版本,1–32 字符 |
|
||||
| payload | JSON | 必填 | 非 null JSON,最大 256 KiB;平台不解释业务字段 |
|
||||
| business_key | string | 可选 | 最多 191 个 Unicode 字符,无 NUL/换行;用于关联,不提供业务幂等 |
|
||||
| available_at | time / null | 受理时数据库时间 | 最早可执行时间;必须早于总截止时间,仅允许最多 1 秒的过去时间容差 |
|
||||
| start_deadline_at | time / null | 无独立限制 | 必须晚于当前时间,不早于 available_at,不晚于总截止时间 |
|
||||
| task_timeout_ms | uint64 | 0 或省略为 86400000 | 从受理时计算的总时限,最大 30 天(2592000000 毫秒) |
|
||||
| recovery_safety | string | RECONCILE_ONLY | 也可为 IDEMPOTENT;必须基于处理器真实的幂等能力声明 |
|
||||
| retry | object | 见下表 | 受理时冻结的执行策略;当前阶段仅保存 |
|
||||
|
||||
处理器及版本名称以 ASCII 字母或数字开头,后续只能包含字母、数字、`_ . : -`。时间年份为 2000–9998。
|
||||
|
||||
| retry 字段 | 默认与限制 |
|
||||
| --- | --- |
|
||||
| max_attempts | 0 或省略为 1;范围 1–100,包含首次尝试 |
|
||||
| attempt_timeout_ms | 0 或省略为 30000;必须不超过任务总时限 |
|
||||
| initial_delay_ms | 多次尝试时 0 或省略为 1000;必须为正且不超过 max_delay_ms;单次尝试默认 0 |
|
||||
| max_delay_ms | 多次尝试时 0 或省略为 30000;单次尝试默认 0;最大 9223372036854,整体仍受总截止时间限制 |
|
||||
|
||||
这些值是当前接口保护边界,不代表已经验证相应吞吐或并发容量。
|
||||
|
||||
业务 JSON 以经过校验的文本持久化,保留大整数和小数的精确数字内容。不要在接入方先转成 float64;Go 使用 json.RawMessage、结构体中的精确类型或业务约定的字符串。单个数字最长 256 字符,显式指数和去除尾零后的指数均需在 -308 至 308 内,数值不能超出有限 double 的幅度;这只是可接受范围检查,摘要不使用浮点近似值。
|
||||
|
||||
请求示例,队列 ID 替换为初始化结果:
|
||||
|
||||
```sh
|
||||
curl -i "$ORBIT_URL/v1/tasks" \
|
||||
-H "Authorization: Bearer $ORBIT_TOKEN" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Idempotency-Key: conversion-operation-001' \
|
||||
--data '{
|
||||
"queue_id":"11111111111111111111111111111111",
|
||||
"handler":"file.convert",
|
||||
"handler_version":"v1",
|
||||
"payload_version":"v1",
|
||||
"payload":{"source_ref":"objects/input.txt","format":"pdf","sequence":9007199254740993},
|
||||
"business_key":"conversion-001"
|
||||
}'
|
||||
```
|
||||
|
||||
首次受理的完整响应示例,ID 和时间为示意值:
|
||||
|
||||
```json
|
||||
{
|
||||
"request_id":"44444444444444444444444444444444",
|
||||
"data":{
|
||||
"deduplicated":false,
|
||||
"task":{
|
||||
"id":"22222222222222222222222222222222",
|
||||
"namespace_id":"33333333333333333333333333333333",
|
||||
"queue_id":"11111111111111111111111111111111",
|
||||
"state":"WAITING",
|
||||
"revision":"1",
|
||||
"handler":"file.convert",
|
||||
"handler_version":"v1",
|
||||
"payload_version":"v1",
|
||||
"payload":{"source_ref":"objects/input.txt","format":"pdf","sequence":9007199254740993},
|
||||
"business_key":"conversion-001",
|
||||
"available_at":"2026-09-17T00:00:00Z",
|
||||
"deadline_at":"2026-09-18T00:00:00Z",
|
||||
"recovery_safety":"RECONCILE_ONLY",
|
||||
"retry":{"max_attempts":1,"initial_delay_ms":0,"max_delay_ms":0,"attempt_timeout_ms":30000},
|
||||
"attempt_count":0,
|
||||
"created_at":"2026-09-17T00:00:00Z",
|
||||
"updated_at":"2026-09-17T00:00:00Z"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
可选响应字段:start_deadline_at、result、cancel_requested_at、completed_at、business_key,未设置时省略。终态有 completed_at。状态集合为 WAITING / LEASED / RUNNING / NEEDS_REVIEW / SUCCEEDED / FAILED / CANCELLED;P1 仅主动产生 WAITING 和 CANCELLED。
|
||||
|
||||
### 幂等与失败处理
|
||||
|
||||
- 键为 1–128 个可打印 ASCII 字符,不含空格;作用域为命名空间 + 操作类型,取消额外包含任务 ID。不同凭据在同一命名空间共享该身份,重复请求仍需通过当前权限校验。
|
||||
- 固定默认值、规范化 UTC 时间、排序 JSON 对象键、精确规范化十进制数字,再计算版本化 SHA-256 摘要。1 与 1.0 等价;数组顺序有意义。内部算法名 orbit-json-v1,不宣称采用 RFC 8785。
|
||||
- 同键不同内容返回 409 IDEMPOTENCY_CONFLICT;不同键即使 business_key 相同,也可以产生两个任务。
|
||||
- 同一事务保存任务、受理事件、提交者审计、幂等身份与原始回执;验证或写入失败整体回滚。提交审计记录凭据与处理器/队列,不复制业务参数。
|
||||
- 同键重报返回**首次操作的回执快照**;任务之后取消也不会改写该回执。获取最新状态调用 GET。
|
||||
- 网络中断、客户端超时或 503 时,不能认定提交未发生;保持原键和原内容查询或重报。SDK 不自动换键或自动重试写操作。
|
||||
- 幂等记录设置 90 天保留截止时间;当前尚无清理任务,存在的记录持续生效。后续清理不得缩短已承诺窗口。
|
||||
|
||||
SDK:`Client.SubmitTask(ctx, key, request)`。
|
||||
|
||||
## GET /v1/tasks/{task_id}
|
||||
|
||||
权限:tasks:read 和任务所在队列范围。200 的 data 直接为上方 task 对象,返回当前状态和完整参数/已保存结果。不存在、跨命名空间或不在该凭据队列范围时返回 404。
|
||||
|
||||
```sh
|
||||
curl "$ORBIT_URL/v1/tasks/$TASK_ID" -H "Authorization: Bearer $ORBIT_TOKEN"
|
||||
```
|
||||
|
||||
SDK:`Client.GetTask(ctx, taskID)`。
|
||||
|
||||
## GET /v1/tasks
|
||||
|
||||
权限:tasks:read。查询参数均只能出现一次:
|
||||
|
||||
| 参数 | 要求 |
|
||||
| --- | --- |
|
||||
| queue_id | 必填,有权限的队列 ID |
|
||||
| state | 可选,取上述状态之一 |
|
||||
| limit | 可选,默认 20;1–100 |
|
||||
| cursor | 可选,上一页返回值;必须保持 queue_id/state 不变,最长 1024 字符 |
|
||||
|
||||
按 (created_at DESC, id DESC) 游标分页,不使用大 offset。不承诺跨页快照:读取过程中状态可能变化。列表省略 payload/result/retry 等大字段,返回摘要。
|
||||
|
||||
```sh
|
||||
curl "$ORBIT_URL/v1/tasks?queue_id=$ORBIT_QUEUE_ID&state=WAITING&limit=20" \
|
||||
-H "Authorization: Bearer $ORBIT_TOKEN"
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"request_id":"44444444444444444444444444444444",
|
||||
"data":{
|
||||
"items":[{
|
||||
"id":"22222222222222222222222222222222",
|
||||
"queue_id":"11111111111111111111111111111111",
|
||||
"state":"WAITING","revision":"1",
|
||||
"handler":"file.convert","handler_version":"v1","business_key":"conversion-001",
|
||||
"available_at":"2026-09-17T00:00:00Z","deadline_at":"2026-09-18T00:00:00Z",
|
||||
"attempt_count":0,"created_at":"2026-09-17T00:00:00Z","updated_at":"2026-09-17T00:00:00Z"
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
还有下一页时返回 data.next_cursor。空结果为 items: []。SDK:`Client.ListTasks(ctx, request)`。
|
||||
|
||||
## POST /v1/tasks/{task_id}:cancel
|
||||
|
||||
权限:tasks:cancel 和队列范围。当前只允许取消 WAITING 状态且不归属流程的任务。LEASED/RUNNING 或流程任务暂时返回 409,后续由执行与流程控制实现安全取消。
|
||||
|
||||
```sh
|
||||
curl "$ORBIT_URL/v1/tasks/$TASK_ID:cancel" \
|
||||
-H "Authorization: Bearer $ORBIT_TOKEN" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Idempotency-Key: conversion-operation-001-cancel' \
|
||||
--data '{"expected_revision":"1","reason":"source object was replaced"}'
|
||||
```
|
||||
|
||||
expected_revision 必填,为非零 uint64 的十进制字符串;reason 必填且不能全为空白,最多 1024 个 Unicode 字符。服务端以版本和状态条件更新,只有一个竞争请求能成功。
|
||||
|
||||
200 的 data 为 `{"task":<完整最新任务>,"deduplicated":false}`。示例任务会变为 state=CANCELLED、revision="2",写入 cancel_requested_at/completed_at,并同事务追加取消事件及审计。首次取消之后使用相同键、原因和**原 expected_revision**重报,返回原取消回执且 deduplicated=true。换键重报已取消任务返回 409。
|
||||
|
||||
SDK:`Client.CancelTask(ctx, taskID, key, request)`。此操作不承诺回滚任何已发生的外部业务效果。
|
||||
|
||||
## 错误与回归
|
||||
|
||||
| HTTP / code | 处理 |
|
||||
| --- | --- |
|
||||
| 400 INVALID_ARGUMENT | 修正字段、时间、游标或幂等键 |
|
||||
| 401 UNAUTHENTICATED | 检查凭据、到期/撤销和应用/命名空间状态 |
|
||||
| 403 PERMISSION_DENIED | 检查动作或提交/列表所需队列范围 |
|
||||
| 404 NOT_FOUND | 资源不存在或单资源读取范围不匹配 |
|
||||
| 409 IDEMPOTENCY_CONFLICT | 原键已对应其他内容,不应盲目换键重试 |
|
||||
| 409 STATE_CONFLICT | 当前状态或版本不允许操作,先查询 |
|
||||
| 413 BODY_TOO_LARGE | 减小请求或改为传递业务对象引用 |
|
||||
| 415 UNSUPPORTED_MEDIA_TYPE | 使用 application/json |
|
||||
| 503 UNAVAILABLE | 结果可能未知;保留原幂等身份,有限退避后核对 |
|
||||
|
||||
```json
|
||||
{"request_id":"44444444444444444444444444444444","error":{"code":"IDEMPOTENCY_CONFLICT","message":"idempotency key was used with different content"}}
|
||||
```
|
||||
|
||||
批量受理、执行历史、人工重试和运行中取消尚未实现。完整可运行程序见 [SDK 任务示例](../../sdk/go/examples/tasks/main.go),已验证异常场景见 [P1 回归报告](../reports/phase-1.md)。SDK 忽略未知响应字段;更改已有字段语义需升级契约和回归。
|
||||
|
||||
@@ -10,11 +10,20 @@
|
||||
- 异常:数据库不可用或迁移记录异常时 readiness 返回 HTTP 503,SDK 返回类型化状态错误。
|
||||
- 清理:只读调用,无业务资源需要删除。
|
||||
|
||||
## 已可运行:文件转换任务的受理与取消
|
||||
|
||||
- 源码:[SDK 任务受理示例](../../sdk/go/examples/tasks/main.go)。
|
||||
- 前置:完成迁移、初始化凭据、启动服务,详见 [SDK 接入](../sdk/README.md)。
|
||||
- 输入:对象引用、格式与精确整数;提交两次同一身份,再查询、分页并带版本取消。
|
||||
- 预期:重复请求返回同一任务,最终 CANCELLED/revision=2。当前不启动 Worker,不实际生成文件。
|
||||
- 异常:凭据失效、权限不足、内容冲突、版本竞争和未知网络结果,见 [任务接口](../api/tasks.md)。
|
||||
- 清理:示例以取消结束;任务和审计历史保留。重复运行会生成独立示例任务。
|
||||
|
||||
## 计划场景与验收标准
|
||||
|
||||
| 场景 | 输入与步骤 | 预期结果 | 必测异常 | 状态 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 文件转换 | 对象引用 → 提交任务 → Worker 转换 → 结果引用 | 同一操作获得一次业务结果,历史可查 | 重复提交、Worker 在结果上报前中断 | P1–P2 待开发 |
|
||||
| 文件转换 | 对象引用 → 提交任务 → Worker 转换 → 结果引用 | 同一操作获得一次业务结果,历史可查 | 重复提交、Worker 在结果上报前中断 | P1 受理完成,P2 执行待开发 |
|
||||
| 定期同步 | 发布计划 → 周期触发 → 暂停 → 恢复 | 触发身份唯一,漏跑策略可追溯 | 多节点竞争、停机后补跑上限 | P3 待开发 |
|
||||
| 并行生成 | 输入对象 → 并行计算两份结果 → 汇合 | 两支满足条件后只创建一份后继工作 | 一支失败、重复结果、汇合竞争 | P4 待开发 |
|
||||
| 等待审核 | 校验 → 等待信号 → 发布结果 | 只接受授权、匹配当前操作的信号 | 早到、重复、过期与越权信号 | P4 待开发 |
|
||||
|
||||
65
docs/reports/phase-1.md
Normal file
65
docs/reports/phase-1.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# P1 任务受理与 SDK 回归记录
|
||||
|
||||
日期:2026-09-17。结论:任务受理阶段已实现并通过本地真实 MySQL 回归;执行引擎和生产高可用验收仍未完成。
|
||||
|
||||
## 实现范围
|
||||
|
||||
- 凭据摘要校验、有效期/撤销、应用与命名空间启停、动作和队列范围。
|
||||
- 受控 bootstrap 命令:创建应用、命名空间、初始队列与凭据,0600 新文件交付,初始化审计。
|
||||
- 队列创建/查询,任务提交/单条查询/游标分页/WAITING 普通任务取消。
|
||||
- 同一事务中的幂等预留、语义摘要、资源状态、持久化事件、管理审计和回执。
|
||||
- 独立 Go SDK 的对应方法、类型化错误、请求身份和精确 JSON 数据。
|
||||
- Markdown 接口字段、失败行为、SDK 接入、任务受理场景源码。
|
||||
|
||||
新增迁移 000002_task_api:业务 JSON 改为 MEDIUMTEXT + JSON_VALID,避免 MySQL 原生 JSON 对业务数字的重新编码;元数据仍使用原生 JSON。增加队列内任务创建时间及状态分页索引。初始迁移校验和保持不变。
|
||||
|
||||
## 环境与执行入口
|
||||
|
||||
本机 macOS / arm64,Go 1.27.1;Docker 隔离容器 MySQL 8.4.10,回环随机端口、随机密码、用后清理。没有连接已有业务数据库。
|
||||
|
||||
```sh
|
||||
make test
|
||||
make vet
|
||||
make build
|
||||
make integration
|
||||
go test ./internal/jsonvalue -fuzz FuzzCanonical -fuzztime=5s
|
||||
cd sdk/go
|
||||
GOWORK=off go test -race ./...
|
||||
GOWORK=off go vet ./...
|
||||
```
|
||||
|
||||
Go 未全局安装时,通过 make GO=/absolute/path/to/go 指定。集成脚本支持 GO、DOCKER、ORBIT_TEST_MYSQL_IMAGE。
|
||||
|
||||
## 实际验证
|
||||
|
||||
| 场景 | 结果 |
|
||||
| --- | --- |
|
||||
| 初始迁移 + 前向迁移,模型字段、隔离、预算、不可变历史、dirty/checksum 防护 | 通过 |
|
||||
| 16 个并发请求共用一个提交键 | 1 次创建、其余复用;同一任务,受理事件和提交审计各 1 条 |
|
||||
| 首次响应未被调用方确认后的原样重报 | 返回原任务与原回执;deduplicated=true |
|
||||
| 字段顺序、1 与 1.00 等价;同键不同内容 | 等价请求复用;不同内容 409 |
|
||||
| 9007199254740993、大整数和多位小数 | 提交、GET、缓存回执不损失数字精度 |
|
||||
| 错误秘密、过期、撤销、应用/命名空间禁用 | 拒绝 |
|
||||
| 跨命名空间、只读动作、队列范围 | 拒绝对应越权访问 |
|
||||
| 未知/重复/别名字段、非法 Unicode、超大 body、过期时间、分页上限 | 拒绝且不留下成功幂等预留 |
|
||||
| 游标分页 | 无重复项;不带业务 payload;更换过滤条件后游标无效 |
|
||||
| 两个不同取消键竞争同一版本 | 1 个成功、1 个 409;取消审计 1 条,终结事件 1 条 |
|
||||
| 同一取消键重复确认 | 原版本仍能取回原取消回执,不重复追加历史 |
|
||||
| 注入审计 INSERT 失败 | 503;任务仍 WAITING/revision=1;事件和预留整体回滚;HTTP 不泄露 SQL 错误 |
|
||||
| 初始化交付失败 | 应用、队列、凭据全部回滚 |
|
||||
| 已取消 context 提交 | 不提交 |
|
||||
| SDK 重定向、错误解析、精确 revision/JSON、写操作不静默重试 | 通过 |
|
||||
| 真实 CLI → 服务进程 → 独立 SDK 示例 | alive/ready;duplicate=true;最终 CANCELLED/revision=2 |
|
||||
| JSON 规范化模糊测试 | 一次约 20 万输入执行,未发现规范化不稳定;不等同于完整形式化证明 |
|
||||
|
||||
集成测试会主动制造一条 UNAVAILABLE 日志以验证审计失败回滚,该日志是预期结果。实际回归曾发现可空 SQL 结果直接扫描到 json.RawMessage 的兼容问题,已改为先扫描 []byte,再赋给响应 DTO,并由受理与查询测试覆盖。
|
||||
|
||||
## 尚未验证或未实现
|
||||
|
||||
- P1 没有 Worker、WebSocket、自动执行、延时扫描、重试扫描或定时计划;任务不会自行完成。
|
||||
- 取消仅覆盖 WAITING 且非流程所属任务;运行中取消、未知结果核查按 P2/P5 完成。
|
||||
- 队列并发/速率配置已保存,尚未启动执行限流;整体 API 配额与背压在后续阶段。
|
||||
- 凭据轮换/管理 API、数据清理、完整监控、备份恢复在后续阶段。
|
||||
- “响应未确认重报”当前验证为重复发送已经提交的请求;未注入真实网络断路或数据库提交 ACK 丢失。
|
||||
- 未运行生产拓扑、复制切换、跨故障域恢复或容量压测。测试耗时不作为吞吐/延迟指标。
|
||||
- SDK 尚未发布版本,代码保存在本地开发分支,当前报告不代表远端发布或生产上线。
|
||||
@@ -1,57 +1,127 @@
|
||||
# Go SDK 接入说明
|
||||
|
||||
当前已实现客户端创建、存活与就绪查询。任务提交、Worker 和流程构建接口按开发计划逐阶段实现。
|
||||
已实现健康查询、任务提交/查询/分页/待执行取消、队列创建/查询。Worker 和流程构建接口按 [开发计划](../08-development-plan.md) 继续实现。
|
||||
|
||||
SDK module:`git.yuntuo.hk/k2safe/orbit/sdk/go`。服务端与 SDK 在同一 Git 仓库,使用独立 `go.mod`;SDK 当前仅依赖 Go 标准库。
|
||||
module:`git.yuntuo.hk/k2safe/orbit/sdk/go`。SDK 使用独立 go.mod,当前仅依赖 Go 标准库,不引用服务端模型或数据库实现。
|
||||
|
||||
## 1. 本地运行当前示例
|
||||
## 1. 从初始化到运行示例
|
||||
|
||||
前置条件:Go 1.27.1、MySQL 8.4+,先按项目根目录 README 迁移数据库并启动服务。
|
||||
需要 Go 1.27.1、MySQL 8.4+。在仓库根目录,通过环境设置专用 ORBIT_MYSQL_DSN:
|
||||
|
||||
在仓库根目录执行:
|
||||
```sh
|
||||
go run ./cmd/orbit-migrate up
|
||||
mkdir -p .local
|
||||
chmod 700 .local
|
||||
go run ./cmd/orbit-admin bootstrap \
|
||||
--application sample-app --namespace default --environment development \
|
||||
--queue files --output .local/development.credentials.json
|
||||
go run ./cmd/orbit
|
||||
```
|
||||
|
||||
另开终端,从仓库根目录执行:
|
||||
|
||||
```sh
|
||||
cd sdk/go
|
||||
ORBIT_URL=http://127.0.0.1:8080 go run ./examples/health
|
||||
ORBIT_URL=http://127.0.0.1:8080 \
|
||||
ORBIT_CREDENTIALS_FILE=../../.local/development.credentials.json \
|
||||
go run ./examples/tasks
|
||||
```
|
||||
|
||||
期望输出:
|
||||
预期输出,task 为每次运行生成的实际 ID:
|
||||
|
||||
```text
|
||||
liveness=alive readiness=ready scope=database_and_schema
|
||||
task=<32位任务ID> duplicate=true listed=1 final_state=CANCELLED revision=2
|
||||
```
|
||||
|
||||
[完整示例源码](../../sdk/go/examples/health/main.go)。示例 context 最多等待 5 秒;数据库或迁移未就绪时返回错误并以非零状态退出。
|
||||
重复运行示例会新建一个独立任务并取消它,listed 数量可能增加,最多显示当前页 10 条。数据和审计保留,不执行硬删除。示例只演示受理闭环,尚不执行文件转换。
|
||||
|
||||
## 2. 当前真实调用方式
|
||||
- [健康示例源码](../../sdk/go/examples/health/main.go):只读,无业务资源写入。
|
||||
- [任务示例源码](../../sdk/go/examples/tasks/main.go):提交两次同一身份、获取当前状态、列表、带版本取消。
|
||||
- 任务示例也接受 ORBIT_TOKEN 和 ORBIT_QUEUE_ID,环境值优先于凭据文件。
|
||||
- 示例发生错误会打印错误并非零退出;打印内容不包含原始 token。
|
||||
- 初始凭据 30 天有效。初始化行为和错误核对方式见 [凭据文档](../api/authentication.md)。
|
||||
- `make integration` 会在一次性数据库中自动完成上面的真实服务与 SDK 示例验证。
|
||||
|
||||
## 2. 创建客户端与提交任务
|
||||
|
||||
下方是接入函数内的调用片段;完整 imports/main 见示例源码。
|
||||
|
||||
```go
|
||||
client, err := orbit.NewClient("http://127.0.0.1:8080", orbit.Options{})
|
||||
client, err := orbit.NewClient(baseURL, orbit.Options{Token: token})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
health, err := client.Readiness(ctx)
|
||||
// 应先把 key 与请求内容保存在业务数据库;网络重报必须复用。
|
||||
key := "file-conversion-operation-001"
|
||||
request := orbit.SubmitTaskRequest{
|
||||
QueueID: queueID,
|
||||
Handler: "file.convert",
|
||||
HandlerVersion: "v1",
|
||||
PayloadVersion: "v1",
|
||||
Payload: json.RawMessage(`{"source_ref":"objects/input.txt","format":"pdf"}`),
|
||||
RecoverySafety: orbit.RecoveryReconcileOnly,
|
||||
}
|
||||
accepted, err := client.SubmitTask(ctx, key, request)
|
||||
if err != nil {
|
||||
var responseErr *orbit.HTTPError
|
||||
if errors.As(err, &responseErr) {
|
||||
// responseErr.StatusCode 是实际 HTTP 状态,例如 503。
|
||||
return err
|
||||
}
|
||||
current, err := client.GetTask(ctx, accepted.Task.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(current.ID, current.State, current.Revision)
|
||||
```
|
||||
|
||||
受理回执不是业务执行结果。同键重报返回原始快照;当前状态应使用 GetTask。业务侧创建操作与平台提交之间存在双写边界,接入方应在自身事务中保存操作记录/Outbox,再使用稳定身份提交,不能依靠随机新键补发来“修复”未知结果。
|
||||
|
||||
## 3. 取消与错误处理
|
||||
|
||||
```go
|
||||
cancelled, err := client.CancelTask(ctx, current.ID, key+"-cancel", orbit.CancelTaskRequest{
|
||||
ExpectedRevision: current.Revision,
|
||||
Reason: "source object was replaced",
|
||||
})
|
||||
if err != nil {
|
||||
var apiErr *orbit.APIError
|
||||
if errors.As(err, &apiErr) {
|
||||
// apiErr.Code、StatusCode、RequestID 可用于分支与排查。
|
||||
// STATE_CONFLICT:先查询;UNAVAILABLE:保留原键和原请求核对。
|
||||
}
|
||||
return err
|
||||
}
|
||||
fmt.Println(health.Status, health.Scope)
|
||||
fmt.Println(cancelled.Task.State)
|
||||
```
|
||||
|
||||
片段需在调用函数中使用并导入标准库包和 `orbit`;完整可运行程序见上方源码。
|
||||
取消重报必须保留第一次取消时的 expected_revision,不能将响应中的新版本塞回同一幂等请求。当前只取消 WAITING 且不归属流程的任务。
|
||||
|
||||
`Options.HTTPClient` 可注入专用 HTTP 客户端。SDK 复制其配置,不修改调用方客户端;禁止自动跟随重定向,限制健康响应大小,不自动重试请求,不将服务端响应正文放进错误。
|
||||
业务错误返回 *orbit.APIError,支持 errors.As 转为 *orbit.HTTPError 查看状态。健康错误或无法识别的网关错误使用 *orbit.HTTPError,不带未知响应正文。网络/上下文错误按标准库错误返回;超时并不能证明服务端没有提交。
|
||||
|
||||
## 3. 外部项目的本地接入
|
||||
## 4. 方法与限制
|
||||
|
||||
仓库尚未发布 SDK 版本。开发期间可使用独立工作区或本地 replace,例如在接入项目中执行:
|
||||
| 方法 | 请求 / 返回 | 文档 |
|
||||
| --- | --- | --- |
|
||||
| Liveness / Readiness | Health | [健康](../api/health.md) |
|
||||
| SubmitTask | SubmitTaskRequest / SubmitTaskResult | [任务](../api/tasks.md) |
|
||||
| GetTask | taskID / Task | [任务](../api/tasks.md) |
|
||||
| ListTasks | ListTasksRequest / TaskPage | [任务](../api/tasks.md) |
|
||||
| CancelTask | taskID、key、CancelTaskRequest / CancelTaskResult | [任务](../api/tasks.md) |
|
||||
| CreateQueue | key、CreateQueueRequest / CreateQueueResult | [队列](../api/queues.md) |
|
||||
| GetQueue | queueID / Queue | [队列](../api/queues.md) |
|
||||
|
||||
所有方法第一个参数为 context.Context,返回值之外都返回 error。命令方法要求调用方提供稳定 key,不自动生成或重试。ListTasksRequest 接受 QueueID、State、Limit、Cursor。
|
||||
|
||||
Options.HTTPClient 可注入专用 HTTP 客户端。SDK 复制配置,不修改调用方实例;默认超时 10 秒,可用 context 缩短。禁止自动跟随重定向,避免凭据被转交其他地址。生产配置 HTTPS;SDK 不承担部署 TLS 终止。
|
||||
|
||||
健康响应最多 16 KiB,业务响应最多 1 MiB,请求最多 512 KiB。大业务内容应传对象引用。参数/result 使用 json.RawMessage,不转成 float64;revision 在 Go 中为 uint64,JSON 编码为字符串。服务端字段及上限见各接口手册。
|
||||
|
||||
## 5. 外部项目本地接入
|
||||
|
||||
SDK 尚未发布版本。开发期可以用本地 replace:
|
||||
|
||||
```sh
|
||||
go mod edit -require=git.yuntuo.hk/k2safe/orbit/sdk/go@v0.0.0
|
||||
@@ -59,14 +129,8 @@ go mod edit -replace=git.yuntuo.hk/k2safe/orbit/sdk/go=/absolute/path/to/orbit/s
|
||||
go mod tidy
|
||||
```
|
||||
|
||||
示例路径需替换为本机实际目录。不要将本机绝对路径 replace 提交为发布依赖。后续发布 SDK 时使用独立 module 标签与兼容说明,在真实仓库取包路径验证后给出 `go get` 命令;当前不提供不存在的发行版本。
|
||||
将示例路径换成真实路径,不要把本机绝对路径作为发布依赖提交。后续会验证独立 module 标签和真实远端取包,再提供 go get 发布命令。当前源码同时验证 GOWORK=off 的独立构建。
|
||||
|
||||
## 4. 后续 SDK 交付
|
||||
## 6. 后续交付
|
||||
|
||||
- P1:凭据配置、幂等提交、查询与待执行取消。
|
||||
- P2:处理器注册、Worker 容量、WSS、续租与结果确认、优雅退出。
|
||||
- P3:计划管理、可靠结果订阅与队列控制。
|
||||
- P4:流程定义、发布、启动、信号与查询。
|
||||
- P5:有界查询、暂停继续和人工恢复入口。
|
||||
|
||||
每阶段同步更新可运行场景、错误处理与兼容测试。业务幂等、外部结果核查与 Outbox 接入责任会与真实代码示例一起说明。
|
||||
P2 提供 Worker 注册、WSS、能力/容量、执行确认、续租和排空;P3 提供计划与结果订阅;P4–P5 提供流程构建发布、信号、等待、轮询与人工恢复。每项随实现同步交付可运行示例及异常回归。
|
||||
|
||||
Reference in New Issue
Block a user