Queue

A durable FIFO queue with delayed visibility, automatic retries and a dead-letter state, over the loopback SDK at /__bext/sdk/queue/*. A registered worker is just an HTTP route bext POSTs each message to — here /api/queue/jobs, which upper-cases & reverses the text and writes the result to KV. This page polls a JSON status endpoint (~1.2s) to update depth counters and the results table in place and toast each completed job — no reloads.

Tip
A message that exceeds maxAttempts lands in the dead-letter queue (DLQ) — it doesn't block the rest. Inspect dead messages via /__bext/sdk/queue/dead/list and replay them with /dead/retry.

Queue depth

0
pending
0
processing
0
dead
0
results

Enqueue work

Processed results (0)

inputoutputattemptsprocessed

nothing processed yet — push a job above.

src/app/api/queue/jobs/route.tsTypeScript
// src/app/api/queue/status/route.ts — JSON snapshot the page polls:
export async function GET() {
  const stats = await queueStats(APP, "demo-jobs");
  const results = await kvEntries(APP, "result:", 12);
  return Response.json({ stats, results });
}

// page client — poll every 1.2s, update DOM + toast completed jobs:
var seen = {};
setInterval(async function () {
  var d = await (await fetch("/api/queue/status")).json();
  renderStats(d.stats);
  renderResults(d.results);
  d.results.forEach(function (r) {
    if (!seen[r.id]) { seen[r.id] = true; bextToast("done: " + r.output, "success"); }
  });
}, 1200);

// pushing a job is a fetch (no reload); the next poll shows it complete:
form.addEventListener("submit", async function (ev) {
  ev.preventDefault();
  await fetch(location.pathname, {
    method: "POST",
    body: new FormData(form),
    headers: { accept: "application/json" },
  });
  bextToast("job queued", "info");
});