UNPKG

homebridge-plugin-utils

Version:

Opinionated utilities to provide common capabilities and create rich configuration webUI experiences for Homebridge plugins.

80 lines (79 loc) 3.63 kB
/** * Backpressure-aware write queue for Node.js writable streams. * * This module provides a utility class for writing data to a writable stream while respecting backpressure signals. It maintains an internal queue and serializes writes, * pausing when the stream signals it isn't ready and resuming when it drains. This is particularly useful when feeding data from an event-driven source (e.g., fMP4 * segments from a livestream) into a process stdin that may not consume data as fast as it arrives. * * @module */ import type { Nullable } from "./util.js"; import type { Writable } from "node:stream"; /** * A backpressure-aware write queue that serializes writes to a writable stream, pausing when the stream signals backpressure and resuming on drain. * * The stream is resolved lazily via a getter function on each write, allowing the writer to be created before the stream exists and to handle stream replacement across * process restarts. * * @example * * ```ts * // Create a writer that feeds segments to an FFmpeg process stdin. * const writer = new BackpressureWriter(() => ffmpegProcess.stdin ?? null); * * // Enqueue segments as they arrive from a livestream source. * livestream.on("segment", (segment) => writer.write(segment)); * * // When the session ends, close the writer to release pending data. * writer.close(); * ``` * * @category Utilities */ export declare class BackpressureWriter { private drainListener; private drainStream; private readonly getStream; private isClosed; private isWriting; private readonly onWrite; private readonly queue; /** * Creates a new backpressure-aware write queue. * * @param getStream - A function that returns the current writable stream, or `null` if the stream is unavailable. Evaluated on each write attempt, allowing the * writer to be created before the stream exists or to track a stream that changes across process restarts. For a static stream, wrap it in an * arrow function: `() => stream`. * @param onWrite - Optional. A callback invoked after each segment is successfully written to the underlying stream. Useful for tracking write statistics. * * @example * * ```ts * // Lazy resolution...the stream is resolved on each write. * const writer = new BackpressureWriter(() => this.ffmpegProcess?.stdin ?? null, () => segmentCount++); * * // Static stream...wrap in an arrow function. * const writer = new BackpressureWriter(() => stream); * ``` */ constructor(getStream: () => Nullable<Writable>, onWrite?: () => void); /** * Enqueues data to be written to the stream. If the stream is available and not under backpressure, the data is written immediately. Otherwise, it is queued and * written when the stream signals it is ready via the drain event. * * @param data - The buffer to write to the stream. * * @returns Returns `true` if the data was accepted (stream is available), `false` if the stream is unavailable or the writer has been closed. */ write(data: Buffer): boolean; /** * Closes the writer, clearing any pending data and removing drain listeners. After closing, all subsequent writes are rejected. This should be called when the * underlying stream is being shut down or the session is ending. */ close(): void; /** * Returns the number of segments currently queued and waiting to be written. */ get pending(): number; private processQueue; }