@hisorange/resistor
Version:
Versatily resource load throttler with extensible strategies, configuration and virtual thread management.
101 lines (100 loc) • 3.97 kB
TypeScript
/// <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;
}