* Internal queue with chunk-based backpressure. * * This implements the core buffering logic shared between writer and readable. * - Chunk-oriented backpressure: counts write/writev calls, not bytes * - Configurable highWaterMark (default: 4) * - Four backpressure policies: strict, block, drop-
| 71 | * - drop-newest: discards new write (pendingWrites unused) |
| 72 | */ |
| 73 | class PushQueue { |
| 74 | /** Buffered chunks (each slot is from one write/writev call) */ |
| 75 | private slots = new RingBuffer<Uint8Array[]>(); |
| 76 | |
| 77 | /** Pending writes waiting for buffer space (strict policy only) */ |
| 78 | private pendingWrites = new RingBuffer<PendingWrite>(); |
| 79 | |
| 80 | /** Pending reads waiting for data */ |
| 81 | private pendingReads = new RingBuffer<PendingRead>(); |
| 82 | |
| 83 | /** Pending drains waiting for backpressure to clear */ |
| 84 | private pendingDrains: PendingDrain[] = []; |
| 85 | |
| 86 | /** Writer state */ |
| 87 | private writerState: WriterState = 'open'; |
| 88 | |
| 89 | /** Consumer state */ |
| 90 | private consumerState: ConsumerState = 'active'; |
| 91 | |
| 92 | /** Error that closed the stream */ |
| 93 | private error: any = null; |
| 94 | |
| 95 | /** Total bytes written */ |
| 96 | private bytesWritten = 0; |
| 97 | |
| 98 | /** Configuration */ |
| 99 | private readonly highWaterMark: number; |
| 100 | private readonly backpressure: BackpressurePolicy; |
| 101 | |
| 102 | /** Abort signal */ |
| 103 | private signal?: AbortSignal; |
| 104 | private abortHandler?: () => void; |
| 105 | |
| 106 | constructor(options: PushStreamOptions = {}) { |
| 107 | this.highWaterMark = Math.max(1, options.highWaterMark ?? 4); |
| 108 | this.backpressure = options.backpressure ?? 'strict'; |
| 109 | this.signal = options.signal; |
| 110 | |
| 111 | if (this.signal) { |
| 112 | if (this.signal.aborted) { |
| 113 | this.fail(this.signal.reason instanceof Error |
| 114 | ? this.signal.reason |
| 115 | : new DOMException('Aborted', 'AbortError')); |
| 116 | } else { |
| 117 | this.abortHandler = () => { |
| 118 | this.fail(this.signal!.reason instanceof Error |
| 119 | ? this.signal!.reason |
| 120 | : new DOMException('Aborted', 'AbortError')); |
| 121 | }; |
| 122 | this.signal.addEventListener('abort', this.abortHandler, { once: true }); |
| 123 | } |
| 124 | } |
| 125 | } |
| 126 | |
| 127 | // =========================================================================== |
| 128 | // Writer Methods |
| 129 | // =========================================================================== |
| 130 |
nothing calls this directly
no outgoing calls
no test coverage detected