use-case

统一异步任务:提交、轮询与结果生命周期

直接答案对适合后台执行的 POST 请求,可在原路径前加 /async 提交并用 /get-async?id=... 查询;流式、模型列表、Files 和 Realtime 不能这样包装。

更新 · 审核信息

小白:提交与轮询

通用异步包装保留原 POST 路径,只在前面加 /async。下面把视频创建放入后台;请用模型广场实际支持的模型和路径。

submit=$(curl -sS "$BASE_URL/async/v1/videos"   -H "Authorization: Bearer $API_KEY"   -H "Content-Type: application/json"   -d '{"model":"<MODEL_ID>","prompt":"雨后城市的短镜头"}')
task_id=$(printf '%s' "$submit" | jq -r .id)

curl -sS "$BASE_URL/get-async?id=$task_id"   -H "Authorization: Bearer $API_KEY"

提交成功通常返回 202、任务 id 与 queued 状态。查询必须使用创建任务的用户和令牌权限,不能把任务 ID 当作公开下载地址。

状态机与终态

把 queued、not_start、submitted、in_progress 视为非终态;failure 和 completed 为终态,expired 表示结果已清理。轮询采用带抖动的退避,例如 1、2、4、8 秒后稳定到上限,并设置总截止时间。不要每秒无限轮询;前端刷新也不应创建新的生成任务。

结果信封

JSON 上游结果会放在 result 字段;二进制结果以 Base64 返回,并带 encoding: "base64"、原始 content_typestatus_code。客户端要先检查外层 status,再验证内层状态码与对象结构。完成后立即把需要长期保存的媒体流式复制到自己的对象存储。

不支持的包装

通用异步拒绝 GET、SSE、stream:true、模型列表、/v1/files/v1/realtime 和 Gemini 流式生成。原生视频、Kling、Suno 等任务协议可能拥有自己的创建与查询路径,不应与通用任务 ID 混用。

幂等、失败与计费

网络在提交响应返回前断开时,任务可能已经创建。客户端应保存业务请求指纹并先查已有任务,避免盲目重发。队列满、参数错误和鉴权错误不可无限重试;临时 429/5xx 才适合有限退避。预扣、最终结算和退款可能跨越任务生命周期,需在终态后用任务 ID、Request-ID 与消费日志核对。

专家运维

监控队列深度、排队时长、执行时长、成功率、失败原因、结果大小、过期率和存储剩余空间。结果写入必须有大小上限并采用流式 I/O,避免整份媒体驻留内存。清理策略应保护运行中任务,低磁盘时拒绝新任务而不是删除仍需交付的结果。

适用场景

  • 长耗时媒体与批处理请求
  • 避免客户端连接超时并可靠取得结果

API 协议

  • /async/*
  • /get-async
  • /v1/videos
  • /v1/video/generations

FAQ

哪些请求能加 /async

仅 JSON、multipart 或表单 POST,且不能是流式、模型列表、Files、Realtime 或 Gemini streamGenerateContent。目标原路径本身仍须受模型与渠道支持。

轮询到 HTTP 200 就完成了吗?

不是。读取 status;queued、submitted、in_progress 仍需等待,completed、failure、expired 才是需要处理的结果状态。

结果为什么会变成 expired?

异步结果不是永久文件。清理、保存期限或存储异常都可能使结果不可再取,应在完成后及时复制到业务存储。

官方来源

  1. OpenAI API Reference Official
  2. Gemini API Errors Official
  3. Claude API Errors Official