From aee467366d8c393b79e7af82c6a7ab12338ee64e Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Fri, 7 Apr 2023 23:15:34 +0200 Subject: [PATCH] refactor: add PoolEvents/PoolEvent types MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- CHANGELOG.md | 6 +- README.md | 8 +- examples/dynamicExample.js | 6 +- examples/fixedExample.js | 4 +- package.json | 2 +- pnpm-lock.yaml | 122 +++++++++--------- src/index.ts | 3 +- src/pools/abstract-pool.ts | 28 ++-- src/pools/pool.ts | 13 ++ .../worker-choice-strategy-context.ts | 5 +- src/utility-types.ts | 4 +- src/worker/abstract-worker.ts | 68 +++++----- tests/pools/abstract/abstract-pool.test.js | 7 +- tests/pools/cluster/dynamic.test.js | 4 +- tests/pools/cluster/fixed.test.js | 6 +- tests/pools/thread/dynamic.test.js | 4 +- tests/pools/thread/fixed.test.js | 6 +- 17 files changed, 163 insertions(+), 133 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 58302171..97c416b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,9 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Add `PoolEvents` enumeration and `PoolEvent` type. + ### Fixed -- fix: destroy worker only on check alive. +- fix: destroy worker only on alive check. ## [2.4.3] - 2023-04-07 diff --git a/README.md b/README.md index dc956759..49f24ef5 100644 --- a/README.md +++ b/README.md @@ -113,22 +113,22 @@ Instantiate your pool based on your needed : ```js 'use strict' -const { FixedThreadPool, DynamicThreadPool } = require('poolifier') +const { DynamicThreadPool, FixedThreadPool, PoolEvents } = require('poolifier') // a fixed worker-threads pool const pool = new FixedThreadPool(15, './yourWorker.js', { errorHandler: (e) => console.error(e), onlineHandler: () => console.log('worker is online') }) -pool.emitter.on('busy', () => console.log('Pool is busy')) +pool.emitter.on(PoolEvents.busy, () => console.log('Pool is busy')) // or a dynamic worker-threads pool const pool = new DynamicThreadPool(10, 100, './yourWorker.js', { errorHandler: (e) => console.error(e), onlineHandler: () => console.log('worker is online') }) -pool.emitter.on('full', () => console.log('Pool is full')) -pool.emitter.on('busy', () => console.log('Pool is busy')) +pool.emitter.on(PoolEvents.full, () => console.log('Pool is full')) +pool.emitter.on(PoolEvents.busy, () => console.log('Pool is busy')) // the execute method signature is the same for both implementations, // so you can easy switch from one to another diff --git a/examples/dynamicExample.js b/examples/dynamicExample.js index 79f73c11..e1d9b503 100644 --- a/examples/dynamicExample.js +++ b/examples/dynamicExample.js @@ -1,4 +1,4 @@ -const { DynamicThreadPool } = require('poolifier') +const { DynamicThreadPool, PoolEvents } = require('poolifier') let resolved = 0 let poolFull = 0 let poolBusy = 0 @@ -6,8 +6,8 @@ const pool = new DynamicThreadPool(10, 20, './yourWorker.js', { errorHandler: e => console.error(e), onlineHandler: () => console.log('worker is online') }) -pool.emitter.on('full', () => poolFull++) -pool.emitter.on('busy', () => poolBusy++) +pool.emitter.on(PoolEvents.full, () => poolFull++) +pool.emitter.on(PoolEvents.busy, () => poolBusy++) const start = Date.now() const iterations = 1000 diff --git a/examples/fixedExample.js b/examples/fixedExample.js index c6ea8848..d10c2062 100644 --- a/examples/fixedExample.js +++ b/examples/fixedExample.js @@ -1,11 +1,11 @@ -const { FixedThreadPool } = require('poolifier') +const { FixedThreadPool, PoolEvents } = require('poolifier') let resolved = 0 let poolBusy = 0 const pool = new FixedThreadPool(15, './yourWorker.js', { errorHandler: e => console.error(e), onlineHandler: () => console.log('worker is online') }) -pool.emitter.on('busy', () => poolBusy++) +pool.emitter.on(PoolEvents.busy, () => poolBusy++) const start = Date.now() const iterations = 1000 diff --git a/package.json b/package.json index 8bcd8a8e..d7befe0a 100644 --- a/package.json +++ b/package.json @@ -133,6 +133,6 @@ "source-map-support": "^0.5.21", "ts-standard": "^12.0.2", "typedoc": "^0.23.28", - "typescript": "^5.0.3" + "typescript": "^5.0.4" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 06dadc57..933753fb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,16 +18,16 @@ devDependencies: version: 0.4.0(rollup@3.20.2) '@rollup/plugin-typescript': specifier: ^11.1.0 - version: 11.1.0(rollup@3.20.2)(typescript@5.0.3) + version: 11.1.0(rollup@3.20.2)(typescript@5.0.4) '@types/node': specifier: ^18.15.11 version: 18.15.11 '@typescript-eslint/eslint-plugin': specifier: ^5.57.1 - version: 5.57.1(@typescript-eslint/parser@5.57.1)(eslint@8.37.0)(typescript@5.0.3) + version: 5.57.1(@typescript-eslint/parser@5.57.1)(eslint@8.37.0)(typescript@5.0.4) '@typescript-eslint/parser': specifier: ^5.57.1 - version: 5.57.1(eslint@8.37.0)(typescript@5.0.3) + version: 5.57.1(eslint@8.37.0)(typescript@5.0.4) benny: specifier: ^3.7.1 version: 3.7.1 @@ -42,7 +42,7 @@ devDependencies: version: 17.0.0(eslint-plugin-import@2.27.5)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.37.0) eslint-config-standard-with-typescript: specifier: ^34.0.1 - version: 34.0.1(@typescript-eslint/eslint-plugin@5.57.1)(eslint-plugin-import@2.27.5)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.37.0)(typescript@5.0.3) + version: 34.0.1(@typescript-eslint/eslint-plugin@5.57.1)(eslint-plugin-import@2.27.5)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.37.0)(typescript@5.0.4) eslint-define-config: specifier: ^1.17.0 version: 1.17.0 @@ -90,7 +90,7 @@ devDependencies: version: 2.8.7 prettier-plugin-organize-imports: specifier: ^3.2.2 - version: 3.2.2(prettier@2.8.7)(typescript@5.0.3) + version: 3.2.2(prettier@2.8.7)(typescript@5.0.4) release-it: specifier: ^15.10.1 version: 15.10.1 @@ -114,13 +114,13 @@ devDependencies: version: 0.5.21 ts-standard: specifier: ^12.0.2 - version: 12.0.2(eslint-import-resolver-typescript@3.5.5)(typescript@5.0.3) + version: 12.0.2(eslint-import-resolver-typescript@3.5.5)(typescript@5.0.4) typedoc: specifier: ^0.23.28 - version: 0.23.28(typescript@5.0.3) + version: 0.23.28(typescript@5.0.4) typescript: - specifier: ^5.0.3 - version: 5.0.3 + specifier: ^5.0.4 + version: 5.0.4 packages: @@ -267,13 +267,13 @@ packages: '@types/node': 18.15.11 chalk: 4.1.2 cosmiconfig: 8.1.3 - cosmiconfig-typescript-loader: 4.3.0(@types/node@18.15.11)(cosmiconfig@8.1.3)(ts-node@10.9.1)(typescript@5.0.3) + cosmiconfig-typescript-loader: 4.3.0(@types/node@18.15.11)(cosmiconfig@8.1.3)(ts-node@10.9.1)(typescript@5.0.4) lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 lodash.uniq: 4.5.0 resolve-from: 5.0.0 - ts-node: 10.9.1(@types/node@18.15.11)(typescript@5.0.3) - typescript: 5.0.3 + ts-node: 10.9.1(@types/node@18.15.11)(typescript@5.0.4) + typescript: 5.0.4 transitivePeerDependencies: - '@swc/core' - '@swc/wasm' @@ -734,7 +734,7 @@ packages: terser: 5.16.8 dev: true - /@rollup/plugin-typescript@11.1.0(rollup@3.20.2)(typescript@5.0.3): + /@rollup/plugin-typescript@11.1.0(rollup@3.20.2)(typescript@5.0.4): resolution: {integrity: sha512-86flrfE+bSHB69znnTV6kVjkncs2LBMhcTCyxWgRxLyfXfQrxg4UwlAqENnjrrxnSNS/XKCDJCl8EkdFJVHOxw==} engines: {node: '>=14.0.0'} peerDependencies: @@ -750,7 +750,7 @@ packages: '@rollup/pluginutils': 5.0.2(rollup@3.20.2) resolve: 1.22.2 rollup: 3.20.2 - typescript: 5.0.3 + typescript: 5.0.4 dev: true /@rollup/pluginutils@5.0.2(rollup@3.20.2): @@ -908,7 +908,7 @@ packages: '@types/yargs-parser': 21.0.0 dev: true - /@typescript-eslint/eslint-plugin@5.57.1(@typescript-eslint/parser@5.57.1)(eslint@8.37.0)(typescript@5.0.3): + /@typescript-eslint/eslint-plugin@5.57.1(@typescript-eslint/parser@5.57.1)(eslint@8.37.0)(typescript@5.0.4): resolution: {integrity: sha512-1MeobQkQ9tztuleT3v72XmY0XuKXVXusAhryoLuU5YZ+mXoYKZP9SQ7Flulh1NX4DTjpGTc2b/eMu4u7M7dhnQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -920,23 +920,23 @@ packages: optional: true dependencies: '@eslint-community/regexpp': 4.5.0 - '@typescript-eslint/parser': 5.57.1(eslint@8.37.0)(typescript@5.0.3) + '@typescript-eslint/parser': 5.57.1(eslint@8.37.0)(typescript@5.0.4) '@typescript-eslint/scope-manager': 5.57.1 - '@typescript-eslint/type-utils': 5.57.1(eslint@8.37.0)(typescript@5.0.3) - '@typescript-eslint/utils': 5.57.1(eslint@8.37.0)(typescript@5.0.3) + '@typescript-eslint/type-utils': 5.57.1(eslint@8.37.0)(typescript@5.0.4) + '@typescript-eslint/utils': 5.57.1(eslint@8.37.0)(typescript@5.0.4) debug: 4.3.4(supports-color@8.1.1) eslint: 8.37.0 grapheme-splitter: 1.0.4 ignore: 5.2.4 natural-compare-lite: 1.4.0 semver: 7.3.8 - tsutils: 3.21.0(typescript@5.0.3) - typescript: 5.0.3 + tsutils: 3.21.0(typescript@5.0.4) + typescript: 5.0.4 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/parser@5.57.1(eslint@8.37.0)(typescript@5.0.3): + /@typescript-eslint/parser@5.57.1(eslint@8.37.0)(typescript@5.0.4): resolution: {integrity: sha512-hlA0BLeVSA/wBPKdPGxoVr9Pp6GutGoY380FEhbVi0Ph4WNe8kLvqIRx76RSQt1lynZKfrXKs0/XeEk4zZycuA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -948,10 +948,10 @@ packages: dependencies: '@typescript-eslint/scope-manager': 5.57.1 '@typescript-eslint/types': 5.57.1 - '@typescript-eslint/typescript-estree': 5.57.1(typescript@5.0.3) + '@typescript-eslint/typescript-estree': 5.57.1(typescript@5.0.4) debug: 4.3.4(supports-color@8.1.1) eslint: 8.37.0 - typescript: 5.0.3 + typescript: 5.0.4 transitivePeerDependencies: - supports-color dev: true @@ -964,7 +964,7 @@ packages: '@typescript-eslint/visitor-keys': 5.57.1 dev: true - /@typescript-eslint/type-utils@5.57.1(eslint@8.37.0)(typescript@5.0.3): + /@typescript-eslint/type-utils@5.57.1(eslint@8.37.0)(typescript@5.0.4): resolution: {integrity: sha512-/RIPQyx60Pt6ga86hKXesXkJ2WOS4UemFrmmq/7eOyiYjYv/MUSHPlkhU6k9T9W1ytnTJueqASW+wOmW4KrViw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -974,12 +974,12 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 5.57.1(typescript@5.0.3) - '@typescript-eslint/utils': 5.57.1(eslint@8.37.0)(typescript@5.0.3) + '@typescript-eslint/typescript-estree': 5.57.1(typescript@5.0.4) + '@typescript-eslint/utils': 5.57.1(eslint@8.37.0)(typescript@5.0.4) debug: 4.3.4(supports-color@8.1.1) eslint: 8.37.0 - tsutils: 3.21.0(typescript@5.0.3) - typescript: 5.0.3 + tsutils: 3.21.0(typescript@5.0.4) + typescript: 5.0.4 transitivePeerDependencies: - supports-color dev: true @@ -989,7 +989,7 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /@typescript-eslint/typescript-estree@5.57.1(typescript@5.0.3): + /@typescript-eslint/typescript-estree@5.57.1(typescript@5.0.4): resolution: {integrity: sha512-A2MZqD8gNT0qHKbk2wRspg7cHbCDCk2tcqt6ScCFLr5Ru8cn+TCfM786DjPhqwseiS+PrYwcXht5ztpEQ6TFTw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -1004,13 +1004,13 @@ packages: globby: 11.1.0 is-glob: 4.0.3 semver: 7.3.8 - tsutils: 3.21.0(typescript@5.0.3) - typescript: 5.0.3 + tsutils: 3.21.0(typescript@5.0.4) + typescript: 5.0.4 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/utils@5.57.1(eslint@8.37.0)(typescript@5.0.3): + /@typescript-eslint/utils@5.57.1(eslint@8.37.0)(typescript@5.0.4): resolution: {integrity: sha512-kN6vzzf9NkEtawECqze6v99LtmDiUJCVpvieTFA1uL7/jDghiJGubGZ5csicYHU1Xoqb3oH/R5cN5df6W41Nfg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -1021,7 +1021,7 @@ packages: '@types/semver': 7.3.13 '@typescript-eslint/scope-manager': 5.57.1 '@typescript-eslint/types': 5.57.1 - '@typescript-eslint/typescript-estree': 5.57.1(typescript@5.0.3) + '@typescript-eslint/typescript-estree': 5.57.1(typescript@5.0.4) eslint: 8.37.0 eslint-scope: 5.1.1 semver: 7.3.8 @@ -1708,7 +1708,7 @@ packages: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} dev: true - /cosmiconfig-typescript-loader@4.3.0(@types/node@18.15.11)(cosmiconfig@8.1.3)(ts-node@10.9.1)(typescript@5.0.3): + /cosmiconfig-typescript-loader@4.3.0(@types/node@18.15.11)(cosmiconfig@8.1.3)(ts-node@10.9.1)(typescript@5.0.4): resolution: {integrity: sha512-NTxV1MFfZDLPiBMjxbHRwSh5LaLcPMwNdCutmnHJCKoVnlvldPWlllonKwrsRJ5pYZBIBGRWWU2tfvzxgeSW5Q==} engines: {node: '>=12', npm: '>=6'} peerDependencies: @@ -1719,8 +1719,8 @@ packages: dependencies: '@types/node': 18.15.11 cosmiconfig: 8.1.3 - ts-node: 10.9.1(@types/node@18.15.11)(typescript@5.0.3) - typescript: 5.0.3 + ts-node: 10.9.1(@types/node@18.15.11)(typescript@5.0.4) + typescript: 5.0.4 dev: true /cosmiconfig@8.1.3: @@ -2140,7 +2140,7 @@ packages: eslint-plugin-react: 7.32.2(eslint@8.37.0) dev: true - /eslint-config-standard-with-typescript@23.0.0(@typescript-eslint/eslint-plugin@5.57.1)(eslint-plugin-import@2.27.5)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.37.0)(typescript@5.0.3): + /eslint-config-standard-with-typescript@23.0.0(@typescript-eslint/eslint-plugin@5.57.1)(eslint-plugin-import@2.27.5)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.37.0)(typescript@5.0.4): resolution: {integrity: sha512-iaaWifImn37Z1OXbNW1es7KI+S7D408F9ys0bpaQf2temeBWlvb0Nc5qHkOgYaRb5QxTZT32GGeN1gtswASOXA==} peerDependencies: '@typescript-eslint/eslint-plugin': ^5.0.0 @@ -2150,19 +2150,19 @@ packages: eslint-plugin-promise: ^6.0.0 typescript: '*' dependencies: - '@typescript-eslint/eslint-plugin': 5.57.1(@typescript-eslint/parser@5.57.1)(eslint@8.37.0)(typescript@5.0.3) - '@typescript-eslint/parser': 5.57.1(eslint@8.37.0)(typescript@5.0.3) + '@typescript-eslint/eslint-plugin': 5.57.1(@typescript-eslint/parser@5.57.1)(eslint@8.37.0)(typescript@5.0.4) + '@typescript-eslint/parser': 5.57.1(eslint@8.37.0)(typescript@5.0.4) eslint: 8.37.0 eslint-config-standard: 17.0.0(eslint-plugin-import@2.27.5)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.37.0) eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.57.1)(eslint-import-resolver-typescript@3.5.5)(eslint@8.37.0) eslint-plugin-n: 15.7.0(eslint@8.37.0) eslint-plugin-promise: 6.1.1(eslint@8.37.0) - typescript: 5.0.3 + typescript: 5.0.4 transitivePeerDependencies: - supports-color dev: true - /eslint-config-standard-with-typescript@34.0.1(@typescript-eslint/eslint-plugin@5.57.1)(eslint-plugin-import@2.27.5)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.37.0)(typescript@5.0.3): + /eslint-config-standard-with-typescript@34.0.1(@typescript-eslint/eslint-plugin@5.57.1)(eslint-plugin-import@2.27.5)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.37.0)(typescript@5.0.4): resolution: {integrity: sha512-J7WvZeLtd0Vr9F+v4dZbqJCLD16cbIy4U+alJMq4MiXdpipdBM3U5NkXaGUjePc4sb1ZE01U9g6VuTBpHHz1fg==} peerDependencies: '@typescript-eslint/eslint-plugin': ^5.43.0 @@ -2172,14 +2172,14 @@ packages: eslint-plugin-promise: ^6.0.0 typescript: '*' dependencies: - '@typescript-eslint/eslint-plugin': 5.57.1(@typescript-eslint/parser@5.57.1)(eslint@8.37.0)(typescript@5.0.3) - '@typescript-eslint/parser': 5.57.1(eslint@8.37.0)(typescript@5.0.3) + '@typescript-eslint/eslint-plugin': 5.57.1(@typescript-eslint/parser@5.57.1)(eslint@8.37.0)(typescript@5.0.4) + '@typescript-eslint/parser': 5.57.1(eslint@8.37.0)(typescript@5.0.4) eslint: 8.37.0 eslint-config-standard: 17.0.0(eslint-plugin-import@2.27.5)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.37.0) eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.57.1)(eslint-import-resolver-typescript@3.5.5)(eslint@8.37.0) eslint-plugin-n: 15.7.0(eslint@8.37.0) eslint-plugin-promise: 6.1.1(eslint@8.37.0) - typescript: 5.0.3 + typescript: 5.0.4 transitivePeerDependencies: - supports-color dev: true @@ -2258,7 +2258,7 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 5.57.1(eslint@8.37.0)(typescript@5.0.3) + '@typescript-eslint/parser': 5.57.1(eslint@8.37.0)(typescript@5.0.4) debug: 3.2.7 eslint: 8.37.0 eslint-import-resolver-node: 0.3.7 @@ -2288,7 +2288,7 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 5.57.1(eslint@8.37.0)(typescript@5.0.3) + '@typescript-eslint/parser': 5.57.1(eslint@8.37.0)(typescript@5.0.4) array-includes: 3.1.6 array.prototype.flat: 1.3.1 array.prototype.flatmap: 1.3.1 @@ -4752,7 +4752,7 @@ packages: engines: {node: '>= 0.8.0'} dev: true - /prettier-plugin-organize-imports@3.2.2(prettier@2.8.7)(typescript@5.0.3): + /prettier-plugin-organize-imports@3.2.2(prettier@2.8.7)(typescript@5.0.4): resolution: {integrity: sha512-e97lE6odGSiHonHJMTYC0q0iLXQyw0u5z/PJpvP/3vRy6/Zi9kLBwFAbEGjDzIowpjQv8b+J04PDamoUSQbzGA==} peerDependencies: '@volar/vue-language-plugin-pug': ^1.0.4 @@ -4766,7 +4766,7 @@ packages: optional: true dependencies: prettier: 2.8.7 - typescript: 5.0.3 + typescript: 5.0.4 dev: true /prettier@2.8.7: @@ -5669,7 +5669,7 @@ packages: engines: {node: '>=8'} dev: true - /ts-node@10.9.1(@types/node@18.15.11)(typescript@5.0.3): + /ts-node@10.9.1(@types/node@18.15.11)(typescript@5.0.4): resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} hasBin: true peerDependencies: @@ -5695,23 +5695,23 @@ packages: create-require: 1.1.1 diff: 4.0.2 make-error: 1.3.6 - typescript: 5.0.3 + typescript: 5.0.4 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 dev: true - /ts-standard@12.0.2(eslint-import-resolver-typescript@3.5.5)(typescript@5.0.3): + /ts-standard@12.0.2(eslint-import-resolver-typescript@3.5.5)(typescript@5.0.4): resolution: {integrity: sha512-XX2wrB9fKKTfBj4yD3ABm9iShzZcS2iWcPK8XzlBvuL20+wMiLgiz/k5tXgZwTaYq5wRhbks1Y9PelhujF/9ag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true peerDependencies: typescript: '*' dependencies: - '@typescript-eslint/eslint-plugin': 5.57.1(@typescript-eslint/parser@5.57.1)(eslint@8.37.0)(typescript@5.0.3) - '@typescript-eslint/parser': 5.57.1(eslint@8.37.0)(typescript@5.0.3) + '@typescript-eslint/eslint-plugin': 5.57.1(@typescript-eslint/parser@5.57.1)(eslint@8.37.0)(typescript@5.0.4) + '@typescript-eslint/parser': 5.57.1(eslint@8.37.0)(typescript@5.0.4) eslint: 8.37.0 eslint-config-standard-jsx: 11.0.0(eslint-plugin-react@7.32.2)(eslint@8.37.0) - eslint-config-standard-with-typescript: 23.0.0(@typescript-eslint/eslint-plugin@5.57.1)(eslint-plugin-import@2.27.5)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.37.0)(typescript@5.0.3) + eslint-config-standard-with-typescript: 23.0.0(@typescript-eslint/eslint-plugin@5.57.1)(eslint-plugin-import@2.27.5)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.37.0)(typescript@5.0.4) eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.57.1)(eslint-import-resolver-typescript@3.5.5)(eslint@8.37.0) eslint-plugin-n: 15.7.0(eslint@8.37.0) eslint-plugin-promise: 6.1.1(eslint@8.37.0) @@ -5719,7 +5719,7 @@ packages: minimist: 1.2.8 pkg-conf: 4.0.0 standard-engine: 15.0.0 - typescript: 5.0.3 + typescript: 5.0.4 transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -5743,14 +5743,14 @@ packages: resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==} dev: true - /tsutils@3.21.0(typescript@5.0.3): + /tsutils@3.21.0(typescript@5.0.4): resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} engines: {node: '>= 6'} peerDependencies: typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' dependencies: tslib: 1.14.1 - typescript: 5.0.3 + typescript: 5.0.4 dev: true /type-check@0.3.2: @@ -5831,7 +5831,7 @@ packages: is-typedarray: 1.0.0 dev: true - /typedoc@0.23.28(typescript@5.0.3): + /typedoc@0.23.28(typescript@5.0.4): resolution: {integrity: sha512-9x1+hZWTHEQcGoP7qFmlo4unUoVJLB0H/8vfO/7wqTnZxg4kPuji9y3uRzEu0ZKez63OJAUmiGhUrtukC6Uj3w==} engines: {node: '>= 14.14'} hasBin: true @@ -5842,11 +5842,11 @@ packages: marked: 4.3.0 minimatch: 7.4.5 shiki: 0.14.1 - typescript: 5.0.3 + typescript: 5.0.4 dev: true - /typescript@5.0.3: - resolution: {integrity: sha512-xv8mOEDnigb/tN9PSMTwSEqAnUvkoXMQlicOb0IUVDBSQCgBSaAAROUZYy2IcUy5qU6XajK5jjjO7TMWqBTKZA==} + /typescript@5.0.4: + resolution: {integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==} engines: {node: '>=12.20'} hasBin: true dev: true diff --git a/src/index.ts b/src/index.ts index 92ed93a1..349af12c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,8 @@ export { DynamicClusterPool } from './pools/cluster/dynamic' export { FixedClusterPool } from './pools/cluster/fixed' export type { ClusterPoolOptions } from './pools/cluster/fixed' -export type { IPool, PoolEmitter, PoolOptions } from './pools/pool' +export { PoolEvents } from './pools/pool' +export type { IPool, PoolEmitter, PoolOptions, PoolEvent } from './pools/pool' export type { ErrorHandler, ExitHandler, diff --git a/src/pools/abstract-pool.ts b/src/pools/abstract-pool.ts index 0d583217..9ac81ce5 100644 --- a/src/pools/abstract-pool.ts +++ b/src/pools/abstract-pool.ts @@ -2,7 +2,7 @@ import crypto from 'node:crypto' import type { MessageValue, PromiseResponseWrapper } from '../utility-types' import { EMPTY_FUNCTION } from '../utils' import { KillBehaviors, isKillBehavior } from '../worker/worker-options' -import type { PoolOptions } from './pool' +import { PoolEvents, type PoolOptions } from './pool' import { PoolEmitter } from './pool' import type { IPoolInternal, TasksUsage, WorkerType } from './pool-internal' import { PoolType } from './pool-internal' @@ -126,16 +126,18 @@ export abstract class AbstractPool< private checkPoolOptions (opts: PoolOptions): void { this.opts.workerChoiceStrategy = opts.workerChoiceStrategy ?? WorkerChoiceStrategies.ROUND_ROBIN - if ( - !Object.values(WorkerChoiceStrategies).includes( - this.opts.workerChoiceStrategy - ) - ) { + this.checkValidWorkerChoiceStrategy(this.opts.workerChoiceStrategy) + this.opts.enableEvents = opts.enableEvents ?? true + } + + private checkValidWorkerChoiceStrategy ( + workerChoiceStrategy: WorkerChoiceStrategy + ): void { + if (!Object.values(WorkerChoiceStrategies).includes(workerChoiceStrategy)) { throw new Error( - `Invalid worker choice strategy '${this.opts.workerChoiceStrategy}'` + `Invalid worker choice strategy '${workerChoiceStrategy}'` ) } - this.opts.enableEvents = opts.enableEvents ?? true } /** @inheritDoc */ @@ -162,6 +164,7 @@ export abstract class AbstractPool< public setWorkerChoiceStrategy ( workerChoiceStrategy: WorkerChoiceStrategy ): void { + this.checkValidWorkerChoiceStrategy(workerChoiceStrategy) this.opts.workerChoiceStrategy = workerChoiceStrategy for (const [index, workerItem] of this.workers.entries()) { this.setWorker(index, workerItem.worker, { @@ -273,7 +276,7 @@ export abstract class AbstractPool< ++workerTasksUsage.error } if (this.workerChoiceStrategyContext.getRequiredStatistics().runTime) { - workerTasksUsage.runTime += message.taskRunTime ?? 0 + workerTasksUsage.runTime += message.runTime ?? 0 if ( this.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime && workerTasksUsage.run !== 0 @@ -305,7 +308,7 @@ export abstract class AbstractPool< (message.kill != null && this.getWorkerTasksUsage(createdWorker)?.running === 0) ) { - // Kill received from the worker, means that no new tasks are submitted to that worker for a while ( > maxInactiveTime) + // Kill message received from the worker, means that no new tasks are submitted to that worker for a while ( > maxInactiveTime) void this.destroyWorker(createdWorker) } }) @@ -389,6 +392,7 @@ export abstract class AbstractPool< protected workerListener (): (message: MessageValue) => void { return message => { if (message.id != null) { + // Task response received const promiseResponse = this.promiseResponseMap.get(message.id) if (promiseResponse != null) { if (message.error != null) { @@ -416,7 +420,7 @@ export abstract class AbstractPool< private checkAndEmitBusy (): void { if (this.opts.enableEvents === true && this.busy) { - this.emitter?.emit('busy') + this.emitter?.emit(PoolEvents.busy) } } @@ -426,7 +430,7 @@ export abstract class AbstractPool< this.opts.enableEvents === true && this.full ) { - this.emitter?.emit('full') + this.emitter?.emit(PoolEvents.full) } } diff --git a/src/pools/pool.ts b/src/pools/pool.ts index 600cb422..f1da5356 100644 --- a/src/pools/pool.ts +++ b/src/pools/pool.ts @@ -12,6 +12,19 @@ import type { WorkerChoiceStrategy } from './selection-strategies/selection-stra */ export class PoolEmitter extends EventEmitter {} +/** + * Enumeration of pool events. + */ +export const PoolEvents = Object.freeze({ + full: 'full', + busy: 'busy' +} as const) + +/** + * Pool event. + */ +export type PoolEvent = keyof typeof PoolEvents + /** * Options for a poolifier pool. */ diff --git a/src/pools/selection-strategies/worker-choice-strategy-context.ts b/src/pools/selection-strategies/worker-choice-strategy-context.ts index 66aafad6..826a89d9 100644 --- a/src/pools/selection-strategies/worker-choice-strategy-context.ts +++ b/src/pools/selection-strategies/worker-choice-strategy-context.ts @@ -89,11 +89,10 @@ export class WorkerChoiceStrategyContext< public setWorkerChoiceStrategy ( workerChoiceStrategy: WorkerChoiceStrategy ): void { - if (this.workerChoiceStrategyType === workerChoiceStrategy) { - this.workerChoiceStrategies.get(workerChoiceStrategy)?.reset() - } else { + if (this.workerChoiceStrategyType !== workerChoiceStrategy) { this.workerChoiceStrategyType = workerChoiceStrategy } + this.workerChoiceStrategies.get(this.workerChoiceStrategyType)?.reset() } /** diff --git a/src/utility-types.ts b/src/utility-types.ts index ec5ff44d..05af4e3d 100644 --- a/src/utility-types.ts +++ b/src/utility-types.ts @@ -32,9 +32,9 @@ export interface MessageValue< */ readonly error?: string /** - * Task runtime. + * Runtime. */ - readonly taskRunTime?: number + readonly runTime?: number /** * Reference to main worker. * diff --git a/src/worker/abstract-worker.ts b/src/worker/abstract-worker.ts index 475595ec..10a0c82d 100644 --- a/src/worker/abstract-worker.ts +++ b/src/worker/abstract-worker.ts @@ -26,7 +26,7 @@ export abstract class AbstractWorker< */ protected lastTaskTimestamp!: number /** - * Handler Id of the `aliveInterval` worker alive check. + * Handler id of the `aliveInterval` worker alive check. */ protected readonly aliveInterval?: NodeJS.Timeout /** @@ -45,7 +45,7 @@ export abstract class AbstractWorker< protected mainWorker: MainWorker | undefined | null, protected readonly opts: WorkerOptions = { /** - * The kill behavior option on this Worker or its default value. + * The kill behavior option on this worker or its default value. */ killBehavior: DEFAULT_KILL_BEHAVIOR, /** @@ -67,28 +67,36 @@ export abstract class AbstractWorker< this.checkAlive.bind(this)() } - this.mainWorker?.on('message', (value: MessageValue) => { - this.messageListener(value, fn) - }) + this.mainWorker?.on( + 'message', + (message: MessageValue) => { + this.messageListener(message, fn) + } + ) } + /** + * Worker message listener. + * + * @param message - Message received. + * @param fn - Function processed by the worker when the pool's `execution` function is invoked. + */ protected messageListener ( - value: MessageValue, + message: MessageValue, fn: (data: Data) => Response ): void { - if (value.data != null && value.id != null) { - // Here you will receive messages + if (message.data != null && message.id != null) { + // Task message received if (this.opts.async === true) { - this.runInAsyncScope(this.runAsync.bind(this), this, fn, value) + this.runInAsyncScope(this.runAsync.bind(this), this, fn, message) } else { - this.runInAsyncScope(this.run.bind(this), this, fn, value) + this.runInAsyncScope(this.run.bind(this), this, fn, message) } - } else if (value.parent != null) { - // Save a reference of the main worker to communicate with it - // This will be received once - this.mainWorker = value.parent - } else if (value.kill != null) { - // Here is time to kill this worker, just clearing the interval + } else if (message.parent != null) { + // Main worker reference message received + this.mainWorker = message.parent + } else if (message.kill != null) { + // Kill message received this.aliveInterval != null && clearInterval(this.aliveInterval) this.emitDestroy() } @@ -158,20 +166,20 @@ export abstract class AbstractWorker< * Runs the given function synchronously. * * @param fn - Function that will be executed. - * @param value - Input data for the given function. + * @param message - Input data for the given function. */ protected run ( fn: (data?: Data) => Response, - value: MessageValue + message: MessageValue ): void { try { - const startTaskTimestamp = Date.now() - const res = fn(value.data) - const taskRunTime = Date.now() - startTaskTimestamp - this.sendToMainWorker({ data: res, id: value.id, taskRunTime }) + const startTimestamp = Date.now() + const res = fn(message.data) + const runTime = Date.now() - startTimestamp + this.sendToMainWorker({ data: res, id: message.id, runTime }) } catch (e) { const err = this.handleError(e as Error) - this.sendToMainWorker({ error: err, id: value.id }) + this.sendToMainWorker({ error: err, id: message.id }) } finally { !this.isMain && (this.lastTaskTimestamp = Date.now()) } @@ -181,22 +189,22 @@ export abstract class AbstractWorker< * Runs the given function asynchronously. * * @param fn - Function that will be executed. - * @param value - Input data for the given function. + * @param message - Input data for the given function. */ protected runAsync ( fn: (data?: Data) => Promise, - value: MessageValue + message: MessageValue ): void { - const startTaskTimestamp = Date.now() - fn(value.data) + const startTimestamp = Date.now() + fn(message.data) .then(res => { - const taskRunTime = Date.now() - startTaskTimestamp - this.sendToMainWorker({ data: res, id: value.id, taskRunTime }) + const runTime = Date.now() - startTimestamp + this.sendToMainWorker({ data: res, id: message.id, runTime }) return null }) .catch(e => { const err = this.handleError(e as Error) - this.sendToMainWorker({ error: err, id: value.id }) + this.sendToMainWorker({ error: err, id: message.id }) }) .finally(() => { !this.isMain && (this.lastTaskTimestamp = Date.now()) diff --git a/tests/pools/abstract/abstract-pool.test.js b/tests/pools/abstract/abstract-pool.test.js index d9b5695e..658be6a9 100644 --- a/tests/pools/abstract/abstract-pool.test.js +++ b/tests/pools/abstract/abstract-pool.test.js @@ -1,8 +1,9 @@ const { expect } = require('expect') const { - FixedClusterPool, DynamicThreadPool, + FixedClusterPool, FixedThreadPool, + PoolEvents, WorkerChoiceStrategies } = require('../../../lib/index') @@ -218,7 +219,7 @@ describe('Abstract pool test suite', () => { ) const promises = [] let poolFull = 0 - pool.emitter.on('full', () => ++poolFull) + pool.emitter.on(PoolEvents.full, () => ++poolFull) for (let i = 0; i < numberOfWorkers * 2; i++) { promises.push(pool.execute()) } @@ -236,7 +237,7 @@ describe('Abstract pool test suite', () => { ) const promises = [] let poolBusy = 0 - pool.emitter.on('busy', () => ++poolBusy) + pool.emitter.on(PoolEvents.busy, () => ++poolBusy) for (let i = 0; i < numberOfWorkers * 2; i++) { promises.push(pool.execute()) } diff --git a/tests/pools/cluster/dynamic.test.js b/tests/pools/cluster/dynamic.test.js index 6dd9f506..74cb5d8f 100644 --- a/tests/pools/cluster/dynamic.test.js +++ b/tests/pools/cluster/dynamic.test.js @@ -1,5 +1,5 @@ const { expect } = require('expect') -const { DynamicClusterPool } = require('../../../lib/index') +const { DynamicClusterPool, PoolEvents } = require('../../../lib/index') const { WorkerFunctions } = require('../../test-types') const TestUtils = require('../../test-utils') @@ -28,7 +28,7 @@ describe('Dynamic cluster pool test suite', () => { it('Verify that new workers are created when required, max size is not exceeded and that after a while new workers will die', async () => { let poolBusy = 0 - pool.emitter.on('busy', () => ++poolBusy) + pool.emitter.on(PoolEvents.busy, () => ++poolBusy) for (let i = 0; i < max * 2; i++) { pool.execute() } diff --git a/tests/pools/cluster/fixed.test.js b/tests/pools/cluster/fixed.test.js index ae899625..908acbfe 100644 --- a/tests/pools/cluster/fixed.test.js +++ b/tests/pools/cluster/fixed.test.js @@ -1,5 +1,5 @@ const { expect } = require('expect') -const { FixedClusterPool } = require('../../../lib/index') +const { FixedClusterPool, PoolEvents } = require('../../../lib/index') const { WorkerFunctions } = require('../../test-types') const TestUtils = require('../../test-utils') @@ -65,9 +65,9 @@ describe('Fixed cluster pool test suite', () => { expect(result).toBe(false) }) - it('Verify that busy event is emitted', async () => { + it("Verify that 'busy' event is emitted", async () => { let poolBusy = 0 - pool.emitter.on('busy', () => ++poolBusy) + pool.emitter.on(PoolEvents.busy, () => ++poolBusy) for (let i = 0; i < numberOfWorkers * 2; i++) { pool.execute() } diff --git a/tests/pools/thread/dynamic.test.js b/tests/pools/thread/dynamic.test.js index d8c68e90..9f69860a 100644 --- a/tests/pools/thread/dynamic.test.js +++ b/tests/pools/thread/dynamic.test.js @@ -1,5 +1,5 @@ const { expect } = require('expect') -const { DynamicThreadPool } = require('../../../lib/index') +const { DynamicThreadPool, PoolEvents } = require('../../../lib/index') const { WorkerFunctions } = require('../../test-types') const TestUtils = require('../../test-utils') @@ -28,7 +28,7 @@ describe('Dynamic thread pool test suite', () => { it('Verify that new workers are created when required, max size is not exceeded and that after a while new workers will die', async () => { let poolBusy = 0 - pool.emitter.on('busy', () => ++poolBusy) + pool.emitter.on(PoolEvents.busy, () => ++poolBusy) for (let i = 0; i < max * 2; i++) { pool.execute() } diff --git a/tests/pools/thread/fixed.test.js b/tests/pools/thread/fixed.test.js index fd9ce5df..a42b5d37 100644 --- a/tests/pools/thread/fixed.test.js +++ b/tests/pools/thread/fixed.test.js @@ -1,5 +1,5 @@ const { expect } = require('expect') -const { FixedThreadPool } = require('../../../lib/index') +const { FixedThreadPool, PoolEvents } = require('../../../lib/index') const { WorkerFunctions } = require('../../test-types') const TestUtils = require('../../test-utils') @@ -65,9 +65,9 @@ describe('Fixed thread pool test suite', () => { expect(result).toBe(false) }) - it('Verify that busy event is emitted', async () => { + it("Verify that 'busy' event is emitted", async () => { let poolBusy = 0 - pool.emitter.on('busy', () => ++poolBusy) + pool.emitter.on(PoolEvents.busy, () => ++poolBusy) for (let i = 0; i < numberOfThreads * 2; i++) { pool.execute() } -- 2.34.1