UNPKG

@imqueue/core

Version:

Simple JSON-based messaging queue for inter service communication

460 lines (459 loc) 11.1 kB
import { EventEmitter } from 'events'; import { IMessageQueue, JsonObject, IMQOptions, IMQMode, EventMap } from '.'; export declare const DEFAULT_IMQ_OPTIONS: IMQOptions; export declare const IMQ_SHUTDOWN_TIMEOUT: number; /** * Returns SHA1 hash sum of the given string * * @param {string} str * @returns {string} */ export declare function sha1(str: string): string; /** * Returns random integer between given min and max * * @param {number} min * @param {number} max * @returns {number} */ export declare function intrand(min: number, max: number): number; /** * Compress given data and returns binary string * * @param {any} data * @returns {string} */ export declare function pack(data: any): string; /** * Decompress binary string and returns plain data * * @param {string} data * @returns {any} */ export declare function unpack(data: string): any; /** * Class RedisQueue * Implements simple messaging queue over redis. */ export declare class RedisQueue extends EventEmitter<EventMap> implements IMessageQueue { name: string; private readonly mode; [name: string]: any; /** * Writer connections collection * * @type {{}} */ private static writers; /** * Watcher connections collection * * @type {{}} */ private static watchers; /** * @event message (message: JsonObject, id: string, from: string) */ /** * This queue instance options * * @type {IMQOptions} */ options: IMQOptions; /** * Reader connection associated with this queue instance * * @type {IRedisClient} */ private reader?; /** * Channel connection associated with this queue instance * Specially designed for client subscriptions to server-emitted events * * @type {IRedisClient} */ private subscription?; /** * Channel name for subscriptions * * @type {string} */ private subscriptionName?; /** * Init state for this queue instance * * @type {boolean} */ private initialized; /** * Signals if the queue was destroyed * * @type {boolean} */ private destroyed; /** * True if the current instance owns a watcher connection, false otherwise * * @type {boolean} */ private watchOwner; /** * Signals initialization state * * @type {boolean} */ private signalsInitialized; /** * Will store check interval reference */ private safeCheckInterval; /** * This queue instance unique key (identifier), for internal use */ private readonly redisKey; /** * LUA scripts for redis * * @type {{moveDelayed: {code: string}}} */ private scripts; /** * Serializes given data object into string * * @param {any} data * @returns {string} */ private readonly pack; /** * Deserialize string data into object * * @param {string} data * @returns {any} */ private readonly unpack; /** * @constructor * @param {string} name * @param {IMQOptions} [options] * @param {IMQMode} [mode] */ constructor(name: string, options?: Partial<IMQOptions>, mode?: IMQMode); /** * Creates a subscription channel over redis and sets up channel * data read handler * * @param {string} channel * @param {(data: JsonObject) => any} handler * @return {Promise<void>} */ subscribe(channel: string, handler: (data: JsonObject) => any): Promise<void>; /** * Closes subscription channel * * @return {Promise<void>} */ unsubscribe(): Promise<void>; /** * Publishes a message to this queue subscription channel for currently * subscribed clients. * * If toName specified will publish to PubSub with a different name. This * can be used to implement broadcasting some messages to other subscribers * on other PubSub channels. * * @param {string} [toName] * @param {JsonObject} data */ publish(data: JsonObject, toName?: string): Promise<void>; /** * Initializes and starts current queue routines * * @returns {Promise<RedisQueue>} */ start(): Promise<RedisQueue>; /** * Sends a given message to a given queue (by name) * * @param {string} toQueue * @param {JsonObject} message * @param {number} [delay] * @param {(err: Error) => void} [errorHandler] * @returns {Promise<RedisQueue>} */ send(toQueue: string, message: JsonObject, delay?: number, errorHandler?: (err: Error) => void): Promise<string>; /** * Stops current queue routines * * @returns {Promise<RedisQueue>} */ stop(): Promise<RedisQueue>; /** * Gracefully destroys this queue * * @returns {Promise<void>} */ destroy(): Promise<void>; /** * Clears queue data in redis; * * @returns {Promise<void>} */ clear(): Promise<RedisQueue>; /** * Returns true if publisher mode is enabled on this queue, false otherwise. * * @return {boolean} */ isPublisher(): boolean; /** * Returns true if worker mode is enabled on this queue, false otherwise. * * @return {boolean} */ isWorker(): boolean; /** * Writer connection associated with this queue instance * * @type {IRedisClient} */ private get writer(); /** * Writer connection setter. * * @param {IRedisClient} conn */ private set writer(value); /** * Watcher connection instance associated with this queue instance * * @type {IRedisClient} */ private get watcher(); /** * Watcher setter sets the watcher connection property for this * queue instance * * @param {IRedisClient} conn */ private set watcher(value); /** * Logger instance associated with the current queue instance * @type {ILogger} */ private get logger(); /** * Return a lock key for watcher connection * * @access private * @returns {string} */ private get lockKey(); /** * Returns current queue key * * @access private * @returns {string} */ private get key(); /** * Destroys watcher channel * * @access private */ private destroyWatcher; /** * Destroys writer channel * * @access private */ private destroyWriter; /** * Establishes a given connection channel by its name * * @access private * @param {RedisConnectionChannel} channel * @param {IMQOptions} options * @param {any} context * @returns {Promise<IRedisClient>} */ private connect; /** * Builds and returns redis reconnection strategy * * @param {RedisQueue} context * @returns {() => (number | void | null)} * @private */ private retryStrategy; /** * Builds and returns connection ready state handler * * @access private * @param {RedisQueue} context * @param {RedisConnectionChannel} channel * @param {(...args: any[]) => void} resolve * @return {() => Promise<void>} */ private onReadyHandler; /** * Generates channel name * * @param {string} contextName * @param {string} prefix * @param {RedisConnectionChannel} name * @return {string} */ private getChannelName; /** * Builds and returns connection error handler * * @access private * @param {RedisQueue} context * @param {RedisConnectionChannel} channel * @param {(...args: any[]) => void} reject * @return {(err: Error) => void} */ private onErrorHandler; /** * Builds and returns redis connection close handler * * @access private * @param {RedisQueue} context * @param {RedisConnectionChannel} channel * @return {(...args: any[]) => any} */ private onCloseHandler; /** * Processes given redis-queue message * * @access private * @param {[any, any]} msg * @returns {RedisQueue} */ private process; /** * Returns the number of established watcher connections on redis * * @access private * @returns {Promise<number>} */ private watcherCount; /** * Processes delayed a message by its given redis key * * @access private * @param {string} key * @returns {Promise<void>} */ private processDelayed; /** * Watch routine * * @access private * @return {Promise<void>} */ private processWatch; /** * Process given keys from a message queue * * @access private * @param {string[]} keys * @param {number} now * @return {Promise<void>} */ private processKeys; /** * Watch message processor * * @access private * @param {...any[]} args * @return {Promise<void>} */ private onWatchMessage; /** * Clears safe check interval * * @access private */ private cleanSafeCheckInterval; /** * Setups watch a process on delayed messages * * @access private * @returns {RedisQueue} */ private watch; /** * Cleans up orphaned keys from redis * * @access private * @returns {Promise<RedisQueue | undefined>} */ private processCleanup; /** * Unreliable but fast way of message handling by the queue */ private readUnsafe; /** * Reliable but slow method of message handling by message queue */ private readSafe; /** * Initializes a read process on the redis message queue * * @returns {RedisQueue} */ private read; /** * Checks if the watcher connection is locked * * @access private * @returns {Promise<boolean>} */ private isLocked; /** * Locks watcher connection * * @access private * @returns {Promise<boolean>} */ private lock; /** * Unlocks watcher connection * * @access private * @returns {Promise<boolean>} */ private unlock; /** * Emits error * * @access private * @param {string} eventName * @param {string} message * @param {Error} err */ private emitError; /** * Acquires an owner for watcher connection to this instance of the queue * * @returns {Promise<void>} */ private ownWatch; /** * This method returns watcher lock resolver function * * @access private * @param {(...args: any[]) => void} resolve * @param {(...args: any[]) => void} reject * @return {() => Promise<any>} */ private watchLockResolver; /** * Initializes a single watcher connection across all queues with the same * prefix. * * @returns {Promise<void>} */ private initWatcher; }