+ private checkAndEmitEvents (): void {
+ if (this.opts.enableEvents === true) {
+ if (this.busy) {
+ this.emitter?.emit(PoolEvents.busy)
+ }
+ if (this.type === PoolType.DYNAMIC && this.full) {
+ this.emitter?.emit(PoolEvents.full)
+ }
+ }
+ }
+
+ /**
+ * Sets the given worker node its tasks usage in the pool.
+ *
+ * @param workerNode - The worker node.
+ * @param tasksUsage - The worker node tasks usage.
+ */
+ private setWorkerNodeTasksUsage (
+ workerNode: WorkerNode<Worker, Data>,
+ tasksUsage: TasksUsage
+ ): void {
+ workerNode.tasksUsage = tasksUsage
+ }
+
+ /**
+ * Gets the given worker its tasks usage in the pool.
+ *
+ * @param worker - The worker.
+ * @throws Error if the worker is not found in the pool worker nodes.
+ * @returns The worker tasks usage.
+ */
+ private getWorkerTasksUsage (worker: Worker): TasksUsage {
+ const workerNodeKey = this.getWorkerNodeKey(worker)
+ if (workerNodeKey !== -1) {
+ return this.workerNodes[workerNodeKey].tasksUsage
+ }
+ throw new Error('Worker could not be found in the pool worker nodes')
+ }
+
+ /**
+ * Pushes the given worker in the pool worker nodes.
+ *
+ * @param worker - The worker.
+ * @returns The worker nodes length.
+ */
+ private pushWorkerNode (worker: Worker): number {
+ return this.workerNodes.push({
+ worker,
+ tasksUsage: {
+ run: 0,
+ running: 0,
+ runTime: 0,
+ runTimeHistory: new CircularArray(),
+ avgRunTime: 0,
+ medRunTime: 0,
+ error: 0
+ },
+ tasksQueue: new Queue<Task<Data>>()
+ })
+ }
+
+ /**
+ * Sets the given worker in the pool worker nodes.
+ *
+ * @param workerNodeKey - The worker node key.
+ * @param worker - The worker.
+ * @param tasksUsage - The worker tasks usage.
+ * @param tasksQueue - The worker task queue.
+ */
+ private setWorkerNode (
+ workerNodeKey: number,
+ worker: Worker,
+ tasksUsage: TasksUsage,
+ tasksQueue: Queue<Task<Data>>
+ ): void {
+ this.workerNodes[workerNodeKey] = {
+ worker,
+ tasksUsage,
+ tasksQueue
+ }
+ }
+
+ /**
+ * Removes the given worker from the pool worker nodes.
+ *
+ * @param worker - The worker.
+ */
+ private removeWorkerNode (worker: Worker): void {
+ const workerNodeKey = this.getWorkerNodeKey(worker)
+ this.workerNodes.splice(workerNodeKey, 1)
+ this.workerChoiceStrategyContext.remove(workerNodeKey)
+ }
+
+ private executeTask (workerNodeKey: number, task: Task<Data>): void {
+ this.beforeTaskExecutionHook(workerNodeKey)
+ this.sendToWorker(this.workerNodes[workerNodeKey].worker, task)
+ }
+
+ private enqueueTask (workerNodeKey: number, task: Task<Data>): number {
+ return this.workerNodes[workerNodeKey].tasksQueue.enqueue(task)
+ }
+
+ private dequeueTask (workerNodeKey: number): Task<Data> | undefined {
+ return this.workerNodes[workerNodeKey].tasksQueue.dequeue()
+ }
+
+ private tasksQueueSize (workerNodeKey: number): number {
+ return this.workerNodes[workerNodeKey].tasksQueue.size
+ }
+
+ private flushTasksQueue (workerNodeKey: number): void {
+ if (this.tasksQueueSize(workerNodeKey) > 0) {
+ for (let i = 0; i < this.tasksQueueSize(workerNodeKey); i++) {
+ this.executeTask(
+ workerNodeKey,
+ this.dequeueTask(workerNodeKey) as Task<Data>
+ )
+ }
+ }
+ }
+
+ private flushTasksQueueByWorker (worker: Worker): void {
+ const workerNodeKey = this.getWorkerNodeKey(worker)
+ this.flushTasksQueue(workerNodeKey)
+ }
+
+ private flushTasksQueues (): void {
+ for (const [workerNodeKey] of this.workerNodes.entries()) {
+ this.flushTasksQueue(workerNodeKey)