Skip to content
RELKIT
Esc
↑↓navigate↵open⌘Jpreview
On this page

Progress and streams

Report typed progress and consume bounded live output.

Report bounded progress from a task so callers can follow the run without holding its execution open.

Progress is an observation channel, not a second source of truth. Define its shape and emit snapshots from the task:

/** Produces demonstration CSV through the ordinary order helper and emits validated progress around the durable export. */
import { defineTask } from "@relkit/app/tasks";
import { z } from "@relkit/app/schema";
import { exportOrderCsv } from "../helpers/fake-business.js";

const exportOrders = defineTask({
  id: "orders.export-orders",
  version: "1",
  execution: "durable",
  input: z.object({ orderIds: z.array(z.string()) }),
  output: z.object({ csv: z.string(), exported: z.number().int().nonnegative() }),
  progress: z.object({
    completed: z.number().int().nonnegative(),
    total: z.number().int().positive(),
  }),
  handler: async ({ orderIds }, context) => {
    await context.progress.emit({ completed: 0, total: orderIds.length });
    const csv = exportOrderCsv(orderIds);
    await context.progress.emit({ completed: orderIds.length, total: orderIds.length });
    return { csv, exported: orderIds.length };
  },
});

export default exportOrders;

Progress and stream items are limited to 64 KiB. Keep payloads small, include a sequence or cursor when consumers need ordering, and store durable results in the task output or application database.

Streams may be live, durable, or unavailable depending on the binding. A reconnect can observe a gap when retention has expired; reset the UI from the latest run snapshot instead of replaying untrusted client state. Provider capability output is authoritative for the selected environment.

Progress does not authorize a client to read a private run. Apply the same ownership and field-level redaction rules to progress and stream payloads as to the final output.

Reference and source