Abort waitForJob on SIGTERM, then resume from the stored job id

On a deploy, abort waitForJob with an AbortController on SIGTERM, keep the Sume job id, and resume the wait after restart. Aborting stops the wait, not the job.

5 min readSume
All posts

To stop a Sume job wait cleanly on deploy, create an AbortController, pass its signal to waitForJob, and call abort() from your SIGTERM handler. The SDK documents signal as aborting the wait and the in-flight request. It does not cancel the job: the job keeps running and keeps spending on Sume's side, so persist the job id before you wait and resume with the same id after restart.

Node's process docs list SIGTERM as a signal a process can listen for with process.on (read 2026-10-04). Container platforms typically send it before a hard kill, so you have a short window to record where you were.

What does the pattern look like?

Store the id first, then wait. On start, look for an unfinished id and wait on that instead of submitting again.

import { createSumeClient, waitForJob } from "@sume-com/sdk";
import { readFileSync, writeFileSync, existsSync } from "node:fs";

const client = createSumeClient({ apiKey: process.env.SUME_API_KEY! });
const STATE = "job-id.txt"; // use your database in production
const ac = new AbortController();
process.on("SIGTERM", () => ac.abort(new Error("shutting down")));

async function main() {
  if (!existsSync(STATE)) {
    throw new Error("no stored job id; submit first and write it to " + STATE);
  }
  const id = readFileSync(STATE, "utf8").trim();
  try {
    const job = await waitForJob(id, { client, signal: ac.signal });
    console.log(id, job.status);
  } catch (err) {
    if (ac.signal.aborted) {
      console.log("stopped waiting; job", id, "is still running");
      return;
    }
    throw err;
  }
}

main().catch((e) => {
  console.error(e);
  process.exitCode = 1;
});

What does an abort change on Sume's side?

What each stop action does to a Sume job, from Sume docs read 2026-10-04
ActionWait loopJob on Sume's side
signal.abort()Rejects with the signal's reason, in-flight read abortedKeeps running and spending
Client timeout elapsesThrows SumeJobTimeoutErrorKeeps running
Process killedGoneKeeps running; the id is your only handle
Cancel requestNext status read shows canceledMoves toward canceled; confirm by polling

How do you resume without double spend?

Resume by waiting on the stored id, not by submitting again. If you must resubmit, send the same Idempotency-Key as the first call: Sume replays the original job rather than starting a second one, as Jobs and results describes. The key has to be derived from your own record, not from Date.now().

What else belongs in the shutdown path?

  • Write the job id to durable storage before the first status read, not after.
  • Treat the abort rejection as a normal exit, not an error to alert on.
  • If the job should stop with the process, send an explicit cancel; aborting the wait will not do it.
  • For minutes-long video, a webhook removes the need for a process to be alive at all.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume