import AsyncProcess from './asyncProcess';
import EventEmitter from '../../../../tools/eventEmitter';
/**
 * Starts, stops, restarts and provides long-running background processes (running functions within node process)
 * resolving race conditions and including process failovers until process canceled
 */
declare class AsyncProcessPool<Provider, Process extends AsyncProcess> {
    protected _logger: import("../../../../logger").Logger;
    private _processProvider;
    private _scheduledProcesses;
    private _runtimeProcesses;
    private _processRuntimes;
    private _options?;
    private _events;
    private _label;
    private _stopped;
    private _usages;
    private _dependencies;
    /**
     * Constructs instance
     * @param provider process provider
     * @param options additional options
     */
    constructor(provider: Provider, options: AsyncProcessPool.Options<Process>);
    /**
     * Returns label for logging
     * @returns label
     */
    get label(): string;
    /**
     * Event emitter related to this pool
     * @returns event emitter
     * @internal
     */
    get events(): EventEmitter<AsyncProcessPool.Events<Process>>;
    /**
     * Returns whether the scheduler was given command to stop
     * @returns whether stopped
     */
    get stopped(): boolean;
    /**
     * Schedules a process. After the process has scheduled, it is immediately available in synchronous way. But it may
     * not be started fully yet (its `start` method not completed yet), or currently running process may be an old one,
     * which is going to stop. The latest actual and fully started process can be awaited with `waitProcess` method
     * @param id process ID. If a process with same ID is already scheduled, the call will be ignored
     * @param options process options
     * @throws if the pool is stopped and the `throwIfStopped` option is enabled
     */
    scheduleProcess(id: string, options: AsyncProcessPool.ScheduleProcessOptions<Provider>): void;
    /**
     * Restarts a process if it is scheduled, otherwise the call will be ignored. If the process is waiting for throttle
     * delay to failover after error or unexpected stop, this method will force the failover
     * @param process process ID or process itself. If the process instance is specified, it will be restarted only if it
     * is still actual running process and not scheduled to be restarted yet
     */
    restartProcess(process: string | Process): void;
    /**
     * Cancels a process
     * @param id process ID
     * @param options additional options
     * @returns promise resolving when currently running process stopped
     */
    cancelProcess(id: string, options?: AsyncProcessPool.CancelProcessOptions): Promise<void>;
    private _cancelProcess;
    /**
     * Returns scheduled process IDs
     * @returns process IDs
     */
    getScheduledIds(): string[];
    /**
     * Returns running at this moment process IDs. It will always include scheduled IDs + some processes that was canceled
     * but may be still running or stopping
     * @returns process IDs
     */
    getRunningIds(): string[];
    /**
     * Returns whether has scheduled process
     * @param id process ID
     * @returns true if scheduled
     */
    hasScheduled(id: string): boolean;
    /**
     * Returns whether has a process, scheduled by specific usage
     * @param id process ID
     * @param usage usage
     * @returns true if scheduled by
     */
    hasScheduledBy(id: string, usage: any): boolean;
    /**
     * Returns process IDs which are scheduled by specific usage
     * @param usage usage
     * @returns process IDs
     */
    getScheduledBy(usage: any): string[];
    /**
     * Returns process schedulement
     * @param id process ID
     * @returns schedulement or undefined if not scheduled
     */
    getSchedulement(id: string): AsyncProcessPool.Schedulement<Provider> | undefined;
    /**
     * Returns current process in its running state which can be not started yet, starting, running, stopping or stopped
     * @param id process ID
     * @returns process in its state or undefined if there is no such process scheduled
     */
    getProcess(id: string): Process | undefined;
    /**
     * Waits for running started process instance. If the process was rescheduled/restarted and an old process instance is
     * still running, the method will wait for the new process instance to start only. Note, that a process can become
     * stopped or canceled till the method resolves after `await` in the calling code. So this method only increases
     * probability the returned process will be running
     * @param id process ID
     * @param options additional options
     * @returns promise resolving with process or `undefined`, depending on specified options
     * @throws if process is not scheduled or becomes unscheduled during waiting due to `throwIfNotScheduled` option
     * @throws `TimeoutError` if timed out waiting for the process due to timeout options
     */
    waitProcess(id: string, options?: AsyncProcessPool.WaitProcessOptions): Promise<Process>;
    /**
     * Cancels all currently scheduled processes and waits until they stop
     * @returns promise resolving when stopped
     */
    cancelAll(): Promise<void>;
    /**
     * Stops all processes
     * @returns promise resolving when stopped
     */
    stop(): Promise<void>;
    private _run;
    private _handleControlSignal;
    private _getThrottleDelay;
    private _stopProcess;
}
declare namespace AsyncProcessPool {
    /** Process provider */
    type ProcessProvider<Process extends AsyncProcess> = (context: Context, args: any[]) => ConstructedProcess<Process>;
    /** Constructed process */
    type ConstructedProcess<Process extends AsyncProcess> = {
        /** Process */
        process: Process;
        /** Process context */
        context: ProcessContext;
        /** Mapped process args */
        args: any[];
    };
    /** Basic process context */
    type Context = {
        /** Process ID */
        processId: string;
        /** Current pool */
        pool: AsyncProcessPool<any, any>;
        /** Process stage */
        stage: ProcessContext.ProcessStage;
        /** Whether the process was scheduled to cancel by external command (cancel or restart) */
        canceled?: boolean;
    };
    /** Constructing options */
    type Options<Process> = {
        /** Logging label. Defaults to `default` */
        label?: string;
        /**
         * Process run attempt throttle delay in case of failover. May be overriden by processes when scheduling,
         * Defaults to 30 seconds
         */
        processFailoverThrottleDelayInMs?: number;
        /** Dependencies shared across all processes */
        dependencies: AsyncProcess.Dependencies<Process>;
    };
    /** Method options */
    type ScheduleProcessOptions<Provider> = {
        /** Process constructor parameters */
        args: ProcessArgs<Provider>;
        /** Whether to throw an error if the pool is already stopped. Defaults to `true` */
        throwIfStopped?: boolean;
        /**
         * Usage to track to make it possible to cancel process only when all usages are canceled.
         * Defaults to `default`
         */
        usage?: any;
        /** Overriden failover throttle delay to use */
        failoverThrottleDelay?: ThrottleDelay;
    };
    /** Throttle delay */
    type ThrottleDelay = FixedDelay | ExponentialDelay;
    /** Fixed delay */
    type FixedDelay = {
        /** Mode */
        mode: 'fixed';
        /** Delay value */
        delayInMs: number;
        /** Delay randomization factor in range [0; 1]. Defaults to `0` */
        randomizationFactor?: number;
    };
    /** Exponential delay */
    type ExponentialDelay = {
        /** Mode */
        mode: 'exponential';
        /** Minimum (start) delay */
        minDelayInMs: number;
        /** Maximum (end) delay */
        maxDelayInMs: number;
        /**
         * Delay to wait after successful connection to reset current exponential delay to its minimum value. If the process
         * should be throttled again and this delay has not timed out yet, the throttle delay will increase exponentially.
         * Otherwise, the throttle delay will start from beginning. Defaults to `0`
         */
        resetDelayInMs?: number;
        /** Delay randomization factor in range [0; 1]. Defaults to `0` */
        randomizationFactor?: number;
    };
    /** Method options */
    type CancelProcessOptions = {
        /** Usage to actually cancel process only when last usage is canceled. Defaults to `default` */
        usage?: any;
        /** Whether to cancel all usages */
        allUsages?: boolean;
    };
    /** Latest schedulement data */
    type Schedulement<Provider> = {
        /** Options with which the account was scheduled */
        options: {
            /** Process constructor parameters */
            args: ProcessArgs<Provider>;
        };
        /** Usages */
        usages: Set<any>;
    };
    /** Method options */
    type WaitProcessOptions = {
        /** Waiting timeout */
        timeoutInMs?: number;
        /**
         * Promise signalizing when waiting should be stopped. Makes the method return `undefined` if resolved or rejects
         * with the promise's error
         */
        stopPromise?: Promise<void>;
        /**
         * Whether to throw error if process is not scheduled or becomes canceled during waiting. If `false` and process is
         * not scheduled, `undefined` will be returned. The error won't be thrown if the process was canceled and then
         * immediately scheduled again in synchronous way
         */
        throwIfNotScheduled?: boolean;
        /** Whether to throw `TimeoutError` error if waiting timeout exceeded */
        throwOnTimeout?: boolean;
    };
    /** Wait process attempt options */
    type WaitAttemptOptions = {
        /** One attempt timeout */
        timeoutInMsPerAttempt?: number;
        /** Whether to throw `TimeoutError` error if waiting attempts exceeded */
        throwIfExceeded?: boolean;
        /**
         * Max attempts to wait. If the attempts exceeded, then eithier:
         * - if the process has still been scheduled, `undefined` will be returned
         * - otherwise, depends on `throwIfNotScheduled` option
         * @default Infinity
         */
        maxAmount?: number;
        /**
         * Predicate to check if new waiting attempt should be performed.
         * If specified, has larger priority than `maxAmount`
         */
        waitIf?: (attempt: number) => boolean;
    };
    /** Event emitter events */
    type Events<Process extends AsyncProcess> = {
        /** Called when a specific process created */
        [event: `created:${ProcessId}`]: () => void;
        /** Called when a specific process fully successfully started */
        [event: `started:${ProcessId}`]: (process: Process) => void;
        /** Called when a specific process canceled */
        [event: `canceled:${ProcessId}`]: () => void;
        /** Called when any process fully successfully started */
        started: (process: Process) => void;
    };
    /** Process ID */
    type ProcessId = string;
}
export default AsyncProcessPool;
import ProcessContext from './processContext';
type ProcessArgs<Provider> = Provider extends AsyncProcessPool.ProcessProvider<any> ? Parameters<Provider>[1] : never;
