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
TypeScript
/**
* 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;
}