Workflow
A durable multi-step pipeline composed from the queue and KV
primitives. Run state lives in KV; the queue carries { runId, step } pointers. Each worker delivery
advances exactly one step and enqueues the next (paced 2s apart),
so a run survives isolate restarts and every transition is
observable. The stepper below is kept live by polling a JSON status endpoint (~1.2s), with a
toast on each step & completion.
Tip
The 2s delay between steps is intentional (third argument to queuePush). In production use it to space out rate-limited third-party API calls, or drop it for maximum throughput.
Start a run
pipeline: validate → charge → ship → notify
Runs (0)
no runs yet — start one above.
// src/app/api/workflow/jobs/route.ts
// A durable multi-step pipeline on top of queue + KV.
// The worker advances ONE step per delivery, then enqueues the next.
export async function POST(req) {
const { payload: { runId, step } } = await req.json();
const run = await kvGet("run:" + runId);
run.steps[step].status = "done";
if (step + 1 < STEPS.length) {
run.steps[step + 1].status = "running";
await kvSet("run:" + runId, run);
await queuePush("demo-flow", { runId, step: step + 1 }, 2); // 2s pacing
} else {
run.status = "completed";
await kvSet("run:" + runId, run);
}
return Response.json({ ok: true });
}
// src/app/api/workflow/status/route.ts — snapshot the page polls ~1.2s:
// returns { runs: Run[] }; the page re-renders steppers in place and
// toasts each transition by diffing against the previous snapshot.
setInterval(async function () {
var runs = (await (await fetch("/api/workflow/status")).json()).runs || [];
renderRuns(runs);
runs.forEach(diffAndToast); // "✓ charge", "order completed", ...
}, 1200);