From 0e4fa348298d36900560f7466f21f44090d2fe1b Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Tue, 3 Jan 2023 15:20:34 +0100 Subject: [PATCH] Optimize worker handlers calls by binding them to the current instance MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- .eslintrc.json | 18 +-- package-lock.json | 134 ++++++++++++++++++ package.json | 1 + src/charging-station/Bootstrap.ts | 6 +- src/charging-station/ChargingStationUtils.ts | 6 +- src/charging-station/ChargingStationWorker.ts | 2 +- .../ocpp/OCPPRequestService.ts | 8 +- src/types/Worker.ts | 4 +- src/utils/Utils.ts | 4 +- src/worker/WorkerAbstract.ts | 4 +- src/worker/WorkerDynamicPool.ts | 21 +-- src/worker/WorkerSet.ts | 32 +++-- src/worker/WorkerStaticPool.ts | 21 +-- 13 files changed, 204 insertions(+), 57 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 21d94099..27d9f65b 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -9,17 +9,9 @@ "ecmaVersion": 2020, "sourceType": "module" }, - "extends": [ - "eslint:recommended", - "plugin:import/recommended", - "plugin:jsdoc/recommended", - "plugin:prettier/recommended" - ], - "plugins": ["import", "jsdoc"], + "plugins": ["import"], + "extends": ["eslint:recommended", "plugin:import/recommended", "plugin:prettier/recommended"], "settings": { - "jsdoc": { - "mode": "typescript" - }, "import/resolver": { "typescript": { "project": "./tsconfig.json" @@ -153,14 +145,15 @@ "parserOptions": { "project": "./tsconfig.json" }, + "plugins": ["@typescript-eslint", "eslint-plugin-tsdoc"], "extends": [ "plugin:@typescript-eslint/eslint-recommended", "plugin:@typescript-eslint/recommended", "plugin:@typescript-eslint/recommended-requiring-type-checking", "plugin:import/typescript" ], - "plugins": ["@typescript-eslint"], "rules": { + "tsdoc/syntax": "warn", "@typescript-eslint/array-type": "off", "semi": "off", "@typescript-eslint/semi": ["error", "always"], @@ -176,7 +169,8 @@ }, { "files": ["**/*.js"], - "extends": "plugin:n/recommended", + "plugins": ["jsdoc"], + "extends": ["plugin:jsdoc/recommended", "plugin:n/recommended"], "rules": { "n/shebang": "off" } diff --git a/package-lock.json b/package-lock.json index 1e117e60..249a13fd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -57,6 +57,7 @@ "eslint-plugin-jsdoc": "^39.6.4", "eslint-plugin-n": "^15.6.0", "eslint-plugin-prettier": "^4.2.1", + "eslint-plugin-tsdoc": "^0.2.17", "expect": "^29.3.1", "husky": "^8.0.2", "lint-staged": "^13.1.0", @@ -1595,6 +1596,59 @@ "integrity": "sha512-EWUguj2kd7ldmrF9F+vI5hUOralPd+sdsUnYbRy33vZTuZkduC1shE9TtEMEjAQwyfyMb4ole5KtjF8MsnQOlA==", "dev": true }, + "node_modules/@microsoft/tsdoc": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz", + "integrity": "sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==", + "dev": true + }, + "node_modules/@microsoft/tsdoc-config": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.16.2.tgz", + "integrity": "sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==", + "dev": true, + "dependencies": { + "@microsoft/tsdoc": "0.14.2", + "ajv": "~6.12.6", + "jju": "~1.4.0", + "resolve": "~1.19.0" + } + }, + "node_modules/@microsoft/tsdoc-config/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@microsoft/tsdoc-config/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@microsoft/tsdoc-config/node_modules/resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "dependencies": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/@mikro-orm/cli": { "version": "5.6.3", "resolved": "https://registry.npmjs.org/@mikro-orm/cli/-/cli-5.6.3.tgz", @@ -6659,6 +6713,16 @@ } } }, + "node_modules/eslint-plugin-tsdoc": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.17.tgz", + "integrity": "sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA==", + "dev": true, + "dependencies": { + "@microsoft/tsdoc": "0.14.2", + "@microsoft/tsdoc-config": "0.16.2" + } + }, "node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -9390,6 +9454,12 @@ "node": ">= 10.13.0" } }, + "node_modules/jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", + "dev": true + }, "node_modules/js-sdsl": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.4.tgz", @@ -18822,6 +18892,54 @@ "integrity": "sha512-EWUguj2kd7ldmrF9F+vI5hUOralPd+sdsUnYbRy33vZTuZkduC1shE9TtEMEjAQwyfyMb4ole5KtjF8MsnQOlA==", "dev": true }, + "@microsoft/tsdoc": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz", + "integrity": "sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==", + "dev": true + }, + "@microsoft/tsdoc-config": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.16.2.tgz", + "integrity": "sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==", + "dev": true, + "requires": { + "@microsoft/tsdoc": "0.14.2", + "ajv": "~6.12.6", + "jju": "~1.4.0", + "resolve": "~1.19.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "requires": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + } + } + } + }, "@mikro-orm/cli": { "version": "5.6.3", "resolved": "https://registry.npmjs.org/@mikro-orm/cli/-/cli-5.6.3.tgz", @@ -22814,6 +22932,16 @@ "prettier-linter-helpers": "^1.0.0" } }, + "eslint-plugin-tsdoc": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.17.tgz", + "integrity": "sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA==", + "dev": true, + "requires": { + "@microsoft/tsdoc": "0.14.2", + "@microsoft/tsdoc-config": "0.16.2" + } + }, "eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -24832,6 +24960,12 @@ "supports-color": "^7.0.0" } }, + "jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", + "dev": true + }, "js-sdsl": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.4.tgz", diff --git a/package.json b/package.json index 9ac30748..07f743a4 100644 --- a/package.json +++ b/package.json @@ -124,6 +124,7 @@ "eslint-plugin-jsdoc": "^39.6.4", "eslint-plugin-n": "^15.6.0", "eslint-plugin-prettier": "^4.2.1", + "eslint-plugin-tsdoc": "^0.2.17", "expect": "^29.3.1", "husky": "^8.0.2", "lint-staged": "^13.1.0", diff --git a/src/charging-station/Bootstrap.ts b/src/charging-station/Bootstrap.ts index 329c5546..64b35d53 100644 --- a/src/charging-station/Bootstrap.ts +++ b/src/charging-station/Bootstrap.ts @@ -19,6 +19,7 @@ import { } from '../types/ChargingStationWorker'; import type { StationTemplateUrl } from '../types/ConfigurationData'; import type { Statistics } from '../types/Statistics'; +import type { MessageHandler } from '../types/Worker'; import Configuration from '../utils/Configuration'; import logger from '../utils/Logger'; import Utils from '../utils/Utils'; @@ -178,10 +179,7 @@ export class Bootstrap { poolOptions: { workerChoiceStrategy: Configuration.getWorker().poolStrategy, }, - messageHandler: this.messageHandler.bind(this) as ( - this: Worker, - msg: ChargingStationWorkerMessage - ) => void, + messageHandler: this.messageHandler.bind(this) as MessageHandler, } )); } diff --git a/src/charging-station/ChargingStationUtils.ts b/src/charging-station/ChargingStationUtils.ts index f7f0d4aa..fd0dd765 100644 --- a/src/charging-station/ChargingStationUtils.ts +++ b/src/charging-station/ChargingStationUtils.ts @@ -284,9 +284,9 @@ export class ChargingStationUtils { /** * Charging profiles should already be sorted by connectorId and stack level (highest stack level has priority) * - * @param {ChargingProfile[]} chargingProfiles - * @param {string} logPrefix - * @returns {{ limit, matchingChargingProfile }} + * @param chargingProfiles - + * @param logPrefix - + * @returns */ public static getLimitFromChargingProfiles( chargingProfiles: ChargingProfile[], diff --git a/src/charging-station/ChargingStationWorker.ts b/src/charging-station/ChargingStationWorker.ts index 58f1327a..66f557d6 100644 --- a/src/charging-station/ChargingStationWorker.ts +++ b/src/charging-station/ChargingStationWorker.ts @@ -40,7 +40,7 @@ function addMessageListener(): void { /** * Create and start a charging station instance * - * @param data workerData + * @param data - workerData */ function startChargingStation(data: ChargingStationWorkerData): void { const station = new ChargingStation(data.index, data.templateFile); diff --git a/src/charging-station/ocpp/OCPPRequestService.ts b/src/charging-station/ocpp/OCPPRequestService.ts index 6c241042..da39fb9e 100644 --- a/src/charging-station/ocpp/OCPPRequestService.ts +++ b/src/charging-station/ocpp/OCPPRequestService.ts @@ -233,8 +233,8 @@ export default abstract class OCPPRequestService { /** * Function that will receive the request's response * - * @param payload - * @param requestPayload + * @param payload - + * @param requestPayload - */ function responseCallback(payload: JsonType, requestPayload: JsonType): void { if (chargingStation.getEnableStatistics() === true) { @@ -265,8 +265,8 @@ export default abstract class OCPPRequestService { /** * Function that will receive the request's error response * - * @param error - * @param requestStatistic + * @param error - + * @param requestStatistic - */ function errorCallback(error: OCPPError, requestStatistic = true): void { if (requestStatistic === true && chargingStation.getEnableStatistics() === true) { diff --git a/src/types/Worker.ts b/src/types/Worker.ts index a387ceef..12c2ea36 100644 --- a/src/types/Worker.ts +++ b/src/types/Worker.ts @@ -8,6 +8,8 @@ export enum WorkerProcessType { STATIC_POOL = 'staticPool', } +export type MessageHandler = (this: T, message: unknown) => void; + export type WorkerOptions = { workerStartDelay?: number; elementStartDelay?: number; @@ -15,7 +17,7 @@ export type WorkerOptions = { poolMinSize?: number; elementsPerWorker?: number; poolOptions?: PoolOptions; - messageHandler?: (this: Worker, message: unknown) => void; + messageHandler?: MessageHandler; }; export type WorkerData = Record; diff --git a/src/utils/Utils.ts b/src/utils/Utils.ts index f28de981..94fa3d18 100644 --- a/src/utils/Utils.ts +++ b/src/utils/Utils.ts @@ -228,7 +228,7 @@ export default class Utils { `${str.slice(0, pos)}${subStr}${str.slice(pos)}`; /** - * @param [retryNumber=0] + * @param retryNumber - the number of retries that have already been attempted * @returns delay in milliseconds */ public static exponentialDelay(retryNumber = 0): number { @@ -288,7 +288,7 @@ export default class Utils { /** * Convert websocket error code to human readable string message * - * @param code websocket error code + * @param code - websocket error code * @returns human readable string message */ public static getWebSocketCloseEventStatusString(code: number): string { diff --git a/src/worker/WorkerAbstract.ts b/src/worker/WorkerAbstract.ts index 27f947d1..356e1a7a 100644 --- a/src/worker/WorkerAbstract.ts +++ b/src/worker/WorkerAbstract.ts @@ -12,8 +12,8 @@ export default abstract class WorkerAbstract { /** * `WorkerAbstract` constructor. * - * @param workerScript - * @param workerOptions + * @param workerScript - + * @param workerOptions - */ constructor( workerScript: string, diff --git a/src/worker/WorkerDynamicPool.ts b/src/worker/WorkerDynamicPool.ts index 68ba56e9..5e235879 100644 --- a/src/worker/WorkerDynamicPool.ts +++ b/src/worker/WorkerDynamicPool.ts @@ -1,4 +1,6 @@ -import { DynamicThreadPool } from 'poolifier'; +import type { Worker } from 'worker_threads'; + +import { DynamicThreadPool, type ErrorHandler, type ExitHandler } from 'poolifier'; import type { WorkerData, WorkerOptions } from '../types/Worker'; import Utils from '../utils/Utils'; @@ -11,15 +13,18 @@ export default class WorkerDynamicPool extends WorkerAbstract { /** * Create a new `WorkerDynamicPool`. * - * @param workerScript - * @param workerOptions + * @param workerScript - + * @param workerOptions - */ constructor(workerScript: string, workerOptions?: WorkerOptions) { super(workerScript, workerOptions); - this.workerOptions.poolOptions.errorHandler = - this.workerOptions?.poolOptions?.errorHandler ?? WorkerUtils.defaultErrorHandler; - this.workerOptions.poolOptions.exitHandler = - this.workerOptions?.poolOptions?.exitHandler ?? WorkerUtils.defaultExitHandler; + this.workerOptions.poolOptions.errorHandler = ( + this.workerOptions?.poolOptions?.errorHandler ?? WorkerUtils.defaultErrorHandler + ).bind(this) as ErrorHandler; + this.workerOptions.poolOptions.exitHandler = ( + this.workerOptions?.poolOptions?.exitHandler ?? WorkerUtils.defaultExitHandler + ).bind(this) as ExitHandler; + this.workerOptions.poolOptions.messageHandler.bind(this); this.pool = new DynamicThreadPool( this.workerOptions.poolMinSize, this.workerOptions.poolMaxSize, @@ -56,7 +61,7 @@ export default class WorkerDynamicPool extends WorkerAbstract { /** * - * @param elementData + * @param elementData - * @returns * @public */ diff --git a/src/worker/WorkerSet.ts b/src/worker/WorkerSet.ts index f41752fc..e69e9285 100644 --- a/src/worker/WorkerSet.ts +++ b/src/worker/WorkerSet.ts @@ -2,29 +2,29 @@ import { Worker } from 'worker_threads'; -import { WorkerData, WorkerMessageEvents, WorkerOptions, WorkerSetElement } from '../types/Worker'; +import { + type MessageHandler, + type WorkerData, + WorkerMessageEvents, + type WorkerOptions, + type WorkerSetElement, +} from '../types/Worker'; import Utils from '../utils/Utils'; import WorkerAbstract from './WorkerAbstract'; import { WorkerUtils } from './WorkerUtils'; export default class WorkerSet extends WorkerAbstract { private readonly workerSet: Set; - private readonly messageHandler: (message: unknown) => void; /** * Create a new `WorkerSet`. * - * @param workerScript - * @param workerOptions + * @param workerScript - + * @param workerOptions - */ constructor(workerScript: string, workerOptions?: WorkerOptions) { super(workerScript, workerOptions); this.workerSet = new Set(); - this.messageHandler = - workerOptions?.messageHandler ?? - (() => { - /* This is intentional */ - }); } get size(): number { @@ -37,7 +37,7 @@ export default class WorkerSet extends WorkerAbstract { /** * - * @param elementData + * @param elementData - * @returns * @public */ @@ -89,8 +89,16 @@ export default class WorkerSet extends WorkerAbstract { */ private async startWorker(): Promise { const worker = new Worker(this.workerScript); - worker.on('message', this.messageHandler); - worker.on('error', WorkerUtils.defaultErrorHandler); + worker.on( + 'message', + ( + this.workerOptions?.messageHandler ?? + (() => { + /* This is intentional */ + }) + ).bind(this) as MessageHandler + ); + worker.on('error', WorkerUtils.defaultErrorHandler.bind(this) as (err: Error) => void); worker.on('exit', (code) => { WorkerUtils.defaultExitHandler(code); this.workerSet.delete(this.getWorkerSetElementByWorker(worker)); diff --git a/src/worker/WorkerStaticPool.ts b/src/worker/WorkerStaticPool.ts index 23112a6c..c3209c25 100644 --- a/src/worker/WorkerStaticPool.ts +++ b/src/worker/WorkerStaticPool.ts @@ -1,4 +1,6 @@ -import { FixedThreadPool } from 'poolifier'; +import type { Worker } from 'worker_threads'; + +import { type ErrorHandler, type ExitHandler, FixedThreadPool } from 'poolifier'; import type { WorkerData, WorkerOptions } from '../types/Worker'; import Utils from '../utils/Utils'; @@ -11,15 +13,18 @@ export default class WorkerStaticPool extends WorkerAbstract { /** * Create a new `WorkerStaticPool`. * - * @param workerScript - * @param workerOptions + * @param workerScript - + * @param workerOptions - */ constructor(workerScript: string, workerOptions?: WorkerOptions) { super(workerScript, workerOptions); - this.workerOptions.poolOptions.errorHandler = - this.workerOptions?.poolOptions?.errorHandler ?? WorkerUtils.defaultErrorHandler; - this.workerOptions.poolOptions.exitHandler = - this.workerOptions?.poolOptions?.exitHandler ?? WorkerUtils.defaultExitHandler; + this.workerOptions.poolOptions.errorHandler = ( + this.workerOptions?.poolOptions?.errorHandler ?? WorkerUtils.defaultErrorHandler + ).bind(this) as ErrorHandler; + this.workerOptions.poolOptions.exitHandler = ( + this.workerOptions?.poolOptions?.exitHandler ?? WorkerUtils.defaultExitHandler + ).bind(this) as ExitHandler; + this.workerOptions.poolOptions.messageHandler.bind(this); this.pool = new FixedThreadPool( this.workerOptions.poolMaxSize, this.workerScript, @@ -55,7 +60,7 @@ export default class WorkerStaticPool extends WorkerAbstract { /** * - * @param elementData + * @param elementData - * @returns * @public */ -- 2.34.1