Files
skills/docs/api-stack/api/api-router-worker-bridge/src/streaming/streaming.md
2026-05-29 08:20:56 +01:00

2.3 KiB

streaming

(no submodules)

Purpose

This module marshals binary ReadableStream<Uint8Array> bodies between the main and worker processes by piggy-backing on @suaveplan/api-worker- rpc's stream-chunk / stream-end / stream-ack frames. It implements the producer (sendStream) and consumer (receiveStream) halves of a single body transfer keyed on a numeric streamId (the same id baked into the body descriptor on the request or response envelope).

Features

  • Window-based back-pressure: the producer stalls after DEFAULT_STREAM_ WINDOW (16) outbound chunks until the consumer sends a matching stream-ack, preventing unbounded buffering across the port.
  • Reuses the wire frame shape of api-worker-rpc so a single port can multiplex RPC and bridge streams interchangeably.
  • Producer errors are forwarded via errorToEnvelope; consumer rehydrates via envelopeToError, preserving the SuaveplanError code chain.
  • Defensive enqueue: non-binary chunks fail with ROUTER_BRIDGE.STREAM_ INTERRUPTED so misuse is loud rather than silently corrupting the body.

Usage: Basic

import {
    sendStream,
    receiveStream,
} from "@suaveplan/api-router-worker-bridge/streaming";

const stream = receiveStream(port, 1);
// consume `stream` like any ReadableStream
await sendStream(port, 1, sourceStream);

Usage: Advanced

Tune the back-pressure window for a high-throughput download path:

import { sendStream } from "@suaveplan/api-router-worker-bridge/streaming";

await sendStream(port, streamId, hugeAttachment.body!, { window: 64 });

API Reference

  • sendStream(port, streamId, stream, options?) → Promise<void>.
  • receiveStream(port, streamId, options?) → ReadableStream<Uint8Array>.
  • DEFAULT_STREAM_WINDOW = 16.
  • StreamOptions { window?: number }.

Implementation Notes

The producer's ack listener is registered for the entire pump lifetime and torn down in finally so a crash in the source stream cannot leak a listener. receiveStream issues a stream-ack whenever its locally- buffered count reaches the window, not after every chunk — this matches the producer's pause threshold so throughput is steady rather than sawtoothed. ArrayBuffer payloads are coerced to Uint8Array to absorb runtime variation in how MessagePort surfaces transfers.