* The start timestamp of the pool.
*/
private readonly startTimestamp
+ /**
+ * The task function names.
+ */
+ private taskFunctions!: string[]
/**
* Constructs a new poolifier pool.
* @throws {@link https://nodejs.org/api/errors.html#class-error} If the worker id is invalid.
*/
private checkMessageWorkerId (message: MessageValue<Response>): void {
- if (
+ if (message.workerId == null) {
+ throw new Error('Worker message received without worker id')
+ } else if (
message.workerId != null &&
this.getWorkerNodeKeyByWorkerId(message.workerId) === -1
) {
}
for (const [workerNodeKey, workerNode] of this.workerNodes.entries()) {
workerNode.resetUsage()
- this.sendWorkerStatisticsMessageToWorker(workerNodeKey)
+ this.sendStatisticsMessageToWorker(workerNodeKey)
}
}
}
}
+ /** @inheritDoc */
+ public listTaskFunctions (): string[] {
+ if (this.taskFunctions != null) {
+ return this.taskFunctions
+ } else {
+ return []
+ }
+ }
+
/** @inheritDoc */
public async execute (
data?: Data,
if (name != null && typeof name !== 'string') {
reject(new TypeError('name argument must be a string'))
}
+ if (
+ name != null &&
+ typeof name === 'string' &&
+ name.trim().length === 0
+ ) {
+ reject(new TypeError('name argument must not be an empty string'))
+ }
+ if (
+ name != null &&
+ this.taskFunctions != null &&
+ !this.taskFunctions.includes(name)
+ ) {
+ reject(
+ new Error(`Task function '${name}' is not registered in the pool`)
+ )
+ }
if (transferList != null && !Array.isArray(transferList)) {
reject(new TypeError('transferList argument must be an array'))
}
await this.destroyWorkerNode(workerNodeKey)
})
)
+ this.emitter?.emit(PoolEvents.destroy)
+ }
+
+ protected async sendKillMessageToWorker (
+ workerNodeKey: number,
+ workerId: number
+ ): Promise<void> {
+ await new Promise<void>((resolve, reject) => {
+ this.registerWorkerMessageListener(workerNodeKey, (message) => {
+ if (message.kill === 'success') {
+ resolve()
+ } else if (message.kill === 'failure') {
+ reject(new Error(`Worker ${workerId} kill message handling failed`))
+ }
+ })
+ this.sendToWorker(workerNodeKey, { kill: true, workerId })
+ })
}
/**
protected createAndSetupWorkerNode (): number {
const worker = this.createWorker()
+ worker.on('online', this.opts.onlineHandler ?? EMPTY_FUNCTION)
worker.on('message', this.opts.messageHandler ?? EMPTY_FUNCTION)
worker.on('error', this.opts.errorHandler ?? EMPTY_FUNCTION)
worker.on('error', (error) => {
this.redistributeQueuedTasks(workerNodeKey)
}
})
- worker.on('online', this.opts.onlineHandler ?? EMPTY_FUNCTION)
worker.on('exit', this.opts.exitHandler ?? EMPTY_FUNCTION)
worker.once('exit', () => {
this.removeWorkerNode(worker)
// Kill message received from worker
if (
isKillBehavior(KillBehaviors.HARD, message.kill) ||
- (message.kill != null &&
+ (isKillBehavior(KillBehaviors.SOFT, message.kill) &&
((this.opts.enableTasksQueue === false &&
workerUsage.tasks.executing === 0) ||
(this.opts.enableTasksQueue === true &&
workerUsage.tasks.executing === 0 &&
this.tasksQueueSize(localWorkerNodeKey) === 0)))
) {
- this.destroyWorkerNode(localWorkerNodeKey).catch(EMPTY_FUNCTION)
+ this.destroyWorkerNode(localWorkerNodeKey).catch((error) => {
+ this.emitter?.emit(PoolEvents.error, error)
+ })
}
})
const workerInfo = this.getWorkerInfo(workerNodeKey)
this.registerWorkerMessageListener(workerNodeKey, this.workerListener())
// Send the startup message to worker.
this.sendStartupMessageToWorker(workerNodeKey)
- // Send the worker statistics message to worker.
- this.sendWorkerStatisticsMessageToWorker(workerNodeKey)
+ // Send the statistics message to worker.
+ this.sendStatisticsMessageToWorker(workerNodeKey)
}
/**
protected abstract sendStartupMessageToWorker (workerNodeKey: number): void
/**
- * Sends the worker statistics message to worker given its worker node key.
+ * Sends the statistics message to worker given its worker node key.
*
* @param workerNodeKey - The worker node key.
*/
- private sendWorkerStatisticsMessageToWorker (workerNodeKey: number): void {
+ private sendStatisticsMessageToWorker (workerNodeKey: number): void {
this.sendToWorker(workerNodeKey, {
statistics: {
runTime:
} else if (message.taskId != null) {
// Task execution response received from worker
this.handleTaskExecutionResponse(message)
+ } else if (message.taskFunctions != null) {
+ // Task functions message received from worker
+ this.taskFunctions = message.taskFunctions
}
}
}