Timeout for AI video jobs: set a deadline in your worker, not HTTP

A Sora-era HTTP timeout of 10 minutes breaks on Sume: sync waits cap at 30 s while jobs run for minutes. Use a client deadline and a poll. Python example.

5 min readSume
All posts

Put the wait for a video job in your worker as a deadline, and never in an HTTP timeout. Sume's sync mode blocks at most 30 seconds, and the API clamps wait_timeout_seconds to 0-30; the job runs on regardless (Jobs and results, read 2026-10-06). A video usually takes from 30 seconds to several minutes (Sume video docs, read 2026-10-06), so an HTTP call that waits for the file is the wrong tool.

The OpenAI Sora API ended on 2026-09-24 (Magic Hour tracker, read 2026-10-06). If your wrapper has a long blocking call, a proxy or edge in front of it probably cut it at some point already.

Three clocks

Which clock limits what, Sume docs, read 2026-10-06
ClockValueWhat it limitsWho sets it
sync wait budget0-30 s, clamped by the APIHow long one HTTP submit blocksSume, via wait_timeout_seconds
Poll intervalAbout 30 s suggested for videoHow often you ask for statusYou, or next_poll_after_seconds
Job durationSeconds to several minutesHow long generation takesThe model and the queue
Your deadlineYour choice, for example 15 minWhen your worker gives up waitingYou

What a deadline looks like

Poll until terminal or until the deadline, honoring next_poll_after_seconds when the jobs status endpoint gives it. On deadline, stop waiting but do not resubmit; the job is still running and still billing.

import os
import time
import requests

H = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"}


def wait(job_id: str, deadline_s: int = 900) -> dict:
    end = time.monotonic() + deadline_s
    delay = 5.0
    while time.monotonic() < end:
        r = requests.get(f"https://api.sume.com/v1/jobs/{job_id}/status",
                         headers=H, timeout=30)
        r.raise_for_status()
        s = r.json()
        if s.get("terminal"):
            return s
        delay = float(s.get("next_poll_after_seconds") or min(delay * 1.5, 30))
        time.sleep(delay)
    raise TimeoutError(f"{job_id} still running; do not resubmit")

Rules that follow

  • On a timeout of your own deadline, record the job id and come back later. Do not submit the original paid request again.
  • If the submit itself timed out, retry it with the same Idempotency-Key; the replay returns the original job.
  • Treat queued as normal. Concurrency limits apply when workers move jobs to processing, so a queue is not an error.
  • Read GET /v1/jobs/{id}/events when a job looks slow; it shows created, queued, started and submitted events.

Match the deadline to the work. Models and lengths differ, and a 30-second Seedance 2.5 or Wan 3.0 job is a bigger request than a 3-second Omni one, so keep a per-model deadline in config. A customer-facing flow should show a state like waiting or running and let the user leave; the result can arrive by a signed callback instead.

The blocked wrapper post and the events debugging post cover the two failures most ported code meets first.

Deadlines in a queue worker

If your jobs run inside a task queue such as Celery or a cloud task service, the visibility timeout or the task time limit is another clock, and it must be longer than your deadline or shorter on purpose. A task that polls for fifteen minutes under a five-minute task limit gets killed and retried, which resubmits the job. The retry is safe if the key is stable, and expensive if it is not.

A cleaner design splits the work into two tasks. The first submits and stores the job id. The second runs later, polls once, and either finishes or reschedules itself. No task waits long, so no limit is hit, and a process restart loses nothing.

Write the deadline into your runbook with its reason. Someone will one day raise it to an hour because a single job ran long, and the note that explains why the worker never blocks on the HTTP call, and why a missed deadline does not mean a lost job, saves a bad change.

  • Store the job id before you do anything else with it.
  • Make the poll task idempotent: it can run twice and the second run changes nothing.
  • Let the deadline be a stored timestamp, not a loop counter, so it survives restarts.
  • On deadline, mark the job as timed out in your own state and stop waiting; do not cancel unless you are sure generation has not started.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume