X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fpools%2Fabstract-pool.ts;h=0069fb7fadc61c95196982365adfaf60561069fa;hb=c05f0d5094264db0ff50636e794201e60ba7f448;hp=0f18de3fba17f63f0f6b0b8c76697852cc085baa;hpb=c4dfd49dbde2f3af0adc4a33d582b1c653f859b5;p=poolifier.git diff --git a/src/pools/abstract-pool.ts b/src/pools/abstract-pool.ts index 0f18de3f..0069fb7f 100644 --- a/src/pools/abstract-pool.ts +++ b/src/pools/abstract-pool.ts @@ -4,11 +4,12 @@ import type { MessageValue, PromiseResponseWrapper } from '../utility-types' import { DEFAULT_WORKER_CHOICE_STRATEGY_OPTIONS, EMPTY_FUNCTION, + isKillBehavior, isPlainObject, median, round } from '../utils' -import { KillBehaviors, isKillBehavior } from '../worker/worker-options' +import { KillBehaviors } from '../worker/worker-options' import { CircularArray } from '../circular-array' import { Queue } from '../queue' import { @@ -20,7 +21,8 @@ import { type PoolType, PoolTypes, type TasksQueueOptions, - type WorkerType + type WorkerType, + WorkerTypes } from './pool' import type { IWorker, @@ -251,7 +253,10 @@ export abstract class AbstractPool< worker: this.worker, minSize: this.minSize, maxSize: this.maxSize, - utilization: round(this.utilization), + ...(this.workerChoiceStrategyContext.getTaskStatisticsRequirements() + .runTime.aggregate && + this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime + .aggregate && { utilization: round(this.utilization) }), workerNodes: this.workerNodes.length, idleWorkerNodes: this.workerNodes.reduce( (accumulator, workerNode) => @@ -344,6 +349,17 @@ export abstract class AbstractPool< */ protected abstract get maxSize (): number + /** + * Get the worker given its id. + * + * @param workerId - The worker id. + * @returns The worker if found in the pool worker nodes, `undefined` otherwise. + */ + private getWorkerById (workerId: number): Worker | undefined { + return this.workerNodes.find(workerNode => workerNode.info.id === workerId) + ?.worker + } + /** * Gets the given worker its worker node key. * @@ -801,33 +817,55 @@ export abstract class AbstractPool< */ protected workerListener (): (message: MessageValue) => void { return message => { - if (message.id != null) { + if (message.workerId != null && message.started != null) { + // Worker started message received + this.handleWorkerStartedMessage(message) + } else if (message.id != null) { // Task execution response received - const promiseResponse = this.promiseResponseMap.get(message.id) - if (promiseResponse != null) { - if (message.taskError != null) { - if (this.emitter != null) { - this.emitter.emit(PoolEvents.taskError, message.taskError) - } - promiseResponse.reject(message.taskError.message) - } else { - promiseResponse.resolve(message.data as Response) - } - this.afterTaskExecutionHook(promiseResponse.worker, message) - this.promiseResponseMap.delete(message.id) - const workerNodeKey = this.getWorkerNodeKey(promiseResponse.worker) - if ( - this.opts.enableTasksQueue === true && - this.tasksQueueSize(workerNodeKey) > 0 - ) { - this.executeTask( - workerNodeKey, - this.dequeueTask(workerNodeKey) as Task - ) - } - this.workerChoiceStrategyContext.update(workerNodeKey) + this.handleTaskExecutionResponse(message) + } + } + } + + private handleWorkerStartedMessage (message: MessageValue): void { + // Worker started message received + const worker = this.getWorkerById(message.workerId as number) + if (worker != null) { + this.workerNodes[this.getWorkerNodeKey(worker)].info.started = + message.started as boolean + } else { + throw new Error( + `Worker started message received from unknown worker '${ + message.workerId as number + }'` + ) + } + } + + private handleTaskExecutionResponse (message: MessageValue): void { + const promiseResponse = this.promiseResponseMap.get(message.id as string) + if (promiseResponse != null) { + if (message.taskError != null) { + if (this.emitter != null) { + this.emitter.emit(PoolEvents.taskError, message.taskError) } + promiseResponse.reject(message.taskError.message) + } else { + promiseResponse.resolve(message.data as Response) + } + this.afterTaskExecutionHook(promiseResponse.worker, message) + this.promiseResponseMap.delete(message.id as string) + const workerNodeKey = this.getWorkerNodeKey(promiseResponse.worker) + if ( + this.opts.enableTasksQueue === true && + this.tasksQueueSize(workerNodeKey) > 0 + ) { + this.executeTask( + workerNodeKey, + this.dequeueTask(workerNodeKey) as Task + ) } + this.workerChoiceStrategyContext.update(workerNodeKey) } } @@ -864,6 +902,7 @@ export abstract class AbstractPool< private pushWorkerNode (worker: Worker): number { this.workerNodes.push({ worker, + info: { id: this.getWorkerId(worker), started: true }, usage: this.getWorkerUsage(), tasksQueue: new Queue>() }) @@ -875,22 +914,39 @@ export abstract class AbstractPool< return this.workerNodes.length } + /** + * Gets the worker id. + * + * @param worker - The worker. + * @returns The worker id. + */ + private getWorkerId (worker: Worker): number | undefined { + if (this.worker === WorkerTypes.thread) { + return worker.threadId + } else if (this.worker === WorkerTypes.cluster) { + return worker.id + } + } + // /** // * Sets the given worker in the pool worker nodes. // * // * @param workerNodeKey - The worker node key. // * @param worker - The worker. + // * @param workerInfo - The worker info. // * @param workerUsage - The worker usage. // * @param tasksQueue - The worker task queue. // */ // private setWorkerNode ( // workerNodeKey: number, // worker: Worker, + // workerInfo: WorkerInfo, // workerUsage: WorkerUsage, // tasksQueue: Queue> // ): void { // this.workerNodes[workerNodeKey] = { // worker, + // info: workerInfo, // usage: workerUsage, // tasksQueue // }