UNPKG

mq-flow

Version:

A lightweight, simple queue system designed for small tasks that need to be executed in a queued manner

1 lines 9.16 kB
{"version":3,"sources":["../src/Queue/Queue.ts"],"sourcesContent":["import { EventEmitter } from \"stream\";\r\nimport { Options, Process, PushPopReturnType } from \"../types/type\";\r\nimport { Priority, ProcessState } from \"../enum/enum\";\r\n\r\n\r\n/**\r\n * Queue Class\r\n * \r\n * A lightweight, efficient, and event-driven queue implementation for managing and executing asynchronous processes.\r\n * Built for Node.js environments, this class uses a FIFO (First-In-First-Out) mechanism with support for priority \r\n * processing, dynamic addition/removal of tasks, and real-time event notifications.\r\n * \r\n * Features:\r\n * - Push processes with priority handling (HIGH or LOW).\r\n * - Dynamically remove or pop processes from the queue.\r\n * - Start and stop the queue processing.\r\n * - Event-driven mechanism to retrieve process results.\r\n * \r\n * Dependencies:\r\n * - Uses Node.js `EventEmitter` for event-based operations.\r\n * \r\n * Usage:\r\n * ```javascript\r\n * import { Queue } from './queue';\r\n * \r\n * const queue = new Queue();\r\n * \r\n * // Push a process\r\n * queue.mqPush(async () => {\r\n * // Some asynchronous operation\r\n * }, { ProcessId: 'task1', Priority: Priority.HIGH });\r\n * \r\n * // Start the queue processing\r\n * queue.mqStart();\r\n * \r\n * // Listen for results\r\n * queue.on('getResult', (result) => {\r\n * console.log(result);\r\n * });\r\n * ```\r\n */\r\nexport class Queue extends EventEmitter {\r\n\r\n #Queue: Process[] = [];\r\n #isProcessStartFlag: boolean = false;\r\n #ProcessState: ProcessState = ProcessState.IDLE;\r\n CurrentProcessId: string | number | null = null;\r\n\r\n /**\r\n * Adds a new process to the queue with an optional priority.\r\n * If the queue is already processing, it starts processing the new process immediately.\r\n * \r\n * @param {() => Promise<any>} Process - The asynchronous function to be executed.\r\n * @param {Options} [Options] - Additional options for the process:\r\n * - ProcessId: A unique identifier for the process.\r\n * - Priority: Priority of the process (HIGH (1) or LOW (0)).\r\n * \r\n * @returns {PushPopReturnType} An object containing the ProcessId and the updated QueueLength.\r\n * \r\n * @throws {Error} If an invalid priority is provided.\r\n */\r\n mqPush(Process: () => Promise<any>, Options?: Options): PushPopReturnType {\r\n const id: string | number = Options?.ProcessId !== undefined ? Options?.ProcessId : (this.#Queue.length + 1);\r\n if (Options?.Priority && Options?.Priority !== 0 && Options?.Priority !== 1) throw new Error('Priority must be HIGH(1) or LOW(0)');\r\n Options?.Priority === Priority.HIGH ? this.#Queue.unshift({ CallableFunction: Process, ProcessId: id }) : this.#Queue.push({ CallableFunction: Process, ProcessId: id });\r\n if (this.#isProcessStartFlag) this.#Worker();\r\n return { ProcessId: id, QueueLength: this.#Queue.length };\r\n }\r\n\r\n /**\r\n * Removes the last process from the queue.\r\n * \r\n * @returns {PushPopReturnType} An object containing the ProcessId of the removed process and the updated QueueLength.\r\n * \r\n * @throws {Error} If the queue is empty or if the last process is currently under execution.\r\n */\r\n mqPop(): PushPopReturnType {\r\n if (this.#Queue.length === 0) throw new Error(\"Queue is empty: No processes available to execute.\");\r\n if (this.CurrentProcessId === this.#Queue[this.#Queue.length - 1].ProcessId)\r\n throw new Error(`Process already under execution: The process with ID ${this.CurrentProcessId} is currently running.`);\r\n const processId = this.#Queue.pop()?.ProcessId;\r\n return { ProcessId: processId, QueueLength: this.#Queue.length };\r\n }\r\n\r\n /**\r\n * Removes a specific process from the queue by its ProcessId.\r\n * \r\n * @param {string | number} ProcessId - The unique identifier of the process to be removed.\r\n * \r\n * @returns {PushPopReturnType} An object containing the ProcessId of the removed process and the updated QueueLength.\r\n * \r\n * @throws {Error} If the queue is empty or if the specified process is currently under execution.\r\n */\r\n mqRemove(ProcessId: string | number): PushPopReturnType {\r\n if (this.#Queue.length === 0) throw new Error(\"Queue is empty: No processes available to execute.\");\r\n if (this.CurrentProcessId === ProcessId)\r\n throw new Error(`Process already under execution: The process with ID ${this.CurrentProcessId} is currently running.`);\r\n const processId = this.#Queue.splice(this.#Queue.findIndex((i) => i.ProcessId === ProcessId), 1)[0].ProcessId;\r\n return { ProcessId: processId, QueueLength: this.#Queue.length }\r\n }\r\n\r\n /**\r\n * Starts processing the queue.\r\n * Processes are executed sequentially in the order they are added unless a higher priority is specified.\r\n */\r\n mqStart() {\r\n this.#isProcessStartFlag = true;\r\n this.#Worker();\r\n }\r\n\r\n /**\r\n * Stops processing the queue.\r\n * This does not clear the queue, and processes can resume when `mqStart()` is called again.\r\n */\r\n mqEnd() {\r\n this.#isProcessStartFlag = false;\r\n }\r\n\r\n /**\r\n * Retrieves the ProcessId of the process currently being executed.\r\n * \r\n * @returns {string | number | null} The ProcessId of the current process, or null if no process is under execution.\r\n */\r\n getCurrentProcessId() {\r\n return this.CurrentProcessId;\r\n }\r\n\r\n /**\r\n * Gets the current length of the queue.\r\n * \r\n * @returns {number} The number of processes currently in the queue.\r\n */\r\n getQueueLength(): number {\r\n return this.#Queue.length;\r\n }\r\n\r\n /**\r\n * Internal method to execute processes in the queue.\r\n * - Processes are executed sequentially.\r\n * - Emits the `getResult` event with the process result and queue details after execution.\r\n * \r\n * @private\r\n * @async\r\n */\r\n async #Worker() {\r\n if (!this.#isProcessStartFlag\r\n || this.#Queue.length === 0\r\n || this.#ProcessState == ProcessState.UNDER_EXECUTION) return;\r\n this.#ProcessState = ProcessState.UNDER_EXECUTION;\r\n\r\n this.CurrentProcessId = this.#Queue[0].ProcessId || null;\r\n\r\n const ele = this.#Queue.shift();\r\n const res = await ele?.CallableFunction();\r\n const result = {\r\n value: res,\r\n processId: ele?.ProcessId,\r\n queueLength: this.#Queue.length,\r\n }\r\n this.emit('getResult', result);\r\n\r\n this.#ProcessState = ProcessState.IDLE;\r\n this.#Worker();\r\n }\r\n\r\n}"],"mappings":"skBAAA,OAAS,gBAAAA,MAAoB,SAA7B,IAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAyCaC,EAAN,cAAoBC,CAAa,CAAjC,kCAAAC,EAAA,KAAAJ,GAEHI,EAAA,KAAAP,EAAoB,CAAC,GACrBO,EAAA,KAAAN,EAA+B,IAC/BM,EAAA,KAAAL,KACA,sBAA2C,KAe3C,OAAOM,EAA6BC,EAAsC,CACtE,IAAMC,GAAsBD,GAAA,YAAAA,EAAS,aAAc,OAAYA,GAAA,YAAAA,EAAS,UAAaE,EAAA,KAAKX,GAAO,OAAS,EAC1G,GAAIS,GAAA,MAAAA,EAAS,WAAYA,GAAA,YAAAA,EAAS,YAAa,IAAKA,GAAA,YAAAA,EAAS,YAAa,EAAG,MAAM,IAAI,MAAM,oCAAoC,EACjI,OAAAA,GAAA,YAAAA,EAAS,YAAa,EAAgBE,EAAA,KAAKX,GAAO,QAAQ,CAAE,iBAAkBQ,EAAS,UAAWE,CAAG,CAAC,EAAIC,EAAA,KAAKX,GAAO,KAAK,CAAE,iBAAkBQ,EAAS,UAAWE,CAAG,CAAC,EACnKC,EAAA,KAAKV,IAAqBW,EAAA,KAAKT,EAAAC,GAAL,WACvB,CAAE,UAAWM,EAAI,YAAaC,EAAA,KAAKX,GAAO,MAAO,CAC5D,CASA,OAA2B,CA5E/B,IAAAa,EA6EQ,GAAIF,EAAA,KAAKX,GAAO,SAAW,EAAG,MAAM,IAAI,MAAM,oDAAoD,EAClG,GAAI,KAAK,mBAAqBW,EAAA,KAAKX,GAAOW,EAAA,KAAKX,GAAO,OAAS,CAAC,EAAE,UAC9D,MAAM,IAAI,MAAM,wDAAwD,KAAK,gBAAgB,wBAAwB,EAEzH,MAAO,CAAE,WADSa,EAAAF,EAAA,KAAKX,GAAO,IAAI,IAAhB,YAAAa,EAAmB,UACN,YAAaF,EAAA,KAAKX,GAAO,MAAO,CACnE,CAWA,SAASc,EAA+C,CACpD,GAAIH,EAAA,KAAKX,GAAO,SAAW,EAAG,MAAM,IAAI,MAAM,oDAAoD,EAClG,GAAI,KAAK,mBAAqBc,EAC1B,MAAM,IAAI,MAAM,wDAAwD,KAAK,gBAAgB,wBAAwB,EAEzH,MAAO,CAAE,UADSH,EAAA,KAAKX,GAAO,OAAOW,EAAA,KAAKX,GAAO,UAAWe,GAAMA,EAAE,YAAcD,CAAS,EAAG,CAAC,EAAE,CAAC,EAAE,UACrE,YAAaH,EAAA,KAAKX,GAAO,MAAO,CACnE,CAMA,SAAU,CACNgB,EAAA,KAAKf,EAAsB,IAC3BW,EAAA,KAAKT,EAAAC,GAAL,UACJ,CAMA,OAAQ,CACJY,EAAA,KAAKf,EAAsB,GAC/B,CAOA,qBAAsB,CAClB,OAAO,KAAK,gBAChB,CAOA,gBAAyB,CACrB,OAAOU,EAAA,KAAKX,GAAO,MACvB,CA+BJ,EA1HIA,EAAA,YACAC,EAAA,YACAC,EAAA,YAJGC,EAAA,YAuGGC,EAAO,UAAG,QAAAa,EAAA,sBACZ,GAAI,CAACN,EAAA,KAAKV,IACHU,EAAA,KAAKX,GAAO,SAAW,GACvBW,EAAA,KAAKT,IAAiB,EAA8B,OAC3Dc,EAAA,KAAKd,KAEL,KAAK,iBAAmBS,EAAA,KAAKX,GAAO,CAAC,EAAE,WAAa,KAEpD,IAAMkB,EAAMP,EAAA,KAAKX,GAAO,MAAM,EAExBmB,EAAS,CACX,MAFQ,MAAMD,GAAA,YAAAA,EAAK,mBAGnB,UAAWA,GAAA,YAAAA,EAAK,UAChB,YAAaP,EAAA,KAAKX,GAAO,MAC7B,EACA,KAAK,KAAK,YAAamB,CAAM,EAE7BH,EAAA,KAAKd,KACLU,EAAA,KAAKT,EAAAC,GAAL,UACJ","names":["EventEmitter","_Queue","_isProcessStartFlag","_ProcessState","_Queue_instances","Worker_fn","Queue","EventEmitter","__privateAdd","Process","Options","id","__privateGet","__privateMethod","_a","ProcessId","i","__privateSet","__async","ele","result"]}