X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Fworker%2Fabstract-worker.ts;h=e10521fcbc7808eeffeb778aa8dfb13ce0eb680e;hb=ae3ab61d14adc1f0511e8dea1f69a1d44e7effdf;hp=1b64dc4f4cfff7c769ade8ef2bbd100efa1885ab;hpb=c172526cd82999efbace45402e0bd6d9ae173963;p=poolifier.git diff --git a/src/worker/abstract-worker.ts b/src/worker/abstract-worker.ts index 1b64dc4f..e10521fc 100644 --- a/src/worker/abstract-worker.ts +++ b/src/worker/abstract-worker.ts @@ -18,14 +18,15 @@ import { KillBehaviors, type WorkerOptions } from './worker-options' import type { TaskAsyncFunction, TaskFunction, + TaskFunctionOperationResult, TaskFunctions, TaskSyncFunction } from './task-functions' - -interface TaskFunctionOperationReturnType { - status: boolean - error?: Error -} +import { + checkTaskFunctionName, + checkValidTaskFunctionEntry, + checkValidWorkerOptions +} from './utils' const DEFAULT_MAX_INACTIVE_TIME = 60000 const DEFAULT_WORKER_OPTIONS: WorkerOptions = { @@ -99,38 +100,18 @@ export abstract class AbstractWorker< this.checkTaskFunctions(taskFunctions) this.checkWorkerOptions(this.opts) if (!this.isMain) { + // Should be once() but Node.js on windows has a bug that prevents it from working this.getMainWorker().on('message', this.handleReadyMessage.bind(this)) } } private checkWorkerOptions (opts: WorkerOptions): void { + checkValidWorkerOptions(opts) this.opts = { ...DEFAULT_WORKER_OPTIONS, ...opts } - delete this.opts.async - } - - private checkValidTaskFunction ( - name: string, - fn: TaskFunction - ): void { - if (typeof name !== 'string') { - throw new TypeError( - 'A taskFunctions parameter object key is not a string' - ) - } - if (typeof name === 'string' && name.trim().length === 0) { - throw new TypeError( - 'A taskFunctions parameter object key is an empty string' - ) - } - if (typeof fn !== 'function') { - throw new TypeError( - 'A taskFunctions parameter object value is not a function' - ) - } } /** - * Checks if the `taskFunctions` parameter is passed to the constructor. + * Checks if the `taskFunctions` parameter is passed to the constructor and valid. * * @param taskFunctions - The task function(s) parameter that should be checked. */ @@ -154,7 +135,7 @@ export abstract class AbstractWorker< } else if (isPlainObject(taskFunctions)) { let firstEntry = true for (const [name, fn] of Object.entries(taskFunctions)) { - this.checkValidTaskFunction(name, fn) + checkValidTaskFunctionEntry(name, fn) const boundFn = fn.bind(this) if (firstEntry) { this.taskFunctions.set(DEFAULT_TASK_NAME, boundFn) @@ -178,9 +159,9 @@ export abstract class AbstractWorker< * @param name - The name of the task function to check. * @returns Whether the worker has a task function with the given name or not. */ - public hasTaskFunction (name: string): TaskFunctionOperationReturnType { + public hasTaskFunction (name: string): TaskFunctionOperationResult { try { - this.checkTaskFunctionName(name) + checkTaskFunctionName(name) } catch (error) { return { status: false, error: error as Error } } @@ -198,9 +179,9 @@ export abstract class AbstractWorker< public addTaskFunction ( name: string, fn: TaskFunction - ): TaskFunctionOperationReturnType { + ): TaskFunctionOperationResult { try { - this.checkTaskFunctionName(name) + checkTaskFunctionName(name) if (name === DEFAULT_TASK_NAME) { throw new Error( 'Cannot add a task function with the default reserved name' @@ -217,7 +198,7 @@ export abstract class AbstractWorker< this.taskFunctions.set(DEFAULT_TASK_NAME, boundFn) } this.taskFunctions.set(name, boundFn) - this.sendTaskFunctionsListToMainWorker() + this.sendTaskFunctionNamesToMainWorker() return { status: true } } catch (error) { return { status: false, error: error as Error } @@ -230,9 +211,9 @@ export abstract class AbstractWorker< * @param name - The name of the task function to remove. * @returns Whether the task function existed and was removed or not. */ - public removeTaskFunction (name: string): TaskFunctionOperationReturnType { + public removeTaskFunction (name: string): TaskFunctionOperationResult { try { - this.checkTaskFunctionName(name) + checkTaskFunctionName(name) if (name === DEFAULT_TASK_NAME) { throw new Error( 'Cannot remove the task function with the default reserved name' @@ -247,7 +228,7 @@ export abstract class AbstractWorker< ) } const deleteStatus = this.taskFunctions.delete(name) - this.sendTaskFunctionsListToMainWorker() + this.sendTaskFunctionNamesToMainWorker() return { status: deleteStatus } } catch (error) { return { status: false, error: error as Error } @@ -286,9 +267,9 @@ export abstract class AbstractWorker< * @param name - The name of the task function to use as default task function. * @returns Whether the default task function was set or not. */ - public setDefaultTaskFunction (name: string): TaskFunctionOperationReturnType { + public setDefaultTaskFunction (name: string): TaskFunctionOperationResult { try { - this.checkTaskFunctionName(name) + checkTaskFunctionName(name) if (name === DEFAULT_TASK_NAME) { throw new Error( 'Cannot set the default task function reserved name as the default task function' @@ -303,21 +284,13 @@ export abstract class AbstractWorker< DEFAULT_TASK_NAME, this.taskFunctions.get(name) as TaskFunction ) + this.sendTaskFunctionNamesToMainWorker() return { status: true } } catch (error) { return { status: false, error: error as Error } } } - private checkTaskFunctionName (name: string): void { - if (typeof name !== 'string') { - throw new TypeError('name parameter is not a string') - } - if (typeof name === 'string' && name.trim().length === 0) { - throw new TypeError('name parameter is an empty string') - } - } - /** * Handles the ready message sent by the main worker. * @@ -353,32 +326,40 @@ export abstract class AbstractWorker< protected handleTaskFunctionOperationMessage ( message: MessageValue ): void { - const { taskFunctionOperation, taskFunction, taskFunctionName } = message - let response!: TaskFunctionOperationReturnType - if (taskFunctionOperation === 'has') { - response = this.hasTaskFunction(taskFunctionName as string) - } else if (taskFunctionOperation === 'add') { - response = this.addTaskFunction( - taskFunctionName as string, - // eslint-disable-next-line @typescript-eslint/no-implied-eval, no-new-func - new Function(`return ${taskFunction as string}`)() as TaskFunction< - Data, - Response - > - ) - } else if (taskFunctionOperation === 'remove') { - response = this.removeTaskFunction(taskFunctionName as string) - } else if (taskFunctionOperation === 'default') { - response = this.setDefaultTaskFunction(taskFunctionName as string) + const { taskFunctionOperation, taskFunctionName, taskFunction } = message + let response!: TaskFunctionOperationResult + switch (taskFunctionOperation) { + case 'add': + response = this.addTaskFunction( + taskFunctionName as string, + // eslint-disable-next-line @typescript-eslint/no-implied-eval, no-new-func + new Function(`return ${taskFunction as string}`)() as TaskFunction< + Data, + Response + > + ) + break + case 'remove': + response = this.removeTaskFunction(taskFunctionName as string) + break + case 'default': + response = this.setDefaultTaskFunction(taskFunctionName as string) + break + default: + response = { status: false, error: new Error('Unknown task operation') } + break } this.sendToMainWorker({ taskFunctionOperation, taskFunctionOperationStatus: response.status, - workerError: { - name: taskFunctionName as string, - message: this.handleError(response.error as Error | string) - }, - workerId: this.id + taskFunctionName, + ...(!response.status && + response?.error != null && { + workerError: { + name: taskFunctionName as string, + message: this.handleError(response.error as Error | string) + } + }) }) } @@ -387,16 +368,16 @@ export abstract class AbstractWorker< * * @param message - The kill message. */ - protected handleKillMessage (message: MessageValue): void { + protected handleKillMessage (_message: MessageValue): void { this.stopCheckActive() if (isAsyncFunction(this.opts.killHandler)) { (this.opts.killHandler?.() as Promise) .then(() => { - this.sendToMainWorker({ kill: 'success', workerId: this.id }) - return null + this.sendToMainWorker({ kill: 'success' }) + return undefined }) .catch(() => { - this.sendToMainWorker({ kill: 'failure', workerId: this.id }) + this.sendToMainWorker({ kill: 'failure' }) }) .finally(() => { this.emitDestroy() @@ -406,9 +387,9 @@ export abstract class AbstractWorker< try { // eslint-disable-next-line @typescript-eslint/no-invalid-void-type this.opts.killHandler?.() as void - this.sendToMainWorker({ kill: 'success', workerId: this.id }) + this.sendToMainWorker({ kill: 'success' }) } catch { - this.sendToMainWorker({ kill: 'failure', workerId: this.id }) + this.sendToMainWorker({ kill: 'failure' }) } finally { this.emitDestroy() } @@ -460,7 +441,7 @@ export abstract class AbstractWorker< performance.now() - this.lastTaskTimestamp > (this.opts.maxInactiveTime ?? DEFAULT_MAX_INACTIVE_TIME) ) { - this.sendToMainWorker({ kill: this.opts.killBehavior, workerId: this.id }) + this.sendToMainWorker({ kill: this.opts.killBehavior }) } } @@ -487,12 +468,11 @@ export abstract class AbstractWorker< ): void /** - * Sends the list of task function names to the main worker. + * Sends task function names to the main worker. */ - protected sendTaskFunctionsListToMainWorker (): void { + protected sendTaskFunctionNamesToMainWorker (): void { this.sendToMainWorker({ - taskFunctionNames: this.listTaskFunctionNames(), - workerId: this.id + taskFunctionNames: this.listTaskFunctionNames() }) } @@ -510,7 +490,6 @@ export abstract class AbstractWorker< * Runs the given task. * * @param task - The task to execute. - * @throws {@link https://nodejs.org/api/errors.html#class-error} If the task function is not found. */ protected run (task: Task): void { const { name, taskId, data } = task @@ -522,7 +501,6 @@ export abstract class AbstractWorker< message: `Task function '${name as string}' not found`, data }, - workerId: this.id, taskId }) return @@ -552,7 +530,6 @@ export abstract class AbstractWorker< this.sendToMainWorker({ data: res, taskPerformance, - workerId: this.id, taskId }) } catch (error) { @@ -562,7 +539,6 @@ export abstract class AbstractWorker< message: this.handleError(error as Error | string), data }, - workerId: this.id, taskId }) } finally { @@ -588,10 +564,9 @@ export abstract class AbstractWorker< this.sendToMainWorker({ data: res, taskPerformance, - workerId: this.id, taskId }) - return null + return undefined }) .catch(error => { this.sendToMainWorker({ @@ -600,7 +575,6 @@ export abstract class AbstractWorker< message: this.handleError(error as Error | string), data }, - workerId: this.id, taskId }) })