/// <reference types="node" />
import EventEmitter from 'events';
import { EVENTS } from './events';
import { IAnalytics } from './interfaces/analytics.interface';
import { IResistorConfig } from './interfaces/config.interface';
import { DeepPartial } from './interfaces/deep-partial.type';
import { EventListener } from './interfaces/event-listener.type';
import { IFlushConfig } from './interfaces/flush-config.interface';
import { WaitPass } from './interfaces/wait-pass.interface';
import { IWorker } from './interfaces/worker.interface';
export declare class Resistor<I> implements Pick<EventEmitter, 'on' | 'once' | 'off'> {
    /**
     * Temporary buffer to store the records until the worker flushes them.
     */
    protected buffer: I[];
    /**
     * Continouosly delayed timer to ensure the flush is called reguraly even if
     * the buffer would not reach it's maximum size.
     */
    protected flushTimer: NodeJS.Timer | undefined;
    /**
     * Stores the active flush workers, this is how the script tracks the active "threads".
     */
    protected vThreads: Promise<void>[];
    /**
     * When the maximum thread reached, the script will enqueue the flush workers in a FIFO logic,
     * after a thread finished, it will shift the first waiting execution and allows its execution.
     */
    protected waitQueue: WaitPass[];
    /**
     * Stores the manageging configurations.
     */
    protected config: IResistorConfig;
    /**
     * Usage analytics, designed to be used with healthchecks.
     */
    protected _analytics: IAnalytics;
    /**
     * NodeJS event emitter.
     */
    protected emitter: EventEmitter;
    /**
     * Store the reference to the worker function.
     */
    protected worker: IWorker<I>;
    /**
     * Initialize a configured resistor.
     */
    constructor(worker: IWorker<I>, config?: DeepPartial<IResistorConfig>);
    /**
     * Register an event listener for every occasion when the event emitted.
     */
    on(event: EVENTS, listener: EventListener): EventEmitter;
    /**
     * Register an event listener for one event emitting.
     */
    once(event: EVENTS, listener: EventListener): EventEmitter;
    /**
     * Deregister the given event listener.
     */
    off(event: EVENTS, listener: EventListener): EventEmitter;
    /**
     * Register an auto flush timeout in case the buffer is not loaded to the full
     * and we need to trigger an flush by timer.
     *
     * This is always being pushed out when the buffer reaches the maximum size.
     */
    protected register(): void;
    /**
     * Call this before shutdown to empty the last buffer and remove the timer.
     * Also useful to await this because only resolves when the buffer, queue, and threads are empty.
     *
     * @example process.on('SIGTERM', resistor.deregister.bind(resistor));
     * @example process.on('SIGKILL', resistor.deregister.bind(resistor));
     */
    deregister(): Promise<void>;
    /**
     * Initiate a flush, this will schedule the current buffer to a virtual thread.
     *
     * Important! By default the flush will not wait for the worker to execute so the caller
     * can push the records until the active threads are populated without waiting.
     *
     * But when the deregister called the script will wait for the last flush to be handled.
     */
    flush(config?: IFlushConfig): Promise<void>;
    /**
     * Handles the actual thread scheduling, the flush simply just packages an execution
     * and the scheduler is responsible to manage the queue and the threads.
     */
    protected schedule(job: (threadId: number) => Promise<void>, waitForWorker: boolean): Promise<void>;
    /**
     * Push a record to the buffer, returns a promise which should be awaited so
     * the caller can be slowed down when the threads are overloaded.
     */
    push(record: I): Promise<void>;
    /**
     * Reads the current analytics.
     */
    get analytics(): IAnalytics;
}
