Promise.allSettled for a wave of Sume jobs: keep the partial wins

Promise.all throws away nine good Sume videos when one job fails. Use Promise.allSettled over a wave sized to your plan's concurrency, in 30 lines of Node.

4 min readSume
All posts

The wave

Sume admits only so many generations at once: concurrency is 1 on Free, 4 on Pro, 8 on Startup and 20 on Scale, and submits beyond that wait in a queue whose default size is the larger of 3 and five times the concurrency. Past the queue you get 429 queue_full. The generation limits object even returns a wave_size_hint.

So a batch of 40 jobs should go out in waves, not as 40 simultaneous submits. Inside a wave you want every job's outcome, and one failure must not hide the rest.

Why not Promise.all

Promise.all rejects on the first rejection and you lose the other results in your handler, even though those jobs keep running and billing on Sume's side. Promise.allSettled always waits for all and gives each result a status of fulfilled or rejected.

A runnable wave

Replace the job ids and run with Node 18+. The poll function returns the final status for one id; a thrown error becomes a rejected result you can log and retry later.

const H = { Authorization: "Bearer " + process.env.SUME_API_KEY };
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

async function poll(id) {
  for (;;) {
    const r = await fetch("https://api.sume.com/v1/jobs/" + id + "/status", { headers: H });
    if (!r.ok) throw new Error(id + " HTTP " + r.status);
    const { data } = await r.json();
    if (data.terminal) return { id, status: data.status };
    await sleep((data.next_poll_after_seconds ?? 5) * 1000);
  }
}

const ids = process.argv.slice(2);
const results = await Promise.allSettled(ids.map(poll));
for (const r of results) {
  console.log(r.status === "fulfilled" ? r.value : "error: " + r.reason.message);
}

After the wave

  • Fetch results only for fulfilled entries whose status is completed.
  • For failed jobs, resubmit with a new Idempotency-Key; the old key points at the old attempt.
  • Save this as a .mjs file: it uses top-level await, which Node supports in ES modules.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume