Files
orbit/docs/sdk/README.md

10 KiB
Raw Blame History

Go SDK 接入说明

已实现健康查询、任务提交/查询/分页/待执行取消、队列创建/查询、自动 Worker、Worker 底层协议 SDK 和 执行历史查询。安全重试 已提供有限策略、WorkerFailure.Retryable、历史查询及完整例子。计划调度 已支持创建、查询、版本发布、暂停/恢复、触发历史与完整示例。流程构建等后续接口按 开发计划 继续实现。

module:git.yuntuo.hk/k2safe/orbit/sdk/go。SDK 使用独立 go.mod,依赖 Go 标准库与 github.com/coder/websocket v1.8.15,不引用服务端模型或数据库实现。

1. 从初始化到运行示例

需要 Go 1.27.1、MySQL 8.4+。在仓库根目录,通过环境设置专用 ORBIT_MYSQL_DSN:

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

另开终端,从仓库根目录执行:

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:

liveness=alive readiness=ready scope=database_and_schema
task=<32位任务ID> duplicate=true listed=1 final_state=CANCELLED revision=2

重复运行示例会新建一个独立任务并取消它,listed 数量可能增加,最多显示当前页 10 条。数据和审计保留,不执行硬删除。示例只演示受理闭环,尚不执行文件转换。

  • 健康示例源码:只读,无业务资源写入。
  • 任务示例源码:提交两次同一身份、获取当前状态、列表、带版本取消。
  • 任务示例也接受 ORBIT_TOKEN 和 ORBIT_QUEUE_ID,环境值优先于凭据文件。
  • 示例发生错误会打印错误并非零退出;打印内容不包含原始 token。
  • 初始凭据 30 天有效。初始化行为和错误核对方式见 凭据文档。
  • make integration 会在一次性数据库中自动完成上面的真实服务与 SDK 示例验证。

2. 创建客户端与提交任务

下方是接入函数内的调用片段;完整 imports/main 见示例源码。

client, err := orbit.NewClient(baseURL, orbit.Options{Token: token})
if err != nil {
    return err
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

// 应先把 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 {
    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. 取消与错误处理

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(cancelled.Task.State)

取消重报必须保留第一次取消时的 expected_revision,不能将响应中的新版本塞回同一幂等请求。已支持独立任务和计划任务的等待、预占、运行和核查状态;运行中受理返回 202,任务状态仍为 RUNNING,需另行查询最终状态。完整语义和运行示例见 取消契约。若此前存在未知效果,本次确认取消不能清除它。

业务错误返回 *orbit.APIError,支持 errors.As 转为 *orbit.HTTPError 查看状态。健康错误或无法识别的网关错误使用 *orbit.HTTPError,不带未知响应正文。网络/上下文错误按标准库错误返回;超时并不能证明服务端没有提交。

4. 方法与限制

方法 请求 / 返回 文档
CreateSchedule / GetSchedule / ListSchedules 计划受理、详情与队列分页 计划
PublishSchedule / GetScheduleVersion 不可变发布与历史版本 计划
PauseSchedule / ResumeSchedule / ListScheduleOccurrences 控制与触发记录 计划
Liveness / Readiness Health 健康
SubmitTask SubmitTaskRequest / SubmitTaskResult 任务
GetTask taskID / Task 任务
ListTasks ListTasksRequest / TaskPage 任务
CancelTask taskID、key、CancelTaskRequest / CancelTaskResult 任务
CreateQueue key、CreateQueueRequest / CreateQueueResult 队列
GetQueue queueID / Queue 队列
ListTaskAttempts taskID、HistoryPageRequest / AttemptPage 执行历史
GetTaskAttempt taskID、attemptID / Attempt 执行历史
ListAttemptEvidence taskID、attemptID、HistoryPageRequest / AttemptEvidencePage 执行历史
GetAttemptEvidence taskID、attemptID、evidenceID / AttemptEvidence 执行历史

所有方法第一个参数为 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:

go mod edit -require=git.yuntuo.hk/k2safe/orbit/sdk/go@v0.0.0
go mod edit -replace=git.yuntuo.hk/k2safe/orbit/sdk/go=/absolute/path/to/orbit/sdk/go
go mod tidy

将示例路径换成真实路径,不要把本机绝对路径作为发布依赖提交。后续会验证独立 module 标签和真实远端取包,再提供 go get 发布命令。当前源码同时验证 GOWORK=off 的独立构建。

6. 查询执行历史与证据

只读凭据需要 tasks:read 和任务所属队列范围。下方为接入函数片段,遍历尝试摘要并查询每条尝试详情;每次页面请求均需检查错误:

pageRequest := orbit.HistoryPageRequest{Limit: 20}
for {
    page, err := client.ListTaskAttempts(ctx, taskID, pageRequest)
    if err != nil { return err }
    for _, summary := range page.Items {
        detail, err := client.GetTaskAttempt(ctx, taskID, summary.ID)
        if err != nil { return err }
        fmt.Println(detail.ID, detail.Epoch, detail.State)
        // Result 是 json.RawMessage;读取业务字段时保留精确类型。
    }
    if page.NextCursor == "" { break }
    pageRequest.Cursor = page.NextCursor
}

查询证据对应 ListAttemptEvidence(ctx, taskID, attemptID, pageRequest) 与 GetAttemptEvidence(ctx, taskID, attemptID, evidenceID),列表相同方式使用 NextCursor。结果正文只在详情返回,列表适合按需展示。查询快照不授予执行权;证据的 outcome 是 Worker 原始声明,EVIDENCE_ONLY 不能当作任务成功。当前权威任务结果用 GetTask 核对。

完整 执行历史示例 会创建一条模拟任务,提交固定成功结果,再模拟矛盾报告,并通过上述四个查询核对历史。先按 Worker 初始化步骤 准备具有提交、读取及 Worker 权限的专用凭据,再从仓库根目录执行:

cd sdk/go
ORBIT_URL=http://127.0.0.1:8080 \
  ORBIT_CREDENTIALS_FILE=../../.local/worker.credentials.json \
  go run ./examples/history

预期输出:

task=<任务ID> state=SUCCEEDED attempts=1 evidence=1 reason=RESULT_CONFLICT disposition=EVIDENCE_ONLY

示例是受控故障演示,不调用外部业务系统。原结果为 {"version":"v1","sequence":9007199254740993},矛盾内容 {"version":"v2"} 只进入证据;任务仍保留原成功结果。每次运行创建独立任务/处理器身份,正常结束会排空并关闭连接,历史保留。示例不自动处理全部网络故障,失败时非零退出;应按输出的稳定错误分类核查,持续消费请使用自动 Worker。

7. 后续交付

P2 已提供底层协议、自动 Worker 运行器及示例 与历史查询,并通过 Schema 及进程故障阶段验收;P3 已实现 安全重试、计划调度、运行中取消 和 队列资源控制及示例,应用级配额、业务键许可、优先级/公平性和结果订阅继续开发;P4–P5 提供流程构建发布、信号、等待、轮询与人工恢复。每项随实现同步交付可运行示例及异常回归。