Files
orbit/docs/api/task-queries.md

7.2 KiB
Raw Blame History

按业务键与创建时间查询任务

状态:P3 已实现HTTP、Go SDK及运行示例。这是 GET /v1/tasks 的扩展,返回任务摘要,查询不执行或重试任务。验证记录见本阶段报告。

1. 权限与字段

请求使用 Authorization: Bearer <token>,需要当前命名空间的 tasks:read 及指定队列范围,不携带幂等键。命名空间由凭据确定,不接受调用方指定。队列不在权限范围返回403;有权限但不存在该队列/无匹配任务时返回空列表,不披露其他命名空间资源。

参数 类型与默认 要求
queue_id string,必填 32位小写十六进制队列标识
state string,可选 WAITING、LEASED、RUNNING、NEEDS_REVIEW、SUCCEEDED、FAILED、CANCELLED之一;省略表示所有状态
business_key string,可选 1–191个Unicode字符,无NUL/回车/换行;精确关联匹配,显式空值拒绝
created_from RFC3339时间,可选 创建时间下界,包含该时刻
created_before RFC3339时间,可选 创建时间上界,不包含该时刻;与下界同时给出时必须更晚
limit integer,默认20 1–100;可以在翻页时更改
cursor string,可选 上页next_cursor,最长1024字符,必须保持其他筛选不变

参数只能出现一次,未知名称、非法百分号编码、空时间、日期字符串、非规范状态或非法范围返回400。时间允许RFC3339时区偏移并规范化UTC;精度最多到微秒,UTC年份2000–9998。上下界可以仅给一个,不设置默认时间窗口。JSON的null不是URL查询值,省略参数才表示不设该条件。

business_key区分大小写、重音字符、Unicode编码形式以及尾部空格。例如 object:1、object:1 、Object:1 是不同键;é 与 e 加组合重音也不同。不修剪/规范化输入,不使用LIKE,% 和 _ 是普通字符;关联键不承担业务幂等。纯空格键若已提交也按原值匹配,空字符串提交仍表示没有关联键;本接口不提供“只查无关联键”筛选。

2. 完整请求和响应

使用URL编码,尤其是键中的 +、%、空格和时间中的时区加号:

curl --get "$ORBIT_URL/v1/tasks" \
  -H "Authorization: Bearer $ORBIT_TOKEN" \
  --data-urlencode "queue_id=$ORBIT_QUEUE_ID" \
  --data-urlencode 'business_key=object:operation-001' \
  --data-urlencode 'state=FAILED' \
  --data-urlencode 'created_from=2026-09-17T00:00:00Z' \
  --data-urlencode 'created_before=2026-09-18T00:00:00Z' \
  --data-urlencode 'limit=20'

HTTP200完整示意响应:

{
  "request_id":"44444444444444444444444444444444",
  "data":{
    "items":[{
      "id":"22222222222222222222222222222222",
      "queue_id":"11111111111111111111111111111111",
      "state":"FAILED",
      "revision":"4",
      "handler":"object.prepare",
      "handler_version":"v1",
      "business_key":"object:operation-001",
      "available_at":"2026-09-17T00:00:00Z",
      "deadline_at":"2026-09-17T00:01:00Z",
      "attempt_count":1,
      "created_at":"2026-09-17T00:00:00Z",
      "updated_at":"2026-09-17T00:00:01Z"
    }]
  }
}

有下一页时data还包含next_cursor字符串;没有匹配时items为 []。摘要不携带payload/result/冻结策略/retry_of,按需调用 GetTask 获取详情。字段完整说明见任务接口。不返回全量总数或大offset接口。

3. 分页与并发语义

固定按 (created_at DESC,id DESC) 排序。相同创建时间以任务ID打破平局;取消、执行和核查改变状态/updated_at,不改变创建排序键。每页取至多limit+1行以判断下一页。

v2游标同时绑定命名空间、队列、状态、精确业务键和规范化UTC时间界限;长业务键通过固定长度摘要绑定,191字符的合法键不会撑破游标上限。修改/删除任何筛选、混用其他命名空间或传入非法游标返回400,不能通过更换参数扩大原页查询。游标是排序位置,不是授权证明,每页都重新校验当前凭据和队列范围。

跨页不是数据库快照:遍历期间新增任务、任务状态变化可能影响后续页面,不能将动态状态查询当作完整审计导出。新任务排在已读位置之前时,从首页刷新才会看到;状态筛选的任务离开该状态时可能从后续页面消失。需要可靠处理结果使用结果订阅,核对历史使用执行历史与操作审计。

旧版未带版本的游标仅兼容原队列/状态查询,不能附加业务键或时间界限。SDK把游标当不透明字符串,不应解析、改写或自行拼接。

4. SDK调用

Client.ListTasks(ctx, orbit.ListTasksRequest) 返回 TaskPage。新增字段BusinessKey、CreatedFrom、CreatedBefore,其余字段保持不变。BusinessKey空字符串在SDK中表示省略,时间指针nil表示无该界限。

query := orbit.ListTasksRequest{
    QueueID: queueID,
    State: orbit.TaskFailed,
    BusinessKey: "object:operation-001",
    CreatedFrom: &from,
    CreatedBefore: &before,
    Limit: 20,
}
for {
    page, err := client.ListTasks(ctx, query)
    if err != nil { return err }
    for _, task := range page.Items {
        fmt.Println(task.ID, task.State, task.CreatedAt)
    }
    if page.NextCursor == "" { break }
    query.Cursor = page.NextCursor
}

片段假设已有客户端及time.Time类型from/before;完整可运行源码见示例。SDK校验ID、范围、状态、键长度/UTF-8及时间精度,并用url.Values编码,时间转UTC,不修改调用方时间对象。超时只影响读取,可保持条件重新请求;没有自动重试或自动翻页。

5. 存储、升级与边界

迁移000016明确business_key使用 utf8mb4_0900_bin,保证尾部空格有意义;现有文本不重写、不修剪,不增加模型字段或数据库外键。单项受理、计划触发和人工重试按Go字符串是否为空决定NULL,不依赖连接排序规则的NULLIF比较。

查询使用四个固定索引之一,全部将等值过滤放在创建时间及ID之前:

筛选组合(均含命名空间与队列) 索引
无状态/业务键 ix_task_created
状态 ix_task_state_created
业务键 ix_task_queue_business_created,新增
业务键与状态 ix_task_queue_business_state_created,新增

上下界与游标在索引时间范围内继续扫描,不按全部任务取回后内存过滤。SQL索引名来自固定服务端分支,查询值全部参数化。实际MySQL执行计划验证四组走对应range/ref索引且无filesort;这是查询路径验证,不是生产吞吐或百万租户容量证明。

升级需先停止旧写入节点、应用迁移,再统一启用新版节点;列排序规则和索引调整会有DDL成本,应演练目标规模维护窗口。新SDK查询旧节点时,新参数会被拒绝,不能删除筛选后自动降级。新旧节点混合分页与生产滚动升级尚未验收。

通用400/401/403/503错误见任务手册。业务键与时间查询不新增权限,不授予执行、取消或人工核查权限。