From e102732c0e3966b81834b2c0bdd087eb051162ad Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Mon, 26 Jun 2023 21:08:32 +0200 Subject: [PATCH] fix: prepare code to fix pool internal IPC for cluster worker MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- .eslintrc.js | 1 + benchmarks/README.md | 6 +- benchmarks/internal/cluster-worker.mjs | 4 +- benchmarks/internal/thread-worker.mjs | 4 +- .../versus-external-pools/fixed-microjob.mjs | 33 ----- .../fixed-threadwork.mjs | 21 --- .../hyperfine_benchmarks.sh | 3 - benchmarks/versus-external-pools/package.json | 7 +- .../versus-external-pools/pnpm-lock.yaml | 125 ---------------- .../versus-external-pools/pool-threadwork.mjs | 9 -- benchmarks/versus-external-pools/threadjs.mjs | 35 ----- .../threadjs/function-to-bench-worker.mjs | 8 -- package.json | 8 +- pnpm-lock.yaml | 136 +++++++++--------- src/index.ts | 7 +- src/pools/abstract-pool.ts | 28 ++-- src/pools/cluster/dynamic.ts | 4 +- src/pools/cluster/fixed.ts | 18 +-- src/pools/pool.ts | 6 +- .../abstract-worker-choice-strategy.ts | 4 +- .../fair-share-worker-choice-strategy.ts | 4 +- ...hted-round-robin-worker-choice-strategy.ts | 4 +- .../least-busy-worker-choice-strategy.ts | 4 +- .../least-elu-worker-choice-strategy.ts | 4 +- .../least-used-worker-choice-strategy.ts | 4 +- .../round-robin-worker-choice-strategy.ts | 4 +- ...hted-round-robin-worker-choice-strategy.ts | 4 +- .../worker-choice-strategy-context.ts | 4 +- src/pools/thread/dynamic.ts | 4 +- src/pools/thread/fixed.ts | 43 +----- src/pools/worker.ts | 10 +- src/queue.ts | 17 +-- src/utility-types.ts | 25 ++-- src/worker/abstract-worker.ts | 11 +- src/worker/cluster-worker.ts | 16 ++- src/worker/thread-worker.ts | 6 +- src/worker/worker-functions.ts | 16 +-- tests/worker/abstract-worker.test.js | 2 +- 38 files changed, 183 insertions(+), 466 deletions(-) delete mode 100644 benchmarks/versus-external-pools/fixed-microjob.mjs delete mode 100644 benchmarks/versus-external-pools/fixed-threadwork.mjs delete mode 100644 benchmarks/versus-external-pools/pool-threadwork.mjs delete mode 100644 benchmarks/versus-external-pools/threadjs.mjs delete mode 100644 benchmarks/versus-external-pools/workers/threadjs/function-to-bench-worker.mjs diff --git a/.eslintrc.js b/.eslintrc.js index 5d9c45bf..e160b189 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -43,6 +43,7 @@ module.exports = defineConfig({ 'builtins', 'christopher', 'cjs', + 'cloneable', 'comparator', 'cpu', 'cpus', diff --git a/benchmarks/README.md b/benchmarks/README.md index 3b7f0702..400bb152 100644 --- a/benchmarks/README.md +++ b/benchmarks/README.md @@ -18,9 +18,6 @@ External pools with which we compared the poolifier results: - [workerpool](https://github.com/josdejong/workerpool) - [worker-nodes](https://github.com/allegro/node-worker-nodes) - [node-worker-threads-pool](https://github.com/SUCHMOKUO/node-worker-threads-pool) -- [threads.js](https://github.com/andywer/threads.js/) -- [threadwork](https://github.com/kevlened/threadwork) -- [microjob](https://github.com/wilk/microjob) Those are our results: @@ -33,6 +30,9 @@ External pools with which we used to compare the poolifier results: - [worker-threads-pool](https://github.com/watson/worker-threads-pool): removed because unmaintained since more than 4 years. +- [threadwork](https://github.com/kevlened/threadwork): removed because unmaintained since more than 3 years. +- [microjob](https://github.com/wilk/microjob): removed because unmaintained since more than 5 years. +- [threads.js](https://github.com/andywer/threads.js/): removed because not a threads pool. ### Internal diff --git a/benchmarks/internal/cluster-worker.mjs b/benchmarks/internal/cluster-worker.mjs index 50e4a324..e8d16d21 100644 --- a/benchmarks/internal/cluster-worker.mjs +++ b/benchmarks/internal/cluster-worker.mjs @@ -5,7 +5,7 @@ import { WorkerFunctions } from '../benchmarks-types.mjs' const debug = false -function yourFunction (data) { +function workerFunction (data) { data = data || {} data.function = data.function || WorkerFunctions.jsonIntegerSerialization executeWorkerFunction(data) @@ -13,4 +13,4 @@ function yourFunction (data) { return { ok: 1 } } -export default new ClusterWorker(yourFunction) +export default new ClusterWorker(workerFunction) diff --git a/benchmarks/internal/thread-worker.mjs b/benchmarks/internal/thread-worker.mjs index 4e3c1050..c1cd0141 100644 --- a/benchmarks/internal/thread-worker.mjs +++ b/benchmarks/internal/thread-worker.mjs @@ -5,7 +5,7 @@ import { WorkerFunctions } from '../benchmarks-types.mjs' const debug = false -function yourFunction (data) { +function workerFunction (data) { data = data || {} data.function = data.function || WorkerFunctions.jsonIntegerSerialization executeWorkerFunction(data) @@ -13,4 +13,4 @@ function yourFunction (data) { return { ok: 1 } } -export default new ThreadWorker(yourFunction) +export default new ThreadWorker(workerFunction) diff --git a/benchmarks/versus-external-pools/fixed-microjob.mjs b/benchmarks/versus-external-pools/fixed-microjob.mjs deleted file mode 100644 index 85075865..00000000 --- a/benchmarks/versus-external-pools/fixed-microjob.mjs +++ /dev/null @@ -1,33 +0,0 @@ -// IMPORT LIBRARIES -import { job, start } from 'microjob' -// FINISH IMPORT LIBRARIES -// IMPORT FUNCTION TO BENCH -import functionToBench from './functions/function-to-bench.js' -// FINISH IMPORT FUNCTION TO BENCH -const size = parseInt(process.env.POOL_SIZE) -const iterations = parseInt(process.env.NUM_ITERATIONS) -const data = { - test: 'MYBENCH', - taskType: process.env.TASK_TYPE, - taskSize: parseInt(process.env.TASK_SIZE) -} - -async function run () { - await start({ maxWorkers: size }) - const promises = [] - for (let i = 0; i < iterations; i++) { - promises.push( - job( - data => { - functionToBench(data) - }, - { data, ctx: { functionToBench } } - ) - ) - } - await Promise.all(promises) - // eslint-disable-next-line n/no-process-exit - process.exit() -} - -await run() diff --git a/benchmarks/versus-external-pools/fixed-threadwork.mjs b/benchmarks/versus-external-pools/fixed-threadwork.mjs deleted file mode 100644 index 190abc1d..00000000 --- a/benchmarks/versus-external-pools/fixed-threadwork.mjs +++ /dev/null @@ -1,21 +0,0 @@ -// IMPORT LIBRARIES -import threadPool from './pool-threadwork' -// FINISH IMPORT LIBRARIES -const iterations = parseInt(process.env.NUM_ITERATIONS) -const data = { - test: 'MYBENCH', - taskType: process.env.TASK_TYPE, - taskSize: parseInt(process.env.TASK_SIZE) -} - -async function run () { - const promises = [] - for (let i = 0; i < iterations; i++) { - promises.push(threadPool.run(data)) - } - await Promise.all(promises) - // eslint-disable-next-line n/no-process-exit - process.exit() -} - -await run() diff --git a/benchmarks/versus-external-pools/hyperfine_benchmarks.sh b/benchmarks/versus-external-pools/hyperfine_benchmarks.sh index b6534d82..011e986b 100755 --- a/benchmarks/versus-external-pools/hyperfine_benchmarks.sh +++ b/benchmarks/versus-external-pools/hyperfine_benchmarks.sh @@ -13,6 +13,3 @@ hyperfine --export-markdown BENCH-100000.md --min-runs 20 --prepare 'sleep 2' -- 'node fixed-worker-nodes.js' \ 'node dynamic-node-worker-threads-pool.mjs' \ 'node static-node-worker-threads-pool.mjs' \ - 'node threadjs.mjs' \ - 'node fixed-threadwork.mjs' \ - 'node fixed-microjob.mjs' diff --git a/benchmarks/versus-external-pools/package.json b/benchmarks/versus-external-pools/package.json index 5d0691b5..8478510e 100644 --- a/benchmarks/versus-external-pools/package.json +++ b/benchmarks/versus-external-pools/package.json @@ -1,6 +1,6 @@ { "name": "poolifier-benchmarks", - "version": "1.0.0-internal", + "version": "1.0.0", "description": "This project contains benchmarks for the most used and popular Node.js thread/cluster pools implementations", "private": true, "main": "index.js", @@ -11,18 +11,15 @@ }, "volta": { "node": "18.16.1", - "pnpm": "8.6.3" + "pnpm": "8.6.5" }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "dependencies": { - "microjob": "0.7.0", "node-worker-threads-pool": "1.5.1", "piscina": "4.0.0", "poolifier": "2.6.3", - "threads": "1.7.0", - "threadwork": "0.6.0", "tinypool": "0.5.0", "worker-nodes": "2.6.0", "workerpool": "6.4.0" diff --git a/benchmarks/versus-external-pools/pnpm-lock.yaml b/benchmarks/versus-external-pools/pnpm-lock.yaml index fe22ee34..69c4154d 100644 --- a/benchmarks/versus-external-pools/pnpm-lock.yaml +++ b/benchmarks/versus-external-pools/pnpm-lock.yaml @@ -5,9 +5,6 @@ settings: excludeLinksFromLockfile: false dependencies: - microjob: - specifier: 0.7.0 - version: 0.7.0 node-worker-threads-pool: specifier: 1.5.1 version: 1.5.1 @@ -17,12 +14,6 @@ dependencies: poolifier: specifier: 2.6.3 version: 2.6.3 - threads: - specifier: 1.7.0 - version: 1.7.0 - threadwork: - specifier: 0.6.0 - version: 0.6.0 tinypool: specifier: 0.5.0 version: 0.5.0 @@ -43,29 +34,6 @@ packages: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} dev: false - /callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - dev: false - - /debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - dev: false - - /esm@3.2.25: - resolution: {integrity: sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==} - engines: {node: '>=6'} - dev: false - optional: true - /event-lite@0.1.3: resolution: {integrity: sha512-8qz9nOz5VeD2z96elrEKD2U433+L3DWdUdDkOINLGOJvx1GsMBbMn0aCeu28y8/e85A6mCigBiFlYMnTBEGlSw==} dev: false @@ -74,14 +42,6 @@ packages: resolution: {integrity: sha512-39F7TBIV0G7gTelxwbEqnwhp90eqCPON1k0NwNfwhgKn4Co4ybUbj2pECcXT0B3ztRKZ7Pw1JujUUgmQJHcVAQ==} dev: false - /find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - dev: false - /hdr-histogram-js@2.0.3: resolution: {integrity: sha512-Hkn78wwzWHNCp2uarhzQ2SGFLU3JY8SBDDd3TAABK4fc30wm+MuPOrg5QVFVfkKOQd6Bfz3ukJEI+q9sXEkK1g==} dependencies: @@ -102,31 +62,10 @@ packages: resolution: {integrity: sha512-v7cSY1J8ydZ0GyjUHqF+1bshJ6cnEVLo9EnjB8p+4HDRPZc9N5jjmvUV7NvEsqQOKyH0pmIBFWXVQbiS0+OBbA==} dev: false - /is-observable@2.1.0: - resolution: {integrity: sha512-DailKdLb0WU+xX8K5w7VsJhapwHLZ9jjmazqCJq4X12CTgqq73TKnbRcnSLuXYPOoLQgV5IrD7ePiX/h1vnkBw==} - engines: {node: '>=8'} - dev: false - /isarray@1.0.0: resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} dev: false - /locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - dependencies: - p-locate: 5.0.0 - dev: false - - /microjob@0.7.0: - resolution: {integrity: sha512-ofDpqaVEv67ymCYdCE8eIVMCJY0H/hAtGxYmi1pXjtNkLOM0UUuUDshA1YLdVFwPwwt5+SW9EbBtSfsNokf+PA==} - engines: {node: '>=10.5.0', npm: '>= 6.0.0'} - dev: false - - /ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: false - /msgpack-lite@0.1.26: resolution: {integrity: sha512-SZ2IxeqZ1oRFGo0xFGbvBJWMp3yLIY9rlIJyxy8CGrwZn1f0ZK4r6jV/AM1r0FZMDUkWkglOk/eeKIL9g77Nxw==} hasBin: true @@ -162,33 +101,10 @@ packages: resolution: {integrity: sha512-7TXAhpMm+jO4MfESxYLtMGSnJWv+itdNHMdaFmeZuPXxwFGU90mtEB42BciUULXOUAxYBfXILAuvrSG3rQZ7mw==} dev: false - /observable-fns@0.6.1: - resolution: {integrity: sha512-9gRK4+sRWzeN6AOewNBTLXir7Zl/i3GB6Yl26gK4flxz8BXVpD3kt8amREmWNb0mxYOGDotvE5a4N+PtGGKdkg==} - dev: false - - /p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - dependencies: - yocto-queue: 0.1.0 - dev: false - - /p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - dependencies: - p-limit: 3.1.0 - dev: false - /pako@1.0.11: resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} dev: false - /path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - dev: false - /piscina@4.0.0: resolution: {integrity: sha512-641nAmJS4k4iqpNUqfggqUBUMmlw0ZoM5VZKdQkV2e970Inn3Tk9kroCc1wpsYLD07vCwpys5iY0d3xI/9WkTg==} dependencies: @@ -199,48 +115,12 @@ packages: nice-napi: 1.0.2 dev: false - /pkg-dir@5.0.0: - resolution: {integrity: sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==} - engines: {node: '>=10'} - dependencies: - find-up: 5.0.0 - dev: false - /poolifier@2.6.3: resolution: {integrity: sha512-5kQjBXqeW8dbzlmDxKRvlC6Vi2zBrpiviVb53rupdQWIsivB6waApeJT4ayhVVLqKGrvLVr9HAeBMHBJaNUDVA==} engines: {node: '>=16.14.0', pnpm: '>=8.6.0'} requiresBuild: true dev: false - /threads@1.7.0: - resolution: {integrity: sha512-Mx5NBSHX3sQYR6iI9VYbgHKBLisyB+xROCBGjjWm1O9wb9vfLxdaGtmT/KCjUqMsSNW6nERzCW3T6H43LqjDZQ==} - dependencies: - callsites: 3.1.0 - debug: 4.3.4 - is-observable: 2.1.0 - observable-fns: 0.6.1 - optionalDependencies: - tiny-worker: 2.3.0 - transitivePeerDependencies: - - supports-color - dev: false - - /threadwork@0.6.0: - resolution: {integrity: sha512-NzKDArTtcSAq0jlMdiC04+fuls5nWn1ziptmMTBwPyjKxZk+aQvw/LVVf3IW3tUKz4vLGJ2XE+PXDMoJuoNEfQ==} - engines: {node: '>=12'} - dependencies: - callsites: 3.1.0 - pkg-dir: 5.0.0 - dev: false - - /tiny-worker@2.3.0: - resolution: {integrity: sha512-pJ70wq5EAqTAEl9IkGzA+fN0836rycEuz2Cn6yeZ6FRzlVS5IDOkFHpIoEsksPRQV34GDqXm65+OlnZqUSyK2g==} - requiresBuild: true - dependencies: - esm: 3.2.25 - dev: false - optional: true - /tinypool@0.5.0: resolution: {integrity: sha512-paHQtnrlS1QZYKF/GnLoOM/DN9fqaGOFbCbxzAhwniySnzl9Ebk8w73/dd34DAhe/obUbPAOldTyYXQZxnPBPQ==} engines: {node: '>=14.0.0'} @@ -256,8 +136,3 @@ packages: /workerpool@6.4.0: resolution: {integrity: sha512-i3KR1mQMNwY2wx20ozq2EjISGtQWDIfV56We+yGJ5yDs8jTwQiLLaqHlkBHITlCuJnYlVRmXegxFxZg7gqI++A==} dev: false - - /yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - dev: false diff --git a/benchmarks/versus-external-pools/pool-threadwork.mjs b/benchmarks/versus-external-pools/pool-threadwork.mjs deleted file mode 100644 index 545c013e..00000000 --- a/benchmarks/versus-external-pools/pool-threadwork.mjs +++ /dev/null @@ -1,9 +0,0 @@ -// IMPORT LIBRARIES -import { ThreadPool } from 'threadwork' -// FINISH IMPORT LIBRARIES -// IMPORT FUNCTION TO BENCH -import functionToBench from './functions/function-to-bench.js' -// FINISH IMPORT FUNCTION TO BENCH -const size = parseInt(process.env.POOL_SIZE) - -export default new ThreadPool({ task: functionToBench, size }) diff --git a/benchmarks/versus-external-pools/threadjs.mjs b/benchmarks/versus-external-pools/threadjs.mjs deleted file mode 100644 index f6c06eec..00000000 --- a/benchmarks/versus-external-pools/threadjs.mjs +++ /dev/null @@ -1,35 +0,0 @@ -// IMPORT LIBRARIES -import { Worker, spawn } from 'threads' -// FINISH IMPORT LIBRARIES -const size = parseInt(process.env.POOL_SIZE) -const iterations = parseInt(process.env.NUM_ITERATIONS) -const data = { - test: 'MYBENCH', - taskType: process.env.TASK_TYPE, - taskSize: parseInt(process.env.TASK_SIZE) -} - -// Threads.js is not really a pool so we need to write few additional code -const workers = [] -async function poolify () { - for (let i = 0; i < size; i++) { - const worker = await spawn( - new Worker('./workers/threadjs/function-to-bench-worker.mjs') - ) - workers.push(worker) - } -} - -async function run () { - await poolify() - const promises = [] - for (let i = 0; i < iterations; i++) { - const worker = workers[i % size] - promises.push(worker.exposedFunction(data)) - } - await Promise.all(promises) - // eslint-disable-next-line n/no-process-exit - process.exit() -} - -await run() diff --git a/benchmarks/versus-external-pools/workers/threadjs/function-to-bench-worker.mjs b/benchmarks/versus-external-pools/workers/threadjs/function-to-bench-worker.mjs deleted file mode 100644 index 8217e22d..00000000 --- a/benchmarks/versus-external-pools/workers/threadjs/function-to-bench-worker.mjs +++ /dev/null @@ -1,8 +0,0 @@ -import { expose } from 'threads/worker' -import functionToBench from '../../functions/function-to-bench.js' - -expose({ - exposedFunction (data) { - return functionToBench(data) - } -}) diff --git a/package.json b/package.json index da45fca7..63ae7d5a 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ }, "volta": { "node": "20.3.1", - "pnpm": "8.6.3" + "pnpm": "8.6.5" }, "repository": { "type": "git", @@ -107,8 +107,8 @@ "@rollup/plugin-terser": "^0.4.3", "@rollup/plugin-typescript": "^11.1.1", "@types/node": "^20.3.1", - "@typescript-eslint/eslint-plugin": "^5.60.0", - "@typescript-eslint/parser": "^5.60.0", + "@typescript-eslint/eslint-plugin": "^5.60.1", + "@typescript-eslint/parser": "^5.60.1", "benny": "^3.7.1", "c8": "^8.0.0", "eslint": "^8.43.0", @@ -117,7 +117,7 @@ "eslint-define-config": "^1.21.0", "eslint-import-resolver-typescript": "^3.5.5", "eslint-plugin-import": "^2.27.5", - "eslint-plugin-jsdoc": "^46.2.6", + "eslint-plugin-jsdoc": "^46.3.0", "eslint-plugin-n": "^16.0.1", "eslint-plugin-promise": "^6.1.1", "eslint-plugin-spellcheck": "^0.0.20", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a4d3ae64..d98662de 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -27,11 +27,11 @@ devDependencies: specifier: ^20.3.1 version: 20.3.1 '@typescript-eslint/eslint-plugin': - specifier: ^5.60.0 - version: 5.60.0(@typescript-eslint/parser@5.60.0)(eslint@8.43.0)(typescript@5.1.3) + specifier: ^5.60.1 + version: 5.60.1(@typescript-eslint/parser@5.60.1)(eslint@8.43.0)(typescript@5.1.3) '@typescript-eslint/parser': - specifier: ^5.60.0 - version: 5.60.0(eslint@8.43.0)(typescript@5.1.3) + specifier: ^5.60.1 + version: 5.60.1(eslint@8.43.0)(typescript@5.1.3) benny: specifier: ^3.7.1 version: 3.7.1 @@ -46,19 +46,19 @@ devDependencies: version: 17.1.0(eslint-plugin-import@2.27.5)(eslint-plugin-n@16.0.1)(eslint-plugin-promise@6.1.1)(eslint@8.43.0) eslint-config-standard-with-typescript: specifier: ^35.0.0 - version: 35.0.0(@typescript-eslint/eslint-plugin@5.60.0)(eslint-plugin-import@2.27.5)(eslint-plugin-n@16.0.1)(eslint-plugin-promise@6.1.1)(eslint@8.43.0)(typescript@5.1.3) + version: 35.0.0(@typescript-eslint/eslint-plugin@5.60.1)(eslint-plugin-import@2.27.5)(eslint-plugin-n@16.0.1)(eslint-plugin-promise@6.1.1)(eslint@8.43.0)(typescript@5.1.3) eslint-define-config: specifier: ^1.21.0 version: 1.21.0 eslint-import-resolver-typescript: specifier: ^3.5.5 - version: 3.5.5(@typescript-eslint/parser@5.60.0)(eslint-plugin-import@2.27.5)(eslint@8.43.0) + version: 3.5.5(@typescript-eslint/parser@5.60.1)(eslint-plugin-import@2.27.5)(eslint@8.43.0) eslint-plugin-import: specifier: ^2.27.5 - version: 2.27.5(@typescript-eslint/parser@5.60.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.43.0) + version: 2.27.5(@typescript-eslint/parser@5.60.1)(eslint-import-resolver-typescript@3.5.5)(eslint@8.43.0) eslint-plugin-jsdoc: - specifier: ^46.2.6 - version: 46.2.6(eslint@8.43.0) + specifier: ^46.3.0 + version: 46.3.0(eslint@8.43.0) eslint-plugin-n: specifier: ^16.0.1 version: 16.0.1(eslint@8.43.0) @@ -912,8 +912,8 @@ packages: '@types/yargs-parser': 21.0.0 dev: true - /@typescript-eslint/eslint-plugin@5.60.0(@typescript-eslint/parser@5.60.0)(eslint@8.43.0)(typescript@5.1.3): - resolution: {integrity: sha512-78B+anHLF1TI8Jn/cD0Q00TBYdMgjdOn980JfAVa9yw5sop8nyTfVOQAv6LWywkOGLclDBtv5z3oxN4w7jxyNg==} + /@typescript-eslint/eslint-plugin@5.60.1(@typescript-eslint/parser@5.60.1)(eslint@8.43.0)(typescript@5.1.3): + resolution: {integrity: sha512-KSWsVvsJsLJv3c4e73y/Bzt7OpqMCADUO846bHcuWYSYM19bldbAeDv7dYyV0jwkbMfJ2XdlzwjhXtuD7OY6bw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: '@typescript-eslint/parser': ^5.0.0 @@ -924,10 +924,10 @@ packages: optional: true dependencies: '@eslint-community/regexpp': 4.5.1 - '@typescript-eslint/parser': 5.60.0(eslint@8.43.0)(typescript@5.1.3) - '@typescript-eslint/scope-manager': 5.60.0 - '@typescript-eslint/type-utils': 5.60.0(eslint@8.43.0)(typescript@5.1.3) - '@typescript-eslint/utils': 5.60.0(eslint@8.43.0)(typescript@5.1.3) + '@typescript-eslint/parser': 5.60.1(eslint@8.43.0)(typescript@5.1.3) + '@typescript-eslint/scope-manager': 5.60.1 + '@typescript-eslint/type-utils': 5.60.1(eslint@8.43.0)(typescript@5.1.3) + '@typescript-eslint/utils': 5.60.1(eslint@8.43.0)(typescript@5.1.3) debug: 4.3.4(supports-color@8.1.1) eslint: 8.43.0 grapheme-splitter: 1.0.4 @@ -940,8 +940,8 @@ packages: - supports-color dev: true - /@typescript-eslint/parser@5.60.0(eslint@8.43.0)(typescript@5.1.3): - resolution: {integrity: sha512-jBONcBsDJ9UoTWrARkRRCgDz6wUggmH5RpQVlt7BimSwaTkTjwypGzKORXbR4/2Hqjk9hgwlon2rVQAjWNpkyQ==} + /@typescript-eslint/parser@5.60.1(eslint@8.43.0)(typescript@5.1.3): + resolution: {integrity: sha512-pHWlc3alg2oSMGwsU/Is8hbm3XFbcrb6P5wIxcQW9NsYBfnrubl/GhVVD/Jm/t8HXhA2WncoIRfBtnCgRGV96Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -950,9 +950,9 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 5.60.0 - '@typescript-eslint/types': 5.60.0 - '@typescript-eslint/typescript-estree': 5.60.0(typescript@5.1.3) + '@typescript-eslint/scope-manager': 5.60.1 + '@typescript-eslint/types': 5.60.1 + '@typescript-eslint/typescript-estree': 5.60.1(typescript@5.1.3) debug: 4.3.4(supports-color@8.1.1) eslint: 8.43.0 typescript: 5.1.3 @@ -960,16 +960,16 @@ packages: - supports-color dev: true - /@typescript-eslint/scope-manager@5.60.0: - resolution: {integrity: sha512-hakuzcxPwXi2ihf9WQu1BbRj1e/Pd8ZZwVTG9kfbxAMZstKz8/9OoexIwnmLzShtsdap5U/CoQGRCWlSuPbYxQ==} + /@typescript-eslint/scope-manager@5.60.1: + resolution: {integrity: sha512-Dn/LnN7fEoRD+KspEOV0xDMynEmR3iSHdgNsarlXNLGGtcUok8L4N71dxUgt3YvlO8si7E+BJ5Fe3wb5yUw7DQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - '@typescript-eslint/types': 5.60.0 - '@typescript-eslint/visitor-keys': 5.60.0 + '@typescript-eslint/types': 5.60.1 + '@typescript-eslint/visitor-keys': 5.60.1 dev: true - /@typescript-eslint/type-utils@5.60.0(eslint@8.43.0)(typescript@5.1.3): - resolution: {integrity: sha512-X7NsRQddORMYRFH7FWo6sA9Y/zbJ8s1x1RIAtnlj6YprbToTiQnM6vxcMu7iYhdunmoC0rUWlca13D5DVHkK2g==} + /@typescript-eslint/type-utils@5.60.1(eslint@8.43.0)(typescript@5.1.3): + resolution: {integrity: sha512-vN6UztYqIu05nu7JqwQGzQKUJctzs3/Hg7E2Yx8rz9J+4LgtIDFWjjl1gm3pycH0P3mHAcEUBd23LVgfrsTR8A==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: '*' @@ -978,8 +978,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 5.60.0(typescript@5.1.3) - '@typescript-eslint/utils': 5.60.0(eslint@8.43.0)(typescript@5.1.3) + '@typescript-eslint/typescript-estree': 5.60.1(typescript@5.1.3) + '@typescript-eslint/utils': 5.60.1(eslint@8.43.0)(typescript@5.1.3) debug: 4.3.4(supports-color@8.1.1) eslint: 8.43.0 tsutils: 3.21.0(typescript@5.1.3) @@ -988,13 +988,13 @@ packages: - supports-color dev: true - /@typescript-eslint/types@5.60.0: - resolution: {integrity: sha512-ascOuoCpNZBccFVNJRSC6rPq4EmJ2NkuoKnd6LDNyAQmdDnziAtxbCGWCbefG1CNzmDvd05zO36AmB7H8RzKPA==} + /@typescript-eslint/types@5.60.1: + resolution: {integrity: sha512-zDcDx5fccU8BA0IDZc71bAtYIcG9PowaOwaD8rjYbqwK7dpe/UMQl3inJ4UtUK42nOCT41jTSCwg76E62JpMcg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /@typescript-eslint/typescript-estree@5.60.0(typescript@5.1.3): - resolution: {integrity: sha512-R43thAuwarC99SnvrBmh26tc7F6sPa2B3evkXp/8q954kYL6Ro56AwASYWtEEi+4j09GbiNAHqYwNNZuNlARGQ==} + /@typescript-eslint/typescript-estree@5.60.1(typescript@5.1.3): + resolution: {integrity: sha512-hkX70J9+2M2ZT6fhti5Q2FoU9zb+GeZK2SLP1WZlvUDqdMbEKhexZODD1WodNRyO8eS+4nScvT0dts8IdaBzfw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: typescript: '*' @@ -1002,8 +1002,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 5.60.0 - '@typescript-eslint/visitor-keys': 5.60.0 + '@typescript-eslint/types': 5.60.1 + '@typescript-eslint/visitor-keys': 5.60.1 debug: 4.3.4(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 @@ -1014,8 +1014,8 @@ packages: - supports-color dev: true - /@typescript-eslint/utils@5.60.0(eslint@8.43.0)(typescript@5.1.3): - resolution: {integrity: sha512-ba51uMqDtfLQ5+xHtwlO84vkdjrqNzOnqrnwbMHMRY8Tqeme8C2Q8Fc7LajfGR+e3/4LoYiWXUM6BpIIbHJ4hQ==} + /@typescript-eslint/utils@5.60.1(eslint@8.43.0)(typescript@5.1.3): + resolution: {integrity: sha512-tiJ7FFdFQOWssFa3gqb94Ilexyw0JVxj6vBzaSpfN/8IhoKkDuSAenUKvsSHw2A/TMpJb26izIszTXaqygkvpQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -1023,9 +1023,9 @@ packages: '@eslint-community/eslint-utils': 4.4.0(eslint@8.43.0) '@types/json-schema': 7.0.12 '@types/semver': 7.5.0 - '@typescript-eslint/scope-manager': 5.60.0 - '@typescript-eslint/types': 5.60.0 - '@typescript-eslint/typescript-estree': 5.60.0(typescript@5.1.3) + '@typescript-eslint/scope-manager': 5.60.1 + '@typescript-eslint/types': 5.60.1 + '@typescript-eslint/typescript-estree': 5.60.1(typescript@5.1.3) eslint: 8.43.0 eslint-scope: 5.1.1 semver: 7.5.3 @@ -1034,11 +1034,11 @@ packages: - typescript dev: true - /@typescript-eslint/visitor-keys@5.60.0: - resolution: {integrity: sha512-wm9Uz71SbCyhUKgcaPRauBdTegUyY/ZWl8gLwD/i/ybJqscrrdVSFImpvUz16BLPChIeKBK5Fa9s6KDQjsjyWw==} + /@typescript-eslint/visitor-keys@5.60.1: + resolution: {integrity: sha512-xEYIxKcultP6E/RMKqube11pGjXH1DCo60mQoWhVYyKfLkwbIVVjYxmOenNMxILx0TjCujPTjjnTIVzm09TXIw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - '@typescript-eslint/types': 5.60.0 + '@typescript-eslint/types': 5.60.1 eslint-visitor-keys: 3.4.1 dev: true @@ -2158,7 +2158,7 @@ packages: eslint-plugin-react: 7.32.2(eslint@8.43.0) dev: true - /eslint-config-standard-with-typescript@23.0.0(@typescript-eslint/eslint-plugin@5.60.0)(eslint-plugin-import@2.27.5)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.43.0)(typescript@5.1.3): + /eslint-config-standard-with-typescript@23.0.0(@typescript-eslint/eslint-plugin@5.60.1)(eslint-plugin-import@2.27.5)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.43.0)(typescript@5.1.3): resolution: {integrity: sha512-iaaWifImn37Z1OXbNW1es7KI+S7D408F9ys0bpaQf2temeBWlvb0Nc5qHkOgYaRb5QxTZT32GGeN1gtswASOXA==} peerDependencies: '@typescript-eslint/eslint-plugin': ^5.0.0 @@ -2168,11 +2168,11 @@ packages: eslint-plugin-promise: ^6.0.0 typescript: '*' dependencies: - '@typescript-eslint/eslint-plugin': 5.60.0(@typescript-eslint/parser@5.60.0)(eslint@8.43.0)(typescript@5.1.3) - '@typescript-eslint/parser': 5.60.0(eslint@8.43.0)(typescript@5.1.3) + '@typescript-eslint/eslint-plugin': 5.60.1(@typescript-eslint/parser@5.60.1)(eslint@8.43.0)(typescript@5.1.3) + '@typescript-eslint/parser': 5.60.1(eslint@8.43.0)(typescript@5.1.3) eslint: 8.43.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.43.0) - eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.60.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.43.0) + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.60.1)(eslint-import-resolver-typescript@3.5.5)(eslint@8.43.0) eslint-plugin-n: 15.7.0(eslint@8.43.0) eslint-plugin-promise: 6.1.1(eslint@8.43.0) typescript: 5.1.3 @@ -2180,7 +2180,7 @@ packages: - supports-color dev: true - /eslint-config-standard-with-typescript@35.0.0(@typescript-eslint/eslint-plugin@5.60.0)(eslint-plugin-import@2.27.5)(eslint-plugin-n@16.0.1)(eslint-plugin-promise@6.1.1)(eslint@8.43.0)(typescript@5.1.3): + /eslint-config-standard-with-typescript@35.0.0(@typescript-eslint/eslint-plugin@5.60.1)(eslint-plugin-import@2.27.5)(eslint-plugin-n@16.0.1)(eslint-plugin-promise@6.1.1)(eslint@8.43.0)(typescript@5.1.3): resolution: {integrity: sha512-Xa7DY9GgduZyp0qmXxBF0/dB+Vm4/DgWu1lGpNLJV2d46aCaUxTKDEnkzjUWX/1O9S0a+Dhnw7A4oI0JpYzwtw==} peerDependencies: '@typescript-eslint/eslint-plugin': ^5.50.0 @@ -2190,11 +2190,11 @@ packages: eslint-plugin-promise: ^6.0.0 typescript: '*' dependencies: - '@typescript-eslint/eslint-plugin': 5.60.0(@typescript-eslint/parser@5.60.0)(eslint@8.43.0)(typescript@5.1.3) - '@typescript-eslint/parser': 5.60.0(eslint@8.43.0)(typescript@5.1.3) + '@typescript-eslint/eslint-plugin': 5.60.1(@typescript-eslint/parser@5.60.1)(eslint@8.43.0)(typescript@5.1.3) + '@typescript-eslint/parser': 5.60.1(eslint@8.43.0)(typescript@5.1.3) eslint: 8.43.0 eslint-config-standard: 17.0.0(eslint-plugin-import@2.27.5)(eslint-plugin-n@16.0.1)(eslint-plugin-promise@6.1.1)(eslint@8.43.0) - eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.60.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.43.0) + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.60.1)(eslint-import-resolver-typescript@3.5.5)(eslint@8.43.0) eslint-plugin-n: 16.0.1(eslint@8.43.0) eslint-plugin-promise: 6.1.1(eslint@8.43.0) typescript: 5.1.3 @@ -2211,7 +2211,7 @@ packages: eslint-plugin-promise: ^6.0.0 dependencies: eslint: 8.43.0 - eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.60.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.43.0) + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.60.1)(eslint-import-resolver-typescript@3.5.5)(eslint@8.43.0) eslint-plugin-n: 15.7.0(eslint@8.43.0) eslint-plugin-promise: 6.1.1(eslint@8.43.0) dev: true @@ -2225,7 +2225,7 @@ packages: eslint-plugin-promise: ^6.0.0 dependencies: eslint: 8.43.0 - eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.60.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.43.0) + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.60.1)(eslint-import-resolver-typescript@3.5.5)(eslint@8.43.0) eslint-plugin-n: 16.0.1(eslint@8.43.0) eslint-plugin-promise: 6.1.1(eslint@8.43.0) dev: true @@ -2240,7 +2240,7 @@ packages: eslint-plugin-promise: ^6.0.0 dependencies: eslint: 8.43.0 - eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.60.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.43.0) + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.60.1)(eslint-import-resolver-typescript@3.5.5)(eslint@8.43.0) eslint-plugin-n: 16.0.1(eslint@8.43.0) eslint-plugin-promise: 6.1.1(eslint@8.43.0) dev: true @@ -2260,7 +2260,7 @@ packages: - supports-color dev: true - /eslint-import-resolver-typescript@3.5.5(@typescript-eslint/parser@5.60.0)(eslint-plugin-import@2.27.5)(eslint@8.43.0): + /eslint-import-resolver-typescript@3.5.5(@typescript-eslint/parser@5.60.1)(eslint-plugin-import@2.27.5)(eslint@8.43.0): resolution: {integrity: sha512-TdJqPHs2lW5J9Zpe17DZNQuDnox4xo2o+0tE7Pggain9Rbc19ik8kFtXdxZ250FVx2kF4vlt2RSf4qlUpG7bhw==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: @@ -2270,8 +2270,8 @@ packages: debug: 4.3.4(supports-color@8.1.1) enhanced-resolve: 5.15.0 eslint: 8.43.0 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.60.0)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.43.0) - eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.60.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.43.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.60.1)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.43.0) + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.60.1)(eslint-import-resolver-typescript@3.5.5)(eslint@8.43.0) get-tsconfig: 4.6.0 globby: 13.2.0 is-core-module: 2.12.1 @@ -2284,7 +2284,7 @@ packages: - supports-color dev: true - /eslint-module-utils@2.8.0(@typescript-eslint/parser@5.60.0)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.43.0): + /eslint-module-utils@2.8.0(@typescript-eslint/parser@5.60.1)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.43.0): resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} engines: {node: '>=4'} peerDependencies: @@ -2305,11 +2305,11 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 5.60.0(eslint@8.43.0)(typescript@5.1.3) + '@typescript-eslint/parser': 5.60.1(eslint@8.43.0)(typescript@5.1.3) debug: 3.2.7 eslint: 8.43.0 eslint-import-resolver-node: 0.3.7 - eslint-import-resolver-typescript: 3.5.5(@typescript-eslint/parser@5.60.0)(eslint-plugin-import@2.27.5)(eslint@8.43.0) + eslint-import-resolver-typescript: 3.5.5(@typescript-eslint/parser@5.60.1)(eslint-plugin-import@2.27.5)(eslint@8.43.0) transitivePeerDependencies: - supports-color dev: true @@ -2336,7 +2336,7 @@ packages: regexpp: 3.2.0 dev: true - /eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.60.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.43.0): + /eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.60.1)(eslint-import-resolver-typescript@3.5.5)(eslint@8.43.0): resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==} engines: {node: '>=4'} peerDependencies: @@ -2346,7 +2346,7 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 5.60.0(eslint@8.43.0)(typescript@5.1.3) + '@typescript-eslint/parser': 5.60.1(eslint@8.43.0)(typescript@5.1.3) array-includes: 3.1.6 array.prototype.flat: 1.3.1 array.prototype.flatmap: 1.3.1 @@ -2354,7 +2354,7 @@ packages: doctrine: 2.1.0 eslint: 8.43.0 eslint-import-resolver-node: 0.3.7 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.60.0)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.43.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.60.1)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.43.0) has: 1.0.3 is-core-module: 2.12.1 is-glob: 4.0.3 @@ -2369,8 +2369,8 @@ packages: - supports-color dev: true - /eslint-plugin-jsdoc@46.2.6(eslint@8.43.0): - resolution: {integrity: sha512-zIaK3zbSrKuH12bP+SPybPgcHSM6MFzh3HFeaODzmsF1N8C1l8dzJ22cW1aq4g0+nayU1VMjmNf7hg0dpShLrA==} + /eslint-plugin-jsdoc@46.3.0(eslint@8.43.0): + resolution: {integrity: sha512-nfSvsR8YJRZyKrWwcXPSQyQC8jllfdEjcRhTXFr7RxfB5Wyl7AxrfjCUz72WwalkXMF4u+R6F/oDoW46ah69HQ==} engines: {node: '>=16'} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -5736,12 +5736,12 @@ packages: peerDependencies: typescript: '*' dependencies: - '@typescript-eslint/eslint-plugin': 5.60.0(@typescript-eslint/parser@5.60.0)(eslint@8.43.0)(typescript@5.1.3) - '@typescript-eslint/parser': 5.60.0(eslint@8.43.0)(typescript@5.1.3) + '@typescript-eslint/eslint-plugin': 5.60.1(@typescript-eslint/parser@5.60.1)(eslint@8.43.0)(typescript@5.1.3) + '@typescript-eslint/parser': 5.60.1(eslint@8.43.0)(typescript@5.1.3) eslint: 8.43.0 eslint-config-standard-jsx: 11.0.0(eslint-plugin-react@7.32.2)(eslint@8.43.0) - eslint-config-standard-with-typescript: 23.0.0(@typescript-eslint/eslint-plugin@5.60.0)(eslint-plugin-import@2.27.5)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.43.0)(typescript@5.1.3) - eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.60.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.43.0) + eslint-config-standard-with-typescript: 23.0.0(@typescript-eslint/eslint-plugin@5.60.1)(eslint-plugin-import@2.27.5)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.43.0)(typescript@5.1.3) + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.60.1)(eslint-import-resolver-typescript@3.5.5)(eslint@8.43.0) eslint-plugin-n: 15.7.0(eslint@8.43.0) eslint-plugin-promise: 6.1.1(eslint@8.43.0) eslint-plugin-react: 7.32.2(eslint@8.43.0) diff --git a/src/index.ts b/src/index.ts index 4730ad65..367c205c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -44,11 +44,7 @@ export type { } from './pools/selection-strategies/selection-strategies-types' export type { WorkerChoiceStrategyContext } from './pools/selection-strategies/worker-choice-strategy-context' export { DynamicThreadPool } from './pools/thread/dynamic' -export { - FixedThreadPool, - type ThreadPoolOptions, - type ThreadWorkerWithMessageChannel -} from './pools/thread/fixed' +export { FixedThreadPool, type ThreadPoolOptions } from './pools/thread/fixed' export type { AbstractWorker } from './worker/abstract-worker' export { ClusterWorker } from './worker/cluster-worker' export { ThreadWorker } from './worker/thread-worker' @@ -61,7 +57,6 @@ export type { WorkerSyncFunction } from './worker/worker-functions' export type { - Draft, MessageValue, PromiseResponseWrapper, TaskError, diff --git a/src/pools/abstract-pool.ts b/src/pools/abstract-pool.ts index 6ebb3059..da8a5eb6 100644 --- a/src/pools/abstract-pool.ts +++ b/src/pools/abstract-pool.ts @@ -21,7 +21,13 @@ import { type TasksQueueOptions, type WorkerType } from './pool' -import type { IWorker, Task, WorkerNode, WorkerUsage } from './worker' +import type { + IWorker, + MessageHandler, + Task, + WorkerNode, + WorkerUsage +} from './worker' import { Measurements, WorkerChoiceStrategies, @@ -34,8 +40,8 @@ import { WorkerChoiceStrategyContext } from './selection-strategies/worker-choic * Base class that implements some shared logic for all poolifier pools. * * @typeParam Worker - Type of worker which manages this pool. - * @typeParam Data - Type of data sent to the worker. This can only be serializable data. - * @typeParam Response - Type of execution response. This can only be serializable data. + * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. + * @typeParam Response - Type of execution response. This can only be structured-cloneable data. */ export abstract class AbstractPool< Worker extends IWorker, @@ -670,9 +676,12 @@ export abstract class AbstractPool< * @param worker - The worker which should register a listener. * @param listener - The message listener callback. */ - protected abstract registerWorkerMessageListener< - Message extends Data | Response - >(worker: Worker, listener: (message: MessageValue) => void): void + private registerWorkerMessageListener( + worker: Worker, + listener: (message: MessageValue) => void + ): void { + worker.on('message', listener as MessageHandler) + } /** * Creates a new worker. @@ -684,11 +693,12 @@ export abstract class AbstractPool< /** * Function that can be hooked up when a worker has been newly created and moved to the pool worker nodes. * - * Can be used to update the `maxListeners` or binding the `main-worker`\<-\>`worker` connection if not bind by default. - * * @param worker - The newly created worker. */ - protected abstract afterWorkerSetup (worker: Worker): void + private afterWorkerSetup (worker: Worker): void { + // Listen to worker messages. + this.registerWorkerMessageListener(worker, this.workerListener()) + } /** * Creates a new worker and sets it up completely in the pool worker nodes. diff --git a/src/pools/cluster/dynamic.ts b/src/pools/cluster/dynamic.ts index b75b3f80..a9ccd697 100644 --- a/src/pools/cluster/dynamic.ts +++ b/src/pools/cluster/dynamic.ts @@ -7,8 +7,8 @@ import { type ClusterPoolOptions, FixedClusterPool } from './fixed' * This cluster pool creates new workers when the others are busy, up to the maximum number of workers. * When the maximum number of workers is reached and workers are busy, an event is emitted. If you want to listen to this event, use the pool's `emitter`. * - * @typeParam Data - Type of data sent to the worker. This can only be serializable data. - * @typeParam Response - Type of execution response. This can only be serializable data. + * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. + * @typeParam Response - Type of execution response. This can only be structured-cloneable data. * @author [Christopher Quadflieg](https://github.com/Shinigami92) * @since 2.0.0 */ diff --git a/src/pools/cluster/fixed.ts b/src/pools/cluster/fixed.ts index 3f56c858..7a3b630b 100644 --- a/src/pools/cluster/fixed.ts +++ b/src/pools/cluster/fixed.ts @@ -32,8 +32,8 @@ export interface ClusterPoolOptions extends PoolOptions { * * It is possible to perform tasks in sync or asynchronous mode as you prefer. * - * @typeParam Data - Type of data sent to the worker. This can only be serializable data. - * @typeParam Response - Type of execution response. This can only be serializable data. + * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. + * @typeParam Response - Type of execution response. This can only be structured-cloneable data. * @author [Christopher Quadflieg](https://github.com/Shinigami92) * @since 2.0.0 */ @@ -80,25 +80,11 @@ export class FixedClusterPool< worker.send(message) } - /** @inheritDoc */ - protected registerWorkerMessageListener( - worker: Worker, - listener: (message: MessageValue) => void - ): void { - worker.on('message', listener) - } - /** @inheritDoc */ protected createWorker (): Worker { return cluster.fork(this.opts.env) } - /** @inheritDoc */ - protected afterWorkerSetup (worker: Worker): void { - // Listen to worker messages. - this.registerWorkerMessageListener(worker, super.workerListener()) - } - /** @inheritDoc */ protected get type (): PoolType { return PoolTypes.fixed diff --git a/src/pools/pool.ts b/src/pools/pool.ts index 257b0d64..ef93982f 100644 --- a/src/pools/pool.ts +++ b/src/pools/pool.ts @@ -152,8 +152,8 @@ export interface PoolOptions { * Contract definition for a poolifier pool. * * @typeParam Worker - Type of worker which manages this pool. - * @typeParam Data - Type of data sent to the worker. This can only be serializable data. - * @typeParam Response - Type of execution response. This can only be serializable data. + * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. + * @typeParam Response - Type of execution response. This can only be structured-cloneable data. */ export interface IPool< Worker extends IWorker, @@ -182,7 +182,7 @@ export interface IPool< /** * Executes the specified function in the worker constructor with the task data input parameter. * - * @param data - The task input data for the specified worker function. This can only be serializable data. + * @param data - The task input data for the specified worker function. This can only be structured-cloneable data. * @param name - The name of the worker function to execute. If not specified, the default worker function will be executed. * @returns Promise that will be fulfilled when the task is completed. */ diff --git a/src/pools/selection-strategies/abstract-worker-choice-strategy.ts b/src/pools/selection-strategies/abstract-worker-choice-strategy.ts index 121647b6..5172a181 100644 --- a/src/pools/selection-strategies/abstract-worker-choice-strategy.ts +++ b/src/pools/selection-strategies/abstract-worker-choice-strategy.ts @@ -13,8 +13,8 @@ import type { * Worker choice strategy abstract base class. * * @typeParam Worker - Type of worker which manages the strategy. - * @typeParam Data - Type of data sent to the worker. This can only be serializable data. - * @typeParam Response - Type of execution response. This can only be serializable data. + * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. + * @typeParam Response - Type of execution response. This can only be structured-cloneable data. */ export abstract class AbstractWorkerChoiceStrategy< Worker extends IWorker, diff --git a/src/pools/selection-strategies/fair-share-worker-choice-strategy.ts b/src/pools/selection-strategies/fair-share-worker-choice-strategy.ts index 7b3ad3f7..9ccec752 100644 --- a/src/pools/selection-strategies/fair-share-worker-choice-strategy.ts +++ b/src/pools/selection-strategies/fair-share-worker-choice-strategy.ts @@ -14,8 +14,8 @@ import { * Loosely modeled after the fair queueing algorithm: https://en.wikipedia.org/wiki/Fair_queuing. * * @typeParam Worker - Type of worker which manages the strategy. - * @typeParam Data - Type of data sent to the worker. This can only be serializable data. - * @typeParam Response - Type of execution response. This can only be serializable data. + * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. + * @typeParam Response - Type of execution response. This can only be structured-cloneable data. */ export class FairShareWorkerChoiceStrategy< Worker extends IWorker, diff --git a/src/pools/selection-strategies/interleaved-weighted-round-robin-worker-choice-strategy.ts b/src/pools/selection-strategies/interleaved-weighted-round-robin-worker-choice-strategy.ts index 85f31483..40522c72 100644 --- a/src/pools/selection-strategies/interleaved-weighted-round-robin-worker-choice-strategy.ts +++ b/src/pools/selection-strategies/interleaved-weighted-round-robin-worker-choice-strategy.ts @@ -12,8 +12,8 @@ import type { * Selects the next worker with an interleaved weighted round robin scheduling algorithm. * * @typeParam Worker - Type of worker which manages the strategy. - * @typeParam Data - Type of data sent to the worker. This can only be serializable data. - * @typeParam Response - Type of execution response. This can only be serializable data. + * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. + * @typeParam Response - Type of execution response. This can only be structured-cloneable data. */ export class InterleavedWeightedRoundRobinWorkerChoiceStrategy< Worker extends IWorker, diff --git a/src/pools/selection-strategies/least-busy-worker-choice-strategy.ts b/src/pools/selection-strategies/least-busy-worker-choice-strategy.ts index 84476eed..31fa281a 100644 --- a/src/pools/selection-strategies/least-busy-worker-choice-strategy.ts +++ b/src/pools/selection-strategies/least-busy-worker-choice-strategy.ts @@ -12,8 +12,8 @@ import type { * Selects the least busy worker. * * @typeParam Worker - Type of worker which manages the strategy. - * @typeParam Data - Type of data sent to the worker. This can only be serializable data. - * @typeParam Response - Type of execution response. This can only be serializable data. + * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. + * @typeParam Response - Type of execution response. This can only be structured-cloneable data. */ export class LeastBusyWorkerChoiceStrategy< Worker extends IWorker, diff --git a/src/pools/selection-strategies/least-elu-worker-choice-strategy.ts b/src/pools/selection-strategies/least-elu-worker-choice-strategy.ts index 30491dce..8394ae7c 100644 --- a/src/pools/selection-strategies/least-elu-worker-choice-strategy.ts +++ b/src/pools/selection-strategies/least-elu-worker-choice-strategy.ts @@ -12,8 +12,8 @@ import type { * Selects the worker with the least ELU. * * @typeParam Worker - Type of worker which manages the strategy. - * @typeParam Data - Type of data sent to the worker. This can only be serializable data. - * @typeParam Response - Type of execution response. This can only be serializable data. + * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. + * @typeParam Response - Type of execution response. This can only be structured-cloneable data. */ export class LeastEluWorkerChoiceStrategy< Worker extends IWorker, diff --git a/src/pools/selection-strategies/least-used-worker-choice-strategy.ts b/src/pools/selection-strategies/least-used-worker-choice-strategy.ts index aaa6c21d..5c266f28 100644 --- a/src/pools/selection-strategies/least-used-worker-choice-strategy.ts +++ b/src/pools/selection-strategies/least-used-worker-choice-strategy.ts @@ -11,8 +11,8 @@ import type { * Selects the least used worker. * * @typeParam Worker - Type of worker which manages the strategy. - * @typeParam Data - Type of data sent to the worker. This can only be serializable data. - * @typeParam Response - Type of execution response. This can only be serializable data. + * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. + * @typeParam Response - Type of execution response. This can only be structured-cloneable data. */ export class LeastUsedWorkerChoiceStrategy< Worker extends IWorker, diff --git a/src/pools/selection-strategies/round-robin-worker-choice-strategy.ts b/src/pools/selection-strategies/round-robin-worker-choice-strategy.ts index 0995b350..83586093 100644 --- a/src/pools/selection-strategies/round-robin-worker-choice-strategy.ts +++ b/src/pools/selection-strategies/round-robin-worker-choice-strategy.ts @@ -12,8 +12,8 @@ import type { * Selects the next worker in a round robin fashion. * * @typeParam Worker - Type of worker which manages the strategy. - * @typeParam Data - Type of data sent to the worker. This can only be serializable data. - * @typeParam Response - Type of execution response. This can only be serializable data. + * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. + * @typeParam Response - Type of execution response. This can only be structured-cloneable data. */ export class RoundRobinWorkerChoiceStrategy< Worker extends IWorker, diff --git a/src/pools/selection-strategies/weighted-round-robin-worker-choice-strategy.ts b/src/pools/selection-strategies/weighted-round-robin-worker-choice-strategy.ts index fc6f48cf..92690080 100644 --- a/src/pools/selection-strategies/weighted-round-robin-worker-choice-strategy.ts +++ b/src/pools/selection-strategies/weighted-round-robin-worker-choice-strategy.ts @@ -14,8 +14,8 @@ import type { * Loosely modeled after the weighted round robin queueing algorithm: https://en.wikipedia.org/wiki/Weighted_round_robin. * * @typeParam Worker - Type of worker which manages the strategy. - * @typeParam Data - Type of data sent to the worker. This can only be serializable data. - * @typeParam Response - Type of execution response. This can only be serializable data. + * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. + * @typeParam Response - Type of execution response. This can only be structured-cloneable data. */ export class WeightedRoundRobinWorkerChoiceStrategy< Worker extends IWorker, diff --git a/src/pools/selection-strategies/worker-choice-strategy-context.ts b/src/pools/selection-strategies/worker-choice-strategy-context.ts index e1332b85..2bc99a7b 100644 --- a/src/pools/selection-strategies/worker-choice-strategy-context.ts +++ b/src/pools/selection-strategies/worker-choice-strategy-context.ts @@ -21,8 +21,8 @@ import { WeightedRoundRobinWorkerChoiceStrategy } from './weighted-round-robin-w * The worker choice strategy context. * * @typeParam Worker - Type of worker. - * @typeParam Data - Type of data sent to the worker. This can only be serializable data. - * @typeParam Response - Type of execution response. This can only be serializable data. + * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. + * @typeParam Response - Type of execution response. This can only be structured-cloneable data. */ export class WorkerChoiceStrategyContext< Worker extends IWorker, diff --git a/src/pools/thread/dynamic.ts b/src/pools/thread/dynamic.ts index b6d41e9e..b03ca47e 100644 --- a/src/pools/thread/dynamic.ts +++ b/src/pools/thread/dynamic.ts @@ -7,8 +7,8 @@ import { FixedThreadPool, type ThreadPoolOptions } from './fixed' * This thread pool creates new threads when the others are busy, up to the maximum number of threads. * When the maximum number of threads is reached and workers are busy, an event is emitted. If you want to listen to this event, use the pool's `emitter`. * - * @typeParam Data - Type of data sent to the worker. This can only be serializable data. - * @typeParam Response - Type of execution response. This can only be serializable data. + * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. + * @typeParam Response - Type of execution response. This can only be structured-cloneable data. * @author [Alessandro Pio Ardizio](https://github.com/pioardi) * @since 0.0.1 */ diff --git a/src/pools/thread/fixed.ts b/src/pools/thread/fixed.ts index d843144c..881e37f6 100644 --- a/src/pools/thread/fixed.ts +++ b/src/pools/thread/fixed.ts @@ -1,11 +1,10 @@ import { - MessageChannel, SHARE_ENV, Worker, type WorkerOptions, isMainThread } from 'node:worker_threads' -import type { Draft, MessageValue } from '../../utility-types' +import type { MessageValue } from '../../utility-types' import { AbstractPool } from '../abstract-pool' import { type PoolOptions, @@ -27,25 +26,20 @@ export interface ThreadPoolOptions extends PoolOptions { workerOptions?: WorkerOptions } -/** - * A thread worker with message channels for communication between main thread and thread worker. - */ -export type ThreadWorkerWithMessageChannel = Worker & Draft - /** * A thread pool with a fixed number of threads. * * It is possible to perform tasks in sync or asynchronous mode as you prefer. * - * @typeParam Data - Type of data sent to the worker. This can only be serializable data. - * @typeParam Response - Type of execution response. This can only be serializable data. + * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. + * @typeParam Response - Type of execution response. This can only be structured-cloneable data. * @author [Alessandro Pio Ardizio](https://github.com/pioardi) * @since 0.0.1 */ export class FixedThreadPool< Data = unknown, Response = unknown -> extends AbstractPool { +> extends AbstractPool { /** * Constructs a new poolifier fixed thread pool. * @@ -67,47 +61,24 @@ export class FixedThreadPool< } /** @inheritDoc */ - protected async destroyWorker ( - worker: ThreadWorkerWithMessageChannel - ): Promise { + protected async destroyWorker (worker: Worker): Promise { this.sendToWorker(worker, { kill: 1 }) await worker.terminate() } /** @inheritDoc */ - protected sendToWorker ( - worker: ThreadWorkerWithMessageChannel, - message: MessageValue - ): void { + protected sendToWorker (worker: Worker, message: MessageValue): void { worker.postMessage(message) } /** @inheritDoc */ - protected registerWorkerMessageListener( - worker: ThreadWorkerWithMessageChannel, - listener: (message: MessageValue) => void - ): void { - worker.port2?.on('message', listener) - } - - /** @inheritDoc */ - protected createWorker (): ThreadWorkerWithMessageChannel { + protected createWorker (): Worker { return new Worker(this.filePath, { env: SHARE_ENV, ...this.opts.workerOptions }) } - /** @inheritDoc */ - protected afterWorkerSetup (worker: ThreadWorkerWithMessageChannel): void { - const { port1, port2 } = new MessageChannel() - worker.postMessage({ parent: port1 }, [port1]) - worker.port1 = port1 - worker.port2 = port2 - // Listen to worker messages. - this.registerWorkerMessageListener(worker, super.workerListener()) - } - /** @inheritDoc */ protected get type (): PoolType { return PoolTypes.fixed diff --git a/src/pools/worker.ts b/src/pools/worker.ts index 4e6aea4e..07eabdfe 100644 --- a/src/pools/worker.ts +++ b/src/pools/worker.ts @@ -6,7 +6,7 @@ import type { Queue } from '../queue' */ export type MessageHandler = ( this: Worker, - m: unknown + message: unknown ) => void /** @@ -14,7 +14,7 @@ export type MessageHandler = ( */ export type ErrorHandler = ( this: Worker, - e: Error + error: Error ) => void /** @@ -27,13 +27,13 @@ export type OnlineHandler = (this: Worker) => void */ export type ExitHandler = ( this: Worker, - code: number + exitCode: number ) => void /** * Message object that is passed as a task between main worker and worker. * - * @typeParam Data - Type of data sent to the worker. This can only be serializable data. + * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. * @internal */ export interface Task { @@ -169,7 +169,7 @@ export interface IWorker { * Worker node interface. * * @typeParam Worker - Type of worker. - * @typeParam Data - Type of data sent to the worker. This can only be serializable data. + * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. * @internal */ export interface WorkerNode { diff --git a/src/queue.ts b/src/queue.ts index baecaa35..e7c9dd11 100644 --- a/src/queue.ts +++ b/src/queue.ts @@ -6,18 +6,15 @@ * @typeParam T - Type of queue items. */ export class Queue { - private items: T[] - private offset: number - public size: number - public maxSize: number + private items!: T[] + private offset!: number + /** The size of the queue. */ + public size!: number + /** The maximum size of the queue. */ + public maxSize!: number public constructor () { - this.items = [] - this.offset = 0 - /** The size of the queue. */ - this.size = 0 - /** The maximum size of the queue. */ - this.maxSize = 0 + this.clear() } /** diff --git a/src/utility-types.ts b/src/utility-types.ts index bfbc2a84..da2fa223 100644 --- a/src/utility-types.ts +++ b/src/utility-types.ts @@ -1,20 +1,11 @@ -import type { Worker as ClusterWorker } from 'node:cluster' -import type { MessagePort } from 'node:worker_threads' import type { EventLoopUtilization } from 'node:perf_hooks' import type { KillBehavior } from './worker/worker-options' import type { IWorker, Task } from './pools/worker' -/** - * Make all properties in T non-readonly. - * - * @typeParam T - Type in which properties will be non-readonly. - */ -export type Draft = { -readonly [P in keyof T]?: T[P] } - /** * Task error. * - * @typeParam Data - Type of data sent to the worker. This can only be serializable data. + * @typeParam Data - Type of data sent to the worker triggering an error. This can only be structured-cloneable data. */ export interface TaskError { /** @@ -56,16 +47,16 @@ export interface WorkerStatistics { /** * Message object that is passed between main worker and worker. * - * @typeParam MessageData - Type of data sent to and/or from the worker. This can only be serializable data. - * @typeParam Data - Type of data sent to the worker. This can only be serializable data. + * @typeParam Data - Type of data sent to the worker or execution response. This can only be structured-cloneable data. + * @typeParam ErrorData - Type of data sent to the worker triggering an error. This can only be structured-cloneable data. * @typeParam MainWorker - Type of main worker. * @internal */ export interface MessageValue< - MessageData = unknown, Data = unknown, - MainWorker extends ClusterWorker | MessagePort = ClusterWorker | MessagePort -> extends Task { + ErrorData = unknown, + MainWorker = NodeJS.Process | MessagePort +> extends Task { /** * Kill code. */ @@ -73,7 +64,7 @@ export interface MessageValue< /** * Task error. */ - readonly taskError?: TaskError + readonly taskError?: TaskError /** * Task performance. */ @@ -92,7 +83,7 @@ export interface MessageValue< * An object holding the execution response promise resolve/reject callbacks. * * @typeParam Worker - Type of worker. - * @typeParam Response - Type of execution response. This can only be serializable data. + * @typeParam Response - Type of execution response. This can only be structured-cloneable data. * @internal */ export interface PromiseResponseWrapper< diff --git a/src/worker/abstract-worker.ts b/src/worker/abstract-worker.ts index 1e1d3088..8df09ee0 100644 --- a/src/worker/abstract-worker.ts +++ b/src/worker/abstract-worker.ts @@ -1,5 +1,4 @@ import { AsyncResource } from 'node:async_hooks' -import type { Worker } from 'node:cluster' import type { MessagePort } from 'node:worker_threads' import { performance } from 'node:perf_hooks' import type { @@ -28,11 +27,11 @@ const DEFAULT_KILL_BEHAVIOR: KillBehavior = KillBehaviors.SOFT * Base class that implements some shared logic for all poolifier workers. * * @typeParam MainWorker - Type of main worker. - * @typeParam Data - Type of data this worker receives from pool's execution. This can only be serializable data. - * @typeParam Response - Type of response the worker sends back to the main worker. This can only be serializable data. + * @typeParam Data - Type of data this worker receives from pool's execution. This can only be structured-cloneable data. + * @typeParam Response - Type of response the worker sends back to the main worker. This can only be structured-cloneable data. */ export abstract class AbstractWorker< - MainWorker extends Worker | MessagePort, + MainWorker extends NodeJS.Process | MessagePort, Data = unknown, Response = unknown > extends AsyncResource { @@ -67,7 +66,7 @@ export abstract class AbstractWorker< taskFunctions: | WorkerFunction | TaskFunctions, - protected mainWorker: MainWorker | undefined | null, + protected mainWorker: MainWorker, protected readonly opts: WorkerOptions = { /** * The kill behavior option on this worker or its default value. @@ -177,7 +176,7 @@ export abstract class AbstractWorker< */ protected getMainWorker (): MainWorker { if (this.mainWorker == null) { - throw new Error('Main worker was not set') + throw new Error('Main worker not set') } return this.mainWorker } diff --git a/src/worker/cluster-worker.ts b/src/worker/cluster-worker.ts index 2a3961b3..efc17acf 100644 --- a/src/worker/cluster-worker.ts +++ b/src/worker/cluster-worker.ts @@ -1,4 +1,4 @@ -import cluster, { type Worker } from 'node:cluster' +import cluster from 'node:cluster' import type { MessageValue } from '../utility-types' import { AbstractWorker } from './abstract-worker' import type { WorkerOptions } from './worker-options' @@ -13,15 +13,15 @@ import type { TaskFunctions, WorkerFunction } from './worker-functions' * If you use a `DynamicClusterPool` the extra workers that were created will be terminated, * but the minimum number of workers will be guaranteed. * - * @typeParam Data - Type of data this worker receives from pool's execution. This can only be serializable data. - * @typeParam Response - Type of response the worker sends back to the main worker. This can only be serializable data. + * @typeParam Data - Type of data this worker receives from pool's execution. This can only be structured-cloneable data. + * @typeParam Response - Type of response the worker sends back to the main worker. This can only be structured-cloneable data. * @author [Christopher Quadflieg](https://github.com/Shinigami92) * @since 2.0.0 */ export class ClusterWorker< Data = unknown, Response = unknown -> extends AbstractWorker { +> extends AbstractWorker { /** * Constructs a new poolifier cluster worker. * @@ -38,14 +38,18 @@ export class ClusterWorker< 'worker-cluster-pool:poolifier', cluster.isPrimary, taskFunctions, - cluster.worker, + process, opts ) } /** @inheritDoc */ protected sendToMainWorker (message: MessageValue): void { - this.getMainWorker().send(message) + const mainWorker = this.getMainWorker() + if (mainWorker.send == null) { + throw new Error('Main worker does not support IPC communication') + } + mainWorker.send(message) } /** @inheritDoc */ diff --git a/src/worker/thread-worker.ts b/src/worker/thread-worker.ts index 81d98aa5..b6573a97 100644 --- a/src/worker/thread-worker.ts +++ b/src/worker/thread-worker.ts @@ -13,8 +13,8 @@ import type { TaskFunctions, WorkerFunction } from './worker-functions' * If you use a `DynamicThreadPool` the extra workers that were created will be terminated, * but the minimum number of workers will be guaranteed. * - * @typeParam Data - Type of data this worker receives from pool's execution. This can only be serializable data. - * @typeParam Response - Type of response the worker sends back to the main thread. This can only be serializable data. + * @typeParam Data - Type of data this worker receives from pool's execution. This can only be structured-cloneable data. + * @typeParam Response - Type of response the worker sends back to the main thread. This can only be structured-cloneable data. * @author [Alessandro Pio Ardizio](https://github.com/pioardi) * @since 0.0.1 */ @@ -38,7 +38,7 @@ export class ThreadWorker< 'worker-thread-pool:poolifier', isMainThread, taskFunctions, - parentPort, + parentPort as MessagePort, opts ) } diff --git a/src/worker/worker-functions.ts b/src/worker/worker-functions.ts index 28b9ed54..9232e58f 100644 --- a/src/worker/worker-functions.ts +++ b/src/worker/worker-functions.ts @@ -1,8 +1,8 @@ /** * Worker synchronous function that can be executed. * - * @typeParam Data - Type of data sent to the worker. This can only be serializable data. - * @typeParam Response - Type of execution response. This can only be serializable data. + * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. + * @typeParam Response - Type of execution response. This can only be structured-cloneable data. */ export type WorkerSyncFunction = ( data?: Data @@ -12,8 +12,8 @@ export type WorkerSyncFunction = ( * Worker asynchronous function that can be executed. * This function must return a promise. * - * @typeParam Data - Type of data sent to the worker. This can only be serializable data. - * @typeParam Response - Type of execution response. This can only be serializable data. + * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. + * @typeParam Response - Type of execution response. This can only be structured-cloneable data. */ export type WorkerAsyncFunction = ( data?: Data @@ -23,8 +23,8 @@ export type WorkerAsyncFunction = ( * Worker function that can be executed. * This function can be synchronous or asynchronous. * - * @typeParam Data - Type of data sent to the worker. This can only be serializable data. - * @typeParam Response - Type of execution response. This can only be serializable data. + * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. + * @typeParam Response - Type of execution response. This can only be structured-cloneable data. */ export type WorkerFunction = | WorkerSyncFunction @@ -36,8 +36,8 @@ export type WorkerFunction = * The key is the name of the function. * The value is the function itself. * - * @typeParam Data - Type of data sent to the worker. This can only be serializable data. - * @typeParam Response - Type of execution response. This can only be serializable data. + * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. + * @typeParam Response - Type of execution response. This can only be structured-cloneable data. */ export type TaskFunctions = Record< string, diff --git a/tests/worker/abstract-worker.test.js b/tests/worker/abstract-worker.test.js index 458cec80..e5bf4c81 100644 --- a/tests/worker/abstract-worker.test.js +++ b/tests/worker/abstract-worker.test.js @@ -114,6 +114,6 @@ describe('Abstract worker test suite', () => { it('Verify that getMainWorker() throw error if main worker is not set', () => { expect(() => new StubWorkerWithMainWorker(() => {}).getMainWorker() - ).toThrowError('Main worker was not set') + ).toThrowError('Main worker not set') }) }) -- 2.34.1