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 matchingstream-ack, preventing unbounded buffering across the port. - Reuses the wire frame shape of
api-worker-rpcso a single port can multiplex RPC and bridge streams interchangeably. - Producer errors are forwarded via
errorToEnvelope; consumer rehydrates viaenvelopeToError, preserving theSuaveplanErrorcode chain. - Defensive enqueue: non-binary chunks fail with
ROUTER_BRIDGE.STREAM_ INTERRUPTEDso 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.