/**
 * @packageDocumentation
 *
 * Based on `p-queue` but with access to the underlying queue, aborting a task
 * removes it from the queue and you can iterate over the queue results.
 *
 * @example
 *
 * ```ts
 * import all from 'it-all'
 * import { Queue } from 'it-queue'
 *
 * const queue = new Queue({
 *   concurrency: Infinity
 * })
 * void queue.add(async () => {
 *   return 'hello'
 * })
 * void queue.add(async () => {
 *   return 'world'
 * })
 *
 * const results = await all(queue)
 * // ['hello', 'world']
 *
 * // how many items are in the queue (includes running items)
 * console.info(queue.size)
 *
 * // how many items are running
 * console.info(queue.running)
 *
 * // how many items have not started running yet
 * console.info(queue.queued)
 * ```
 */
import { TypedEventEmitter } from 'main-event';
import { Job } from './job.ts';
import type { AbortOptions } from 'abort-error';
export type { Job, JobTimeline } from './job.ts';
export type { JobRecipient } from './recipient.ts';
export interface Comparator<T> {
    (a: T, b: T): -1 | 0 | 1;
}
export interface QueueInit<JobReturnType, JobOptions extends AbortOptions = AbortOptions> {
    /**
     * Concurrency limit.
     *
     * Minimum: `1`.
     *
     * @default Infinity
     */
    concurrency?: number;
    /**
     * If the queue size grows to larger than this number the promise returned
     * from the add function will reject
     *
     * @default Infinity
     */
    maxSize?: number;
    /**
     * An optional function that will sort the queue after a job has been added
     */
    sort?: Comparator<Job<JobOptions, JobReturnType>>;
    /**
     * If false, `.start` will need to be called to start processing jobs
     *
     * @default true
     */
    autoStart?: boolean;
}
export type JobStatus = 'queued' | 'running' | 'errored' | 'complete';
export interface RunFunction<Options extends AbortOptions = AbortOptions, ReturnType = void> {
    (options: Options): Promise<ReturnType>;
}
export interface JobMatcher<JobOptions extends AbortOptions = AbortOptions> {
    (options?: Partial<JobOptions>): boolean;
}
export interface QueueJobSuccess<JobReturnType, JobOptions extends AbortOptions = AbortOptions> {
    job: Job<JobOptions, JobReturnType>;
    result: JobReturnType;
}
export interface QueueJobFailure<JobReturnType, JobOptions extends AbortOptions = AbortOptions> {
    job: Job<JobOptions, JobReturnType>;
    error: Error;
}
export interface QueueEvents<JobReturnType, JobOptions extends AbortOptions = AbortOptions> {
    /**
     * A job is about to start running
     */
    active: CustomEvent;
    /**
     * All jobs have finished and the queue is empty
     */
    idle: CustomEvent;
    /**
     * The queue is empty, jobs may be running
     */
    empty: CustomEvent;
    /**
     * A job was added to the queue
     */
    add: CustomEvent;
    /**
     * A job has finished or failed
     */
    next: CustomEvent;
    /**
     * Emitted just after `"completed", a job has finished successfully - this
     * event gives access to the job and it's result
     */
    success: CustomEvent<QueueJobSuccess<JobReturnType, JobOptions>>;
    /**
     * A job has failed - this event gives access to the job and the thrown error
     */
    failure: CustomEvent<QueueJobFailure<JobReturnType, JobOptions>>;
}
/**
 * Heavily influence by `p-queue` with the following differences:
 *
 * 1. Items remain at the head of the queue while they are running so `queue.size` includes `queue.pending` items - this is so interested parties can join the results of a queue item while it is running
 * 2. The options for a job are stored separately to the job in order for them to be modified while they are still in the queue
 * 3. If a job's abort signal fires before execution begins, it is removed from the queue immediately
 * 4. 'success'/'failure' events are emitted instead of 'error'/'complete'
 */
export declare class Queue<JobReturnType = unknown, JobOptions extends AbortOptions = AbortOptions> extends TypedEventEmitter<QueueEvents<JobReturnType, JobOptions>> {
    concurrency: number;
    maxSize: number;
    queue: Array<Job<JobOptions, JobReturnType>>;
    private pending;
    private readonly sort?;
    private autoStart;
    constructor(init?: QueueInit<JobReturnType, JobOptions>);
    [Symbol.asyncIterator](): AsyncGenerator<JobReturnType, void, unknown>;
    emitEmpty(): void;
    emitIdle(): void;
    private tryToStartAnother;
    private enqueue;
    /**
     * Start the queue. If the `autoStart` parameter passed to the constructor was
     * not `false` this is a no-op
     */
    start(): void;
    /**
     * Prevent further jobs from running - call `.start` to start the queue again
     */
    pause(): void;
    /**
     * Adds a sync or async task to the queue. Always returns a promise.
     */
    add(fn: RunFunction<JobOptions, JobReturnType>, options?: JobOptions): Promise<JobReturnType>;
    /**
     * Clear the queue
     */
    clear(): void;
    /**
     * Abort all jobs in the queue and clear it
     */
    abort(): void;
    /**
     * Can be called multiple times. Useful if you for example add additional items at a later time.
     *
     * @returns A promise that settles when the queue becomes empty.
     */
    onEmpty(options?: AbortOptions): Promise<void>;
    /**
     * @returns A promise that settles when the queue size is less than the given
     * limit: `queue.size < limit`.
     *
     * If you want to avoid having the queue grow beyond a certain size you can
     * `await queue.onSizeLessThan()` before adding a new item.
     *
     * Note that this only limits the number of items waiting to start. There
     * could still be up to `concurrency` jobs already running that this call does
     * not include in its calculation.
     */
    onSizeLessThan(limit: number, options?: AbortOptions): Promise<void>;
    /**
     * The difference with `.onEmpty` is that `.onIdle` guarantees that all work
     * from the queue has finished. `.onEmpty` merely signals that the queue is
     * empty, but it could mean that some promises haven't completed yet.
     *
     * @returns A promise that settles when the queue becomes empty, and all
     * promises have completed; `queue.size === 0 && queue.pending === 0`.
     */
    onIdle(options?: AbortOptions): Promise<void>;
    /**
     * Size of the queue including running items
     */
    get size(): number;
    /**
     * The number of queued items waiting to run.
     */
    get queued(): number;
    /**
     * The number of items currently running.
     */
    get running(): number;
    /**
     * Returns an async generator that makes it easy to iterate over the results
     * of jobs added to the queue.
     *
     * The generator will end when the queue becomes idle, that is there are no
     * jobs running and no jobs that have yet to run.
     *
     * If you need to keep the queue open indefinitely, consider using it-pushable
     * instead.
     */
    toGenerator(options?: AbortOptions): AsyncGenerator<JobReturnType, void, unknown>;
}
//# sourceMappingURL=index.d.ts.map