Job HubJob Hub任务状态中心

Job Hub API

接口说明

Job 代表一个完整任务,step 代表任务里的阶段状态。创建 job 后,后续主要通过 step 上报自动推进 job 进度;最终 step 映射到 100% 时,会用当前 step output 写入 job output 并完成 job。

PUT/api/jobs/:jobId

创建或更新 job

用于初始化 job,或特殊情况下手动修正整体状态。日常执行过程建议通过 steps 接口推进。

请求 body

{
  "name": "整理文章",
  "description": "抓取网页并生成摘要",
  "input": {
    "url": "https://example.com/article"
  },
  "metadata": {
    "traceId": "trace_123"
  }
}
curl -X PUT https://job-hub.kokoship.com/api/jobs/demo-job \
  -H 'content-type: application/json' \
  -d '{"name":"整理文章","description":"抓取网页并生成摘要","input":{"url":"https://example.com/article"}}'
PUT/api/jobs/:jobId/steps/:stepKey

创建或更新 step

根据 jobId + stepKey upsert 一个 step。jobId、stepKey、stepName 和 jobProgressStart/jobProgressEnd 应由主逻辑/orchestrator 分配后传给具体执行逻辑,worker 内不要重新生成。这个接口同时用于创建 step、更新 step 进度和 step 完成上报;同一个 stepKey 重复 PUT 会更新同一条 step。progress 是 step 自身进度;jobProgressStart/jobProgressEnd 用于换算整体 job 进度,不落库。

请求 body

{
  "stepName": "提取正文",
  "status": "running",
  "progress": 50,
  "jobProgressStart": 0,
  "jobProgressEnd": 30,
  "message": "正在提取正文"
}

响应示例

{
  "stepId": "uuid",
  "jobId": "demo-job",
  "stepKey": "extract",
  "stepName": "提取正文",
  "status": "running",
  "progress": 50,
  "message": "正在提取正文",
  "createdAt": "2026-06-17T10:00:03.000Z",
  "updatedAt": "2026-06-17T10:00:03.000Z",
  "startedAt": "2026-06-17T10:00:03.000Z"
}

请求示例:step 完成,job progress 到 30

{
  "status": "completed",
  "progress": 100,
  "jobProgressStart": 0,
  "jobProgressEnd": 30,
  "output": {
    "content": "正文..."
  }
}

请求示例:step 完成,job progress 到 100

{
  "stepName": "生成最终结果",
  "status": "completed",
  "progress": 100,
  "jobProgressStart": 80,
  "jobProgressEnd": 100,
  "output": {
    "summary": "...",
    "tags": ["AI"]
  }
}

请求示例:step 失败并终止 job

{
  "stepName": "提取正文",
  "status": "failed",
  "progress": 40,
  "message": "目标网页无法访问",
  "failJob": true
}
curl -X PUT https://job-hub.kokoship.com/api/jobs/demo-job/steps/extract \
  -H 'content-type: application/json' \
  -d '{"stepName":"提取正文","status":"running","progress":50,"jobProgressStart":0,"jobProgressEnd":30,"message":"正在提取正文"}'
GET/api/jobs/:jobId

获取单个 job

返回 job 核心信息、当前 running step 和最终 output。默认不返回完整 steps 列表。

curl https://job-hub.kokoship.com/api/jobs/demo-job
GET/api/jobs/:jobId?stepKey=:stepKey

获取 job 并带出指定 step

轻量探测接口。返回 job 核心信息、currentStep,并额外返回指定 stepKey 对应的 step。适合主流程只关心某个上游 step output 的场景。

响应示例

{
  "jobId": "demo-job",
  "status": "running",
  "progress": 30,
  "currentStep": null,
  "step": {
    "stepId": "uuid",
    "jobId": "demo-job",
    "stepKey": "extract",
    "stepName": "提取正文",
    "status": "completed",
    "progress": 100,
    "output": {
      "content": "正文..."
    },
    "durationMs": 7000
  }
}
curl 'https://job-hub.kokoship.com/api/jobs/demo-job?stepKey=extract'
GET/api/jobs/:jobId?include=steps

获取 job 详情

返回 job 核心信息、currentStep、output 和完整 steps timeline。这个接口适合详情页和调试,不建议主流程高频探测时使用。

curl 'https://job-hub.kokoship.com/api/jobs/demo-job?include=steps'
GET/api/jobs

获取 job 列表

返回 job 列表,按创建时间倒序排列,避免运行中任务因为频繁更新而在列表中跳动。支持 status=running|completed|failed 过滤。

curl https://job-hub.kokoship.com/api/jobs?status=running
GET/api/jobs/:jobId/steps

获取 step 列表

