UNPKG

@alexanderfedin/async-queue

Version:

TypeScript async producer-consumer queue with backpressure control, similar to Go channels or .NET Channel<T>

205 lines 6.13 kB
/** * AsyncQueue - A TypeScript implementation of an async producer-consumer queue with backpressure control * Uses circular buffer for O(1) enqueue/dequeue operations * * Developed by AI Hive® at O2.services * https://o2.services * * Copyright (c) 2024 AI Hive® at O2.services * Licensed under the MIT License */ /** * AsyncQueue provides a thread-safe producer-consumer queue with backpressure control, * similar to .NET's Channel<T> or Go channels. * Uses a circular buffer for optimal performance. * * @template T The type of items in the queue */ export declare class AsyncQueue<T = any> { private readonly maxSize; private readonly buffer; private head; private tail; private count; private waitingConsumers; private waitingConsumersCount; private waitingProducers; private waitingProducersCount; private readonly INITIAL_WAITING_CAPACITY; private closed; /** * Creates a new AsyncQueue instance * @param maxSize Maximum number of items the queue can hold before producers block (default: 1) */ constructor(maxSize?: number); /** * Adds an item to the circular buffer */ private addToBuffer; /** * Removes an item from the circular buffer */ private removeFromBuffer; /** * Pushes a resolver onto a waiting queue with capacity management */ private pushWaiter; /** * Pops a resolver from a waiting queue (LIFO) */ private popWaiter; /** * Adds an item to the queue. Blocks if the queue is full. * @param item The item to add to the queue * @returns A promise that resolves when the item has been added * @throws Error if the queue has been closed */ enqueue(item: T): Promise<void>; /** * Removes and returns the oldest item from the queue. Blocks if the queue is empty. * @returns A promise that resolves to the item, or undefined if the queue is closed and empty */ dequeue(): Promise<T | undefined>; /** * Signals that no more items will be added to the queue. * Existing items can still be consumed. */ close(): void; /** * Checks if the queue is closed AND empty * @returns true if the queue is closed and has no remaining items */ get isClosed(): boolean; /** * Gets the current number of items in the queue * @returns The number of items currently in the queue */ get size(): number; /** * Gets the maximum size of the queue * @returns The maximum number of items the queue can hold */ get capacity(): number; /** * Checks if the queue is at full capacity * @returns true if the queue is full */ get isFull(): boolean; /** * Checks if the queue is empty * @returns true if the queue has no items */ get isEmpty(): boolean; /** * Gets the number of waiting consumers * @returns The number of consumers waiting for items */ get waitingConsumerCount(): number; /** * Gets the number of waiting producers * @returns The number of producers waiting for space */ get waitingProducerCount(): number; /** * Returns an async iterator for consuming items from the queue. * Allows the queue to be used with for-await-of loops. * The iterator will complete when the queue is closed and empty. * * @example * ```typescript * const queue = new AsyncQueue<number>(); * * // Producer * setTimeout(async () => { * for (let i = 0; i < 5; i++) { * await queue.enqueue(i); * } * queue.close(); * }, 0); * * // Consumer using async iterator * for await (const item of queue) { * console.log(item); // 0, 1, 2, 3, 4 * } * ``` */ [Symbol.asyncIterator](): AsyncIterator<T>; /** * Creates an async iterable that consumes items from the queue. * This is an alternative way to get an async iterator. * * @returns An async iterable for consuming queue items * @example * ```typescript * const queue = new AsyncQueue<string>(); * const iterator = queue.iterate(); * * for await (const item of iterator) { * console.log(item); * } * ``` */ iterate(): AsyncIterable<T>; /** * Converts the queue to an async generator. * Useful for transformation pipelines. * * @returns An async generator that yields items from the queue * @example * ```typescript * const queue = new AsyncQueue<number>(); * const generator = queue.toAsyncGenerator(); * * // Transform items * async function* double(source: AsyncGenerator<number>) { * for await (const item of source) { * yield item * 2; * } * } * * for await (const item of double(generator)) { * console.log(item); * } * ``` */ toAsyncGenerator(): AsyncGenerator<T>; /** * Drains all items from the queue into an array. * Waits until the queue is closed and returns all items. * * @returns A promise that resolves to an array of all items * @example * ```typescript * const queue = new AsyncQueue<number>(); * * // Producer * (async () => { * for (let i = 0; i < 5; i++) { * await queue.enqueue(i); * } * queue.close(); * })(); * * const items = await queue.drain(); * console.log(items); // [0, 1, 2, 3, 4] * ``` */ drain(): Promise<T[]>; /** * Takes up to n items from the queue. * Returns early if the queue is closed before n items are received. * * @param n The maximum number of items to take * @returns A promise that resolves to an array of items * @example * ```typescript * const queue = new AsyncQueue<number>(); * * // Take first 3 items * const items = await queue.take(3); * ``` */ take(n: number): Promise<T[]>; } export default AsyncQueue; //# sourceMappingURL=index.d.ts.map