The Workflow SDK's start()
function can now admit a run and claim a hook in one atomic step. Duplicate workflow starts fail safely. The atomic start replaces the previous getHookByToken()
-then-start()
pattern, whose gap between the lookup and the start left a documented duplicate-start race.
import { resumeHook, start } from "workflow/api";import { HookConflictError } from "workflow/errors";import { processOrder } from "./workflows/process-order";
export async function POST(request: Request) { const { orderId, note } = await request.json(); const token = `order:${orderId}`;
try { const run = await start(processOrder, [orderId, note], { experimental_hook: { token }, }); return Response.json({ runId: run.runId, started: true }); } catch (error) { if (!HookConflictError.is(error)) throw error; // Route the duplicate's payload to the run that owns the token const hook = await resumeHook(token, { note }); return Response.json({ runId: hook.runId, started: false }); }}
Starting a run idempotently and routing a duplicate's payload to the run that already owns the token
Copy link to headingSubscribe to messages inside the run
The claimed Hook exists from the moment the run is admitted, so resumeHook
works even before…