返回指定 job 的所有 steps,按创建时间升序排列。

curl https://job-hub.kokoship.com/api/jobs/demo-job/steps
GET/api/jobs/:jobId/steps/:stepKey

获取单个 step

返回指定 stepKey 对应的 step。下游 step 如果需要读取上游 step output,可以用这个接口精准读取。

curl https://job-hub.kokoship.com/api/jobs/demo-job/steps/extract
DELETE/api/jobs/:jobId

删除 job

删除 job,并级联删除该 job 下的 steps。

响应示例

{
  "ok": true
}
curl -X DELETE https://job-hub.kokoship.com/api/jobs/demo-job
DELETE/api/jobs

清理所有 jobs

删除所有 jobs,并级联删除所有 steps。这个接口用于清理任务列表,请谨慎使用。

响应示例

{
  "ok": true
}
curl -X DELETE https://job-hub.kokoship.com/api/jobs

进度规则

step.progress 表示 step 自身进度,不等于 job.progress。

当请求同时包含 progress、jobProgressStart、jobProgressEnd 时,服务端计算:jobProgressStart + progress / 100 * (jobProgressEnd - jobProgressStart)。

jobs.progress 只前进不后退,使用 max(existing, calculated)。

step 更新只要包含 message,服务端会同步刷新 jobs.message,dashboard 顶部显示最近一次上报的状态信息。

计算结果达到 100 时,当前请求必须包含 output;服务端会写入 step.output 和 jobs.output,并完成 job。

具体执行逻辑应避免过密或重复上报。不要在 tight loop 中每处理一小块就 PUT,也不要反复发送相同的 progress/message。建议只在阶段切换、进度有明显变化(例如至少 5%)、完成或失败时上报。

失败处理

step 失败时,使用同一个 step upsert 接口上报 status=failed,并把简短失败原因放在 message 中。

默认情况下,step failed 只会标记当前 step 失败,不会自动让整个 job 失败,因为某些 step 可能可重试、可跳过或可降级。

如果需要终止整个 job,传 failJob=true。服务端会把 jobs.status 更新为 failed,并把 step 的 message 同步到 jobs.message。

job failed 时不会强制 progress=100,也不会自动写 jobs.output。

stepKey 和 step 依赖

stepKey 是一个 job 内部的 step 幂等键,应由主逻辑/orchestrator 分配并通过路径传入,要求同一个 job 内唯一。重复 PUT 同一个 stepKey 会更新同一条 step。

stepName 是给人看的步骤名称,必须由主逻辑/orchestrator 在请求体中传入。具体 step 执行逻辑应复用主逻辑传入的 stepKey 和 stepName,不应自行随机生成。

如果 stepKey 是动态生成的,也应由主逻辑生成,并在重试或恢复时复用同一个 stepKey,避免产生重复 step。

jobProgressStart / jobProgressEnd 也建议由主逻辑分配,因为只有主逻辑知道每一步在整体 job 进度中的位置。

把 jobId、stepKey、stepName、jobProgressStart 和 jobProgressEnd 交给具体执行逻辑时,应把它们当成 workflow 契约复用。这样失败重试、进程恢复和多次上报都会落到同一条 step 记录上。

为了让 dashboard 保持轻快,也为了减少数据库写入压力,step worker 应主动去重:如果 progress 和 message 没有变化,就不需要再次上报。

Job Hub 不负责调度或唤醒下一个 step。step 的执行顺序、依赖传递、重试和分支逻辑由外层 workflow/orchestrator 负责。

下一个 step 如果需要上一个 step 的 output,可以使用 GET /api/jobs/:jobId?stepKey=:stepKey 或 GET /api/jobs/:jobId/steps/:stepKey 精准读取。

字段说明

字段类型说明
job.outputobject最终结果,由最终 step 映射到 100% 时自动写入,或 PUT job 时手动写入
step.outputobject当前 step 的输出结果
messagestringjob 或 step 当前状态的人类可读描述;status=failed 时用于放简短失败原因
failJobbooleanstep failed 时可传;true 表示同时把 job 标记为 failed
jobProgressStart / jobProgressEndnumber请求参数,用于把 step progress 换算成 job progress,不落库
stepKeystring路径参数,由主逻辑分配的 job 内 step 幂等键
stepNamestring请求 body 必填,由主逻辑传入的可读步骤名称
progress 上报频率约定由具体执行逻辑控制;建议阶段边界、至少约 5% 变化、完成或失败时上报,避免重复 PUT 相同 progress/message
currentStepobject | null当前最新 running step;默认 GET job 时返回
stepobject | null仅 GET job 时传 stepKey 参数返回,表示指定 stepKey 的 step
stepsarray仅 include=steps 或 steps 列表接口返回