From: Jérôme Benoit Date: Sun, 2 Jun 2024 20:30:38 +0000 (+0200) Subject: build(deps-dev): apply updates X-Git-Url: https://git.piment-noir.org/?a=commitdiff_plain;h=HEAD;hp=5bce9acc6be94ef36b2d31a2fec0d3892f605d42;p=poolifier.git build(deps-dev): apply updates Signed-off-by: Jérôme Benoit --- diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index f2ad06fb..00000000 --- a/.eslintignore +++ /dev/null @@ -1,4 +0,0 @@ -docs/ -dist/ -lib/ -outputs/ diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index ef9e86c0..00000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,186 +0,0 @@ -const { defineConfig } = require('eslint-define-config') - -module.exports = defineConfig({ - root: true, - env: { - es2022: true, - node: true, - mocha: true - }, - parserOptions: { - sourceType: 'module', - ecmaVersion: 2022 - }, - plugins: ['simple-import-sort', 'promise', 'spellcheck'], - extends: [ - 'eslint:recommended', - 'plugin:import/recommended', - 'plugin:promise/recommended' - ], - settings: { - 'import/resolver': { - typescript: { - project: './tsconfig.json' - } - } - }, - rules: { - 'simple-import-sort/imports': 'error', - 'simple-import-sort/exports': 'error', - - 'spellcheck/spell-checker': [ - 'warn', - { - skipWords: [ - 'argv', - 'axios', - 'benoit', - 'browserslist', - 'builtins', - 'christopher', - 'cjs', - 'cloneable', - 'comparator', - 'cpu', - 'cpus', - 'cryptographically', - 'ctx', - 'deprecations', - 'deque', - 'dequeue', - 'dequeued', - 'deregisters', - 'dts', - 'ecma', - 'elu', - 'enqueue', - 'enum', - 'errored', - 'esm', - 'fastify', - 'fibonacci', - 'fp', - 'fs', - 'func', - 'inheritDoc', - 'javascript', - 'jsdoc', - 'linebreak', - 'localhost', - 'microjob', - 'mjs', - 'nodemailer', - 'npx', - 'num', - 'os', - 'perf', - 'piscina', - 'pnpm', - 'poolifier', - 'prepend', - 'prepends', - 'positionals', - 'readdir', - 'readonly', - 'req', - 'resize', - 'sinon', - 'smtp', - 'threadjs', - 'threadwork', - 'tinypool', - 'tld', - 'tos', - 'tsconfig', - 'tsdoc', - 'typedoc', - 'unlink', - 'unref', - 'utf8', - 'workerpool', - 'ws', - 'wss', - 'wwr' - ], - skipIfMatch: ['^@.*', '^plugin:.*'] - } - ] - }, - overrides: [ - { - files: ['**/*.ts'], - plugins: ['@typescript-eslint', 'eslint-plugin-tsdoc'], - parser: '@typescript-eslint/parser', - parserOptions: { - project: './tsconfig.json' - }, - extends: [ - 'plugin:@typescript-eslint/strict-type-checked', - 'plugin:@typescript-eslint/stylistic-type-checked', - 'plugin:import/typescript', - 'love' - ], - rules: { - 'operator-linebreak': 'off', - 'tsdoc/syntax': 'warn' - } - }, - { - files: ['examples/typescript/**/*.ts'], - rules: { - 'import/no-unresolved': [ - 'error', - { - ignore: [ - '^axios$', - '^express$', - '^fastify$', - '^fastify-plugin$', - '^node-fetch$', - '^nodemailer$', - '^poolifier$', - '^ws$' - ] - } - ], - '@typescript-eslint/no-unsafe-argument': 'off', - '@typescript-eslint/no-unsafe-call': 'off', - '@typescript-eslint/no-unsafe-return': 'off', - '@typescript-eslint/no-unsafe-assignment': 'off', - '@typescript-eslint/no-unsafe-member-access': 'off', - '@typescript-eslint/no-unnecessary-type-assertion': 'off', - '@typescript-eslint/no-redundant-type-constituents': 'off', - '@typescript-eslint/strict-boolean-expressions': 'off', - '@typescript-eslint/return-await': 'off', - '@typescript-eslint/no-non-null-assertion': 'off' - } - }, - { - files: ['**/*.cjs', '**/*.js', '**/*.mjs'], - plugins: ['jsdoc'], - extends: ['plugin:n/recommended', 'plugin:jsdoc/recommended', 'standard'] - }, - { - files: ['tests/**/*.cjs', 'tests/**/*.js', 'tests/**/*.mjs'], - rules: { - 'jsdoc/require-jsdoc': 'off' - } - }, - { - files: [ - 'benchmarks/**/*.cjs', - 'benchmarks/**/*.js', - 'benchmarks/**/*.mjs' - ], - rules: { - 'jsdoc/require-jsdoc': 'off' - } - }, - { - files: ['examples/javascript/**/*.cjs', 'examples/javascript/**/*.js'], - rules: { - 'jsdoc/require-jsdoc': 'off' - } - } - ] -}) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index afcfc1f1..d8f3ab84 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,9 +30,7 @@ jobs: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis. This is needed for better sonar - name: Setup pnpm - uses: pnpm/action-setup@v3 - with: - version: 9 + uses: pnpm/action-setup@v4 - name: Setup Node.js ${{ matrix.node }} uses: actions/setup-node@v4 @@ -69,7 +67,7 @@ jobs: - name: SonarCloud Code Analysis if: ${{ steps.sonar-token.outputs.available == 'true' && github.repository == 'poolifier/poolifier' && matrix.os == 'ubuntu-latest' && matrix.node == '20.x' }} - uses: sonarsource/sonarcloud-github-action@v2.1.1 + uses: sonarsource/sonarcloud-github-action@v2.2.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/.github/workflows/generate-documentation.yml b/.github/workflows/generate-documentation.yml index 2bc13936..677a6195 100644 --- a/.github/workflows/generate-documentation.yml +++ b/.github/workflows/generate-documentation.yml @@ -12,9 +12,7 @@ jobs: uses: actions/checkout@v4 - name: Setup pnpm - uses: pnpm/action-setup@v3 - with: - version: 9 + uses: pnpm/action-setup@v4 - name: Setup Node.js uses: actions/setup-node@v4 diff --git a/.github/workflows/internal-benchmark.yml b/.github/workflows/internal-benchmark.yml index 1e3115f4..75b97cff 100644 --- a/.github/workflows/internal-benchmark.yml +++ b/.github/workflows/internal-benchmark.yml @@ -15,15 +15,13 @@ jobs: env: BENCHER_PROJECT: poolifier BENCHER_API_TOKEN: ${{ secrets.BENCHER_API_TOKEN }} - BENCHER_ADAPTER: js_benchmark + BENCHER_ADAPTER: json BENCHER_TESTBED: self-hosted steps: - name: Checkout uses: actions/checkout@v4 - name: Setup pnpm - uses: pnpm/action-setup@v3 - with: - version: 9 + uses: pnpm/action-setup@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: @@ -32,14 +30,15 @@ jobs: cache: 'pnpm' - name: Install dependencies run: pnpm install --ignore-scripts --frozen-lockfile - # - uses: bencherdev/bencher@main - # - name: Run production benchmark - # run: | - # bencher run \ - # --if-branch "$GITHUB_REF_NAME" \ - # --else-if-branch "$GITHUB_BASE_REF" \ - # --else-if-branch master \ - # --hash "$GITHUB_SHA" \ - # --err \ - # --github-actions ${{ secrets.GITHUB_TOKEN }} \ - # "pnpm benchmark:benchmark.js:prod" + - uses: bencherdev/bencher@main + - name: Run production benchmark + run: | + bencher run \ + --if-branch "$GITHUB_REF_NAME" \ + --else-if-branch "$GITHUB_BASE_REF" \ + --else-if-branch master \ + --hash "$GITHUB_SHA" \ + --file benchmark-report.json \ + --err \ + --github-actions ${{ secrets.GITHUB_TOKEN }} \ + "pnpm benchmark:tatami-ng:prod" diff --git a/.github/workflows/publish-package.yml b/.github/workflows/publish-package.yml index bc0929ae..3f6243c1 100644 --- a/.github/workflows/publish-package.yml +++ b/.github/workflows/publish-package.yml @@ -13,9 +13,7 @@ jobs: uses: actions/checkout@v4 - name: Setup pnpm - uses: pnpm/action-setup@v3 - with: - version: 9 + uses: pnpm/action-setup@v4 - name: Setup Node.js uses: actions/setup-node@v4 @@ -71,9 +69,7 @@ jobs: uses: actions/checkout@v4 - name: Setup pnpm - uses: pnpm/action-setup@v3 - with: - version: 9 + uses: pnpm/action-setup@v4 - name: Setup Node.js uses: actions/setup-node@v4 diff --git a/.gitignore b/.gitignore index d014f1b3..9f9e3aa7 100644 --- a/.gitignore +++ b/.gitignore @@ -78,3 +78,4 @@ dist tmp .history/ reports/ +benchmark-report.json diff --git a/.lintstagedrc.js b/.lintstagedrc.js index aca15ab7..f9e18d53 100644 --- a/.lintstagedrc.js +++ b/.lintstagedrc.js @@ -1,8 +1,8 @@ export default { '**/*.{ts,tsx,js,jsx,cjs,mjs}': [ - 'biome format --write', - 'eslint --cache --fix' + // 'biome format --write', + 'eslint --cache --fix', ], '**/*.json': ['biome format --write'], - '**/*.{md,yml,yaml}': ['prettier --cache --write'] + '**/*.{md,yml,yaml}': ['prettier --cache --write'], } diff --git a/.vscode/launch.json b/.vscode/launch.json index f3ee906a..c750ba52 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -14,16 +14,6 @@ "skipFiles": ["/**"], "stopOnEntry": true }, - { - "type": "node", - "request": "launch", - "name": "Launch Benchmark.js Benchmark Debug", - "cwd": "${workspaceFolder}", - "runtimeExecutable": "pnpm", - "runtimeArgs": ["run", "benchmark:benchmark.js:debug"], - "skipFiles": ["/**"], - "stopOnEntry": true - }, { "type": "node", "request": "launch", diff --git a/.vscode/settings.json b/.vscode/settings.json index b014abda..ebec4d23 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -36,6 +36,7 @@ "mochawesome", "MYBENCH", "nanothreads", + "neostandard", "npmjs", "nproc", "octocat", @@ -58,6 +59,7 @@ "tinypool", "trimmable", "tsdoc", + "tseslint", "typedoc", "workerpool" ], diff --git a/CHANGELOG.md b/CHANGELOG.md index 53632f35..27b2a232 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,79 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [4.0.13] - 2024-05-29 + +### Changed + +- Optimize tasks queue implementation. +- Enable prioritized tasks queueing only when necessary. + +## [4.0.12] - 2024-05-25 + +### Changed + +- Optimize circular buffer implementation to store task execution measurements. + +## [4.0.11] - 2024-05-21 + +### Changed + +- Switch to optimized circular buffer implementation to store task execution measurements. + +## [4.0.10] - 2024-05-20 + +### Fixed + +- Ensure tasks stealing dynamic worker node is not destroyed on inactivity. + +## [4.0.9] - 2024-05-19 + +### Changed + +- Add ELU `utilization` statistics to pool information. + +## [4.0.8] - 2024-05-15 + +### Fixed + +- Fix default task function worker choice strategy and priority handling. + +## [4.0.7] - 2024-05-13 + +### Changed + +- Add ELU statistics to pool information. + +## [4.0.6] - 2024-05-10 + +### Fixed + +- Fix pools' `addTaskFunction()` type definition. + +## [4.0.5] - 2024-05-09 + +### Fixed + +- Avoid queued tasks redistribution on the errored worker node. + +## [4.0.4] - 2024-05-08 + +### Fixed + +- Disable `tasksStealingOnBackPressure` by default until performance issues under heavy load are sorted out. + +## [4.0.3] - 2024-05-08 + +### Changed + +- Optimize task(s) stealing by dequeuing task(s) from the last prioritized bucket. + +## [4.0.2] - 2024-05-06 + +### Fixed + +- Ensure poolifier worker task performance measurement requirements are synchronized with task function objects' worker choice strategies. + ## [4.0.1] - 2024-05-02 ### Fixed @@ -398,7 +471,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add `startWorkers` to pool options to whether start the minimum number of workers at pool initialization or not. - Add `start()` method to pool API to start the minimum number of workers. -- Add `taskStealing` and `tasksStealingOnPressure` to tasks queue options to whether enable task stealing or not and whether enable tasks stealing under back pressure or not. +- Add `taskStealing` and `tasksStealingOnBackPressure` to tasks queue options to whether enable task stealing or not and whether enable tasks stealing under back pressure or not. - Continuous internal benchmarking: [https://poolifier.github.io/benchmark-results/dev/bench](https://poolifier.github.io/benchmark-results/dev/bench). ## [2.6.44] - 2023-09-08 diff --git a/benchmarks/README.md b/benchmarks/README.md index 27467511..319cafcf 100644 --- a/benchmarks/README.md +++ b/benchmarks/README.md @@ -24,7 +24,6 @@ See the dedicated repository [README.md](https://github.com/poolifier/benchmark# To run the internal benchmark, you just need to navigate to the root of poolifier cloned repository and run: -- `pnpm benchmark:benchmark.js` or - `pnpm benchmark:tatami-ng` ### [Results](https://bencher.dev/perf/poolifier) diff --git a/benchmarks/benchmarks-types.cjs b/benchmarks/benchmarks-types.cjs index eaaf05d1..f99a1501 100644 --- a/benchmarks/benchmarks-types.cjs +++ b/benchmarks/benchmarks-types.cjs @@ -2,7 +2,7 @@ const TaskFunctions = { jsonIntegerSerialization: 'jsonIntegerSerialization', fibonacci: 'fibonacci', factorial: 'factorial', - readWriteFiles: 'readWriteFiles' + readWriteFiles: 'readWriteFiles', } module.exports = { TaskFunctions } diff --git a/benchmarks/benchmarks-utils.cjs b/benchmarks/benchmarks-utils.cjs index c3b470f7..f212c7b2 100644 --- a/benchmarks/benchmarks-utils.cjs +++ b/benchmarks/benchmarks-utils.cjs @@ -4,14 +4,14 @@ const { mkdirSync, readFileSync, rmSync, - writeFileSync + writeFileSync, } = require('node:fs') const { TaskFunctions } = require('./benchmarks-types.cjs') const jsonIntegerSerialization = n => { for (let i = 0; i < n; i++) { const o = { - a: i + a: i, } JSON.stringify(o) } @@ -19,8 +19,8 @@ const jsonIntegerSerialization = n => { } /** - * @param {number} n - The number of fibonacci numbers to generate. - * @returns {number} - The nth fibonacci number. + * @param n - The number of fibonacci numbers to generate. + * @returns - The nth fibonacci number. */ const fibonacci = n => { n = BigInt(n) @@ -36,8 +36,8 @@ const fibonacci = n => { } /** - * @param {number} n - The number to calculate the factorial of. - * @returns {number} - The factorial of n. + * @param n - The number to calculate the factorial of. + * @returns - The factorial of n. */ const factorial = n => { if (n === 0 || n === 1) { @@ -65,7 +65,7 @@ const readWriteFiles = ( const filePath = `${baseDirectory}/${i}` writeFileSync(filePath, i.toString(), { encoding: 'utf8', - flag: 'a' + flag: 'a', }) readFileSync(filePath, 'utf8') } @@ -89,5 +89,5 @@ const executeTaskFunction = data => { } module.exports = { - executeTaskFunction + executeTaskFunction, } diff --git a/benchmarks/benchmarks-utils.mjs b/benchmarks/benchmarks-utils.mjs index 35c335c4..6c01efcb 100644 --- a/benchmarks/benchmarks-utils.mjs +++ b/benchmarks/benchmarks-utils.mjs @@ -1,6 +1,5 @@ import { strictEqual } from 'node:assert' -import Benchmark from 'benchmark' import { bench, clear, group, run } from 'tatami-ng' import { @@ -11,7 +10,7 @@ import { Measurements, PoolTypes, WorkerChoiceStrategies, - WorkerTypes + WorkerTypes, } from '../lib/index.mjs' import { executeTaskFunction } from './benchmarks-utils.cjs' @@ -55,198 +54,9 @@ const buildPoolifierPool = (workerType, poolType, poolSize, poolOptions) => { } const runPoolifierPool = async (pool, { taskExecutions, workerData }) => { - return await new Promise((resolve, reject) => { - let executions = 0 - for (let i = 1; i <= taskExecutions; i++) { - pool - .execute(workerData) - .then(() => { - ++executions - if (executions === taskExecutions) { - resolve({ ok: 1 }) - } - return undefined - }) - .catch(err => { - console.error(err) - reject(err) - }) - } - }) -} - -export const runPoolifierBenchmarkBenchmarkJs = async ( - name, - workerType, - poolType, - poolSize, - poolOptions, - { taskExecutions, workerData } -) => { - return await new Promise((resolve, reject) => { - const pool = buildPoolifierPool(workerType, poolType, poolSize, poolOptions) - let workerChoiceStrategy - let enableTasksQueue - let workerChoiceStrategyOptions - if (poolOptions != null) { - ({ - workerChoiceStrategy, - enableTasksQueue, - workerChoiceStrategyOptions - } = poolOptions) - } - const measurement = workerChoiceStrategyOptions?.measurement - new Benchmark( - `${name} with ${workerChoiceStrategy ?? pool.opts.workerChoiceStrategy}${ - measurement != null ? `, with ${measurement}` : '' - } and ${enableTasksQueue ? 'with' : 'without'} tasks queue`, - async () => { - await runPoolifierPool(pool, { - taskExecutions, - workerData - }) - }, - { - onStart: () => { - if (workerChoiceStrategy != null) { - strictEqual(pool.opts.workerChoiceStrategy, workerChoiceStrategy) - } - if (enableTasksQueue != null) { - strictEqual(pool.opts.enableTasksQueue, enableTasksQueue) - } - if (measurement != null) { - strictEqual( - pool.opts.workerChoiceStrategyOptions.measurement, - measurement - ) - } - }, - onComplete: event => { - console.info(event.target.toString()) - if (pool.started && !pool.destroying) { - pool.destroy().then(resolve).catch(reject) - } else { - resolve() - } - }, - onError: event => { - if (pool.started && !pool.destroying) { - pool - .destroy() - .then(() => { - return reject(event.target.error) - }) - .catch(() => {}) - } else { - reject(event.target.error) - } - } - } - ).run({ async: true }) - }) -} - -export const runPoolifierBenchmarkBenchmarkJsSuite = async ( - name, - workerType, - poolType, - poolSize, - { taskExecutions, workerData } -) => { - return await new Promise((resolve, reject) => { - const pool = buildPoolifierPool(workerType, poolType, poolSize) - const suite = new Benchmark.Suite(name, { - onComplete: () => { - if (pool.started && !pool.destroying) { - pool.destroy().then(resolve).catch(reject) - } else { - resolve() - } - }, - onCycle: event => { - console.info(event.target.toString()) - }, - onError: event => { - if (pool.started && !pool.destroying) { - pool - .destroy() - .then(() => { - return reject(event.target.error) - }) - .catch(() => {}) - } else { - reject(event.target.error) - } - } - }) - for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) { - for (const enableTasksQueue of [false, true]) { - if (workerChoiceStrategy === WorkerChoiceStrategies.FAIR_SHARE) { - for (const measurement of [Measurements.runTime, Measurements.elu]) { - suite.add( - `${name} with ${workerChoiceStrategy}, with ${measurement} and ${ - enableTasksQueue ? 'with' : 'without' - } tasks queue`, - async () => { - await runPoolifierPool(pool, { - taskExecutions, - workerData - }) - }, - { - onStart: () => { - pool.setWorkerChoiceStrategy(workerChoiceStrategy, { - measurement - }) - pool.enableTasksQueue(enableTasksQueue) - strictEqual( - pool.opts.workerChoiceStrategy, - workerChoiceStrategy - ) - strictEqual(pool.opts.enableTasksQueue, enableTasksQueue) - strictEqual( - pool.opts.workerChoiceStrategyOptions.measurement, - measurement - ) - } - } - ) - } - } else { - suite.add( - `${name} with ${workerChoiceStrategy} and ${ - enableTasksQueue ? 'with' : 'without' - } tasks queue`, - async () => { - await runPoolifierPool(pool, { - taskExecutions, - workerData - }) - }, - { - onStart: () => { - pool.setWorkerChoiceStrategy(workerChoiceStrategy) - pool.enableTasksQueue(enableTasksQueue) - strictEqual( - pool.opts.workerChoiceStrategy, - workerChoiceStrategy - ) - strictEqual(pool.opts.enableTasksQueue, enableTasksQueue) - } - } - ) - } - } - } - suite - .on('complete', function () { - console.info( - 'Fastest is ' + - LIST_FORMATTER.format(this.filter('fastest').map('name')) - ) - }) - .run({ async: true }) - }) + for (let i = 1; i <= taskExecutions; i++) { + await pool.execute(workerData) + } } export const runPoolifierBenchmarkTatamiNg = async ( @@ -270,13 +80,13 @@ export const runPoolifierBenchmarkTatamiNg = async ( async () => { await runPoolifierPool(pool, { taskExecutions, - workerData + workerData, }) }, { before: () => { pool.setWorkerChoiceStrategy(workerChoiceStrategy, { - measurement + measurement, }) pool.enableTasksQueue(enableTasksQueue) strictEqual( @@ -288,7 +98,7 @@ export const runPoolifierBenchmarkTatamiNg = async ( pool.opts.workerChoiceStrategyOptions.measurement, measurement ) - } + }, } ) }) @@ -302,7 +112,7 @@ export const runPoolifierBenchmarkTatamiNg = async ( async () => { await runPoolifierPool(pool, { taskExecutions, - workerData + workerData, }) }, { @@ -314,24 +124,39 @@ export const runPoolifierBenchmarkTatamiNg = async ( workerChoiceStrategy ) strictEqual(pool.opts.enableTasksQueue, enableTasksQueue) - } + }, } ) }) } } } - await run() + const report = await run() clear() await pool.destroy() + return report } catch (error) { console.error(error) } } -const LIST_FORMATTER = new Intl.ListFormat('en-US', { - style: 'long', - type: 'conjunction' -}) +export const convertTatamiNgToBmf = report => { + return report.benchmarks + .map(({ name, stats }) => { + return { + [name]: { + latency: { + value: stats?.avg, + lower_value: stats?.min, + upper_value: stats?.max, + }, + throughput: { + value: stats?.iter, + }, + }, + } + }) + .reduce((obj, item) => Object.assign(obj, item), {}) +} export { executeTaskFunction } diff --git a/benchmarks/internal/bench.mjs b/benchmarks/internal/bench.mjs index 41cf62e6..8bae6aaf 100644 --- a/benchmarks/internal/bench.mjs +++ b/benchmarks/internal/bench.mjs @@ -1,24 +1,27 @@ -import { exit } from 'node:process' +import { writeFileSync } from 'node:fs' +import { env } from 'node:process' // eslint-disable-next-line n/no-unsupported-features/node-builtins import { parseArgs } from 'node:util' import { availableParallelism, PoolTypes, - WorkerTypes + WorkerTypes, } from '../../lib/index.mjs' import { TaskFunctions } from '../benchmarks-types.cjs' import { - runPoolifierBenchmarkBenchmarkJsSuite, - runPoolifierBenchmarkTatamiNg + convertTatamiNgToBmf, + runPoolifierBenchmarkTatamiNg, } from '../benchmarks-utils.mjs' const poolSize = availableParallelism() const taskExecutions = 1 const workerData = { function: TaskFunctions.factorial, - taskSize: 50000 + taskSize: 1000, } +const benchmarkReportFile = 'benchmark-report.json' +let benchmarkReport switch ( parseArgs({ @@ -26,98 +29,74 @@ switch ( options: { type: { type: 'string', - short: 't' - } + short: 't', + }, }, strict: true, - allowPositionals: true + allowPositionals: true, }).values.type ) { case 'tatami-ng': - await runPoolifierBenchmarkTatamiNg( - 'FixedThreadPool', - WorkerTypes.thread, - PoolTypes.fixed, - poolSize, - { - taskExecutions, - workerData - } - ) - await runPoolifierBenchmarkTatamiNg( - 'DynamicThreadPool', - WorkerTypes.thread, - PoolTypes.dynamic, - poolSize, - { - taskExecutions, - workerData - } - ) - await runPoolifierBenchmarkTatamiNg( - 'FixedClusterPool', - WorkerTypes.cluster, - PoolTypes.fixed, - poolSize, - { - taskExecutions, - workerData - } - ) - await runPoolifierBenchmarkTatamiNg( - 'DynamicClusterPool', - WorkerTypes.cluster, - PoolTypes.dynamic, - poolSize, - { - taskExecutions, - workerData - } - ) - break - case 'benchmark.js': default: - await runPoolifierBenchmarkBenchmarkJsSuite( - 'FixedThreadPool', - WorkerTypes.thread, - PoolTypes.fixed, - poolSize, - { - taskExecutions, - workerData - } - ) - await runPoolifierBenchmarkBenchmarkJsSuite( - 'DynamicThreadPool', - WorkerTypes.thread, - PoolTypes.dynamic, - poolSize, - { - taskExecutions, - workerData - } - ) - await runPoolifierBenchmarkBenchmarkJsSuite( - 'FixedClusterPool', - WorkerTypes.cluster, - PoolTypes.fixed, - poolSize, - { - taskExecutions, - workerData - } - ) - await runPoolifierBenchmarkBenchmarkJsSuite( - 'DynamicClusterPool', - WorkerTypes.cluster, - PoolTypes.dynamic, - poolSize, - { - taskExecutions, - workerData - } + benchmarkReport = convertTatamiNgToBmf( + await runPoolifierBenchmarkTatamiNg( + 'FixedThreadPool', + WorkerTypes.thread, + PoolTypes.fixed, + poolSize, + { + taskExecutions, + workerData, + } + ) ) + benchmarkReport = { + ...benchmarkReport, + ...convertTatamiNgToBmf( + await runPoolifierBenchmarkTatamiNg( + 'DynamicThreadPool', + WorkerTypes.thread, + PoolTypes.dynamic, + poolSize, + { + taskExecutions, + workerData, + } + ) + ), + } + benchmarkReport = { + ...benchmarkReport, + ...convertTatamiNgToBmf( + await runPoolifierBenchmarkTatamiNg( + 'FixedClusterPool', + WorkerTypes.cluster, + PoolTypes.fixed, + poolSize, + { + taskExecutions, + workerData, + } + ) + ), + } + benchmarkReport = { + ...benchmarkReport, + ...convertTatamiNgToBmf( + await runPoolifierBenchmarkTatamiNg( + 'DynamicClusterPool', + WorkerTypes.cluster, + PoolTypes.dynamic, + poolSize, + { + taskExecutions, + workerData, + } + ) + ), + } + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + env.CI != null && + writeFileSync(benchmarkReportFile, JSON.stringify(benchmarkReport)) break } - -exit() diff --git a/benchmarks/internal/cluster-worker.cjs b/benchmarks/internal/cluster-worker.cjs index 5f59d49b..40d614c7 100644 --- a/benchmarks/internal/cluster-worker.cjs +++ b/benchmarks/internal/cluster-worker.cjs @@ -8,6 +8,7 @@ const taskFunction = data => { data.function = data.function || TaskFunctions.factorial data.debug = data.debug || false const res = executeTaskFunction(data) + // eslint-disable-next-line @typescript-eslint/no-unused-expressions data.debug === true && console.debug(`This is the main thread ${isPrimary}`) return res } diff --git a/benchmarks/internal/thread-worker.mjs b/benchmarks/internal/thread-worker.mjs index 232881b5..a5873926 100644 --- a/benchmarks/internal/thread-worker.mjs +++ b/benchmarks/internal/thread-worker.mjs @@ -9,6 +9,7 @@ const taskFunction = data => { data.function = data.function || TaskFunctions.factorial data.debug = data.debug || false const res = executeTaskFunction(data) + // eslint-disable-next-line @typescript-eslint/no-unused-expressions data.debug === true && console.debug(`This is the main thread ${isMainThread}`) return res diff --git a/benchmarks/worker-selection/least.mjs b/benchmarks/worker-selection/least.mjs index ca5de3c1..5c9ff1ba 100644 --- a/benchmarks/worker-selection/least.mjs +++ b/benchmarks/worker-selection/least.mjs @@ -2,6 +2,11 @@ import { randomInt } from 'node:crypto' import { bench, group, run } from 'tatami-ng' +/** + * + * @param numberOfWorkers + * @param maxNumberOfTasksPerWorker + */ function generateRandomTasksMap ( numberOfWorkers, maxNumberOfTasksPerWorker = 10 @@ -16,9 +21,13 @@ function generateRandomTasksMap ( const tasksMap = generateRandomTasksMap(60, 20) +/** + * + * @param tasksMap + */ function loopSelect (tasksMap) { let minKey - let minValue = Infinity + let minValue = Number.POSITIVE_INFINITY for (const [key, value] of tasksMap) { if (value === 0) { return key @@ -30,6 +39,10 @@ function loopSelect (tasksMap) { return [minKey, minValue] } +/** + * + * @param tasksMap + */ function arraySortSelect (tasksMap) { const tasksArray = Array.from(tasksMap) return tasksArray.sort((a, b) => { @@ -54,12 +67,26 @@ const randomPivotIndexSelect = (leftIndex, rightIndex) => { return randomInt(leftIndex, rightIndex) } +/** + * + * @param array + * @param index1 + * @param index2 + */ function swap (array, index1, index2) { const tmp = array[index1] array[index1] = array[index2] array[index2] = tmp } +/** + * + * @param array + * @param leftIndex + * @param rightIndex + * @param pivotIndex + * @param compare + */ function partition ( array, leftIndex, @@ -80,6 +107,15 @@ function partition ( return storeIndex } +/** + * + * @param array + * @param k + * @param leftIndex + * @param rightIndex + * @param compare + * @param pivotIndexSelect + */ function selectLoop ( array, k, @@ -102,6 +138,15 @@ function selectLoop ( } } +/** + * + * @param array + * @param k + * @param leftIndex + * @param rightIndex + * @param compare + * @param pivotIndexSelect + */ function selectRecursion ( array, k, @@ -122,6 +167,10 @@ function selectRecursion ( } } +/** + * + * @param tasksMap + */ function quickSelectLoop (tasksMap) { const tasksArray = Array.from(tasksMap) @@ -130,6 +179,10 @@ function quickSelectLoop (tasksMap) { }) } +/** + * + * @param tasksMap + */ function quickSelectLoopRandomPivot (tasksMap) { const tasksArray = Array.from(tasksMap) @@ -145,6 +198,10 @@ function quickSelectLoopRandomPivot (tasksMap) { ) } +/** + * + * @param tasksMap + */ function quickSelectRecursion (tasksMap) { const tasksArray = Array.from(tasksMap) @@ -153,6 +210,10 @@ function quickSelectRecursion (tasksMap) { }) } +/** + * + * @param tasksMap + */ function quickSelectRecursionRandomPivot (tasksMap) { const tasksArray = Array.from(tasksMap) diff --git a/benchmarks/worker-selection/round-robin.mjs b/benchmarks/worker-selection/round-robin.mjs index 82892450..d39fd699 100644 --- a/benchmarks/worker-selection/round-robin.mjs +++ b/benchmarks/worker-selection/round-robin.mjs @@ -1,5 +1,9 @@ import { bench, group, run } from 'tatami-ng' +/** + * + * @param numberOfWorkers + */ function generateWorkersArray (numberOfWorkers) { return [...Array(numberOfWorkers).keys()] } @@ -8,12 +12,18 @@ const workers = generateWorkersArray(60) let nextWorkerIndex +/** + * + */ function roundRobinTernaryOffByOne () { nextWorkerIndex = workers.length - 1 === nextWorkerIndex ? 0 : nextWorkerIndex + 1 return workers[nextWorkerIndex] } +/** + * + */ function roundRobinTernaryWithNegation () { nextWorkerIndex = !nextWorkerIndex || workers.length - 1 === nextWorkerIndex @@ -22,6 +32,9 @@ function roundRobinTernaryWithNegation () { return workers[nextWorkerIndex] } +/** + * + */ function roundRobinTernaryWithPreChoosing () { const chosenWorker = workers[nextWorkerIndex] nextWorkerIndex = @@ -29,6 +42,9 @@ function roundRobinTernaryWithPreChoosing () { return chosenWorker } +/** + * + */ function roundRobinIncrementModulo () { const chosenWorker = workers[nextWorkerIndex] nextWorkerIndex++ diff --git a/biome.json b/biome.json index 7a087018..4bd089e4 100644 --- a/biome.json +++ b/biome.json @@ -1,5 +1,5 @@ { - "$schema": "https://biomejs.dev/schemas/1.7.2/schema.json", + "$schema": "https://biomejs.dev/schemas/1.7.3/schema.json", "organizeImports": { "enabled": false }, diff --git a/docs/api.md b/docs/api.md index 1b888173..28e6aad2 100644 --- a/docs/api.md +++ b/docs/api.md @@ -99,7 +99,7 @@ An object with these properties: - `WorkerChoiceStrategies.ROUND_ROBIN`: Submit tasks to worker in a round robin fashion - `WorkerChoiceStrategies.LEAST_USED`: Submit tasks to the worker with the minimum number of executing and queued tasks - - `WorkerChoiceStrategies.LEAST_BUSY`: Submit tasks to the worker with the minimum tasks total execution and wait time + - `WorkerChoiceStrategies.LEAST_BUSY`: Submit tasks to the worker with the minimum tasks execution time - `WorkerChoiceStrategies.LEAST_ELU`: Submit tasks to the worker with the minimum event loop utilization (ELU) - `WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN`: Submit tasks to worker by using a [weighted round robin scheduling algorithm](./worker-choice-strategies.md#weighted-round-robin) based on tasks execution time - `WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN`: Submit tasks to worker by using an [interleaved weighted round robin scheduling algorithm](./worker-choice-strategies.md#interleaved-weighted-round-robin-experimental) based on tasks execution time (experimental) @@ -137,7 +137,7 @@ An object with these properties: - `tasksStealingOnBackPressure` (optional) - Tasks stealing enablement under back pressure. - `tasksFinishedTimeout` (optional) - Queued tasks finished timeout in milliseconds at worker termination. - Default: `{ size: (pool maximum size)^2, concurrency: 1, taskStealing: true, tasksStealingOnBackPressure: true, tasksFinishedTimeout: 2000 }` + Default: `{ size: (pool maximum size)^2, concurrency: 1, taskStealing: true, tasksStealingOnBackPressure: false, tasksFinishedTimeout: 2000 }` - `workerOptions` (optional) - An object with the worker options to pass to worker. See [worker_threads](https://nodejs.org/api/worker_threads.html#worker_threads_new_worker_filename_options) for more details. @@ -153,8 +153,8 @@ An object with these properties: `opts` (optional) An object with these properties: - `killBehavior` (optional) - Dictates if your worker will be deleted in case a task is active on it. - **KillBehaviors.SOFT**: If `currentTime - lastActiveTime` is greater than `maxInactiveTime` but a task is still executing or queued, then the worker **won't** be deleted. - **KillBehaviors.HARD**: If `currentTime - lastActiveTime` is greater than `maxInactiveTime` but a task is still executing or queued, then the worker will be deleted. + **KillBehaviors.SOFT**: If `currentTime - lastActiveTime` is greater than `maxInactiveTime` but the worker is stealing tasks or a task is executing or queued, then the worker **won't** be deleted. + **KillBehaviors.HARD**: If `currentTime - lastActiveTime` is greater than `maxInactiveTime` but the worker is stealing tasks or a task is executing or queued, then the worker will be deleted. This option only apply to the newly created workers. Default: `KillBehaviors.SOFT` diff --git a/docs/assets/highlight.css b/docs/assets/highlight.css index 9b823cb3..0b3cf03b 100644 --- a/docs/assets/highlight.css +++ b/docs/assets/highlight.css @@ -1,22 +1,22 @@ :root { - --light-hl-0: #000000; - --dark-hl-0: #D4D4D4; - --light-hl-1: #098658; - --dark-hl-1: #B5CEA8; - --light-hl-2: #795E26; - --dark-hl-2: #DCDCAA; - --light-hl-3: #001080; - --dark-hl-3: #9CDCFE; - --light-hl-4: #0000FF; - --dark-hl-4: #569CD6; - --light-hl-5: #0070C1; - --dark-hl-5: #4FC1FF; - --light-hl-6: #AF00DB; - --dark-hl-6: #C586C0; - --light-hl-7: #A31515; - --dark-hl-7: #CE9178; - --light-hl-8: #008000; - --dark-hl-8: #6A9955; + --light-hl-0: #001080; + --dark-hl-0: #9CDCFE; + --light-hl-1: #0000FF; + --dark-hl-1: #569CD6; + --light-hl-2: #000000; + --dark-hl-2: #D4D4D4; + --light-hl-3: #0070C1; + --dark-hl-3: #4FC1FF; + --light-hl-4: #AF00DB; + --dark-hl-4: #C586C0; + --light-hl-5: #A31515; + --dark-hl-5: #CE9178; + --light-hl-6: #795E26; + --dark-hl-6: #DCDCAA; + --light-hl-7: #008000; + --dark-hl-7: #6A9955; + --light-hl-8: #098658; + --dark-hl-8: #B5CEA8; --light-hl-9: #267F99; --dark-hl-9: #4EC9B0; --light-hl-10: #000000; diff --git a/docs/assets/navigation.js b/docs/assets/navigation.js index 2ecaffa7..2a12b22c 100644 --- a/docs/assets/navigation.js +++ b/docs/assets/navigation.js @@ -1 +1 @@ -window.navigationData = "data:application/octet-stream;base64,H4sIAAAAAAAAA52YTXPTMBCG/4vPHQqFFuit9GPo8NHQtPTAcFCdTSOqSEaSMzVM/zsjp6klS9pVuPp995G8K61k//hbWXiw1WF1dGusZrWdKCWqnaphdlEdVrVgxoDZ9dUXC7t0lnsuZ9Xhq713jzsR5Ubpe9B5zlrHSMdc161g+khr1sWgQEY5ojUWdG5CgYxxTjrJlrx+8qezFHsKiFcLDWyGAgcLxjvjDzBD5zd2kDRsbiMDxpporjS33bcWWohJgYxx1qPlSumrGGXtOF4oXsPUambhjoM5VrLXIyxqx8Y5XYG0n5Vqri0X/A+zXMkvwEyrYQnSTi2z3Fhem2FMLi3oOavB7BZHh1PY2z/wpnAels7Dn8c1G4WO0+wHp5KcDA/S1mGw0FmA/qpmgAGdjmG8ZF40LrvpOsS2QihR361rmQy4hN8tXz/cYhg/Ch/SGHYH35lo06n2DRjILbZzOVdJyEakAFiVPB3F+J0mu4AiF45US27gEkyjpIEbzZoms23SVgy+2Q4nzLIk0jeUgCZK8Dq9D0MLBrti5j6JcAIVeNbK2tXp4vYX1DaLCW3F0AZ03ykvwbSigB76S4eZaNWAthzSizFtpeAT0HOll0zW6VU58lA4ov2ElnIY2XDydmoQ0+83bJdHLgyZOlYwOOKnhznVWqU3vafTmGyPHGQa4jpWf3s4Act4+vhPOsvQdA49F42kccUoYsmPTTTw2h1uCKvXMYx3147e03bN8P2RP79evn/7an/Pv1a6pfSRyZnwj5k1zddIjit8juNpJOeBZzGDRFE+cSE+wIKtuIowvlbCyczGkyiKd2saUzyJpvS3o8x0QpViXUjBZQ4ViBTJLbW+vmPKs1BCuOoaSAHccyretfEj08l6c0iOQZGhhIjB/ocTbdVALCFNiVecbvOGzx/amUYSGSgi/oG2hhZ8mmW4qfUxKCRDc8tuRUx4er5NN/EytWKau/CwpYwy9TrTCJIcX0cwz1srCRlUAuFSlyX0IgJI/8dI0dJOEp2dnScjELZiXLiACdNMCBDcLAfafLPxdlO+EHvw5vHnPwWuLITZFAAA" \ No newline at end of file +window.navigationData = "data:application/octet-stream;base64,H4sIAAAAAAAAA52Y21LbMBCG38XXTCm00JY7jlOmB1ISykWnF8LZEBVFciU5Q9rh3Tt2CJbs1a7S2/z/fpK1B9n58bfw8OiLo+L4znkrSj8yRhU7RSX8vDgqSiWcA7cbqq/mftFYHqSeFkd7+++fdgaUW2MfwKY5a50inUpb1krYk3o2w0ixTpJU7TzY1JYimeKcrbRYyPLZj5/T0JNBnMwtiCkJ7CwU70I+wpTcX9/B0kZWGiv96lsNNSR4kYclUk/bM1AsZmPZe1qvliqOUKUoa8fp3MgSxt4KD/cS3KnRrT7AknZqnfMlaP/ZmOrGSyX/CC+N/gLC1RYWoP3YCy+dl6Xr1pTag52JEtxudnS8hf2DQ7IsvpopoOvhVgp+GddFwLocFkQvtJ/DMBjLIBoe5WRFwWJnBjp5TIFOYYJMXVVN6vAkD22ZUKZ4ti4UNOAaftdy/eMWy4RR9JLOiXv4LlSNH3VooEBNsV3qmUEhG5EDUFkKdBKT1WdbtdjImoV0cA2uMtrBrRVVlWgb3ErBN+1wJrxAkaEhBzQySpZ4H8YWCjYR7gFFNAIXeFHrssnT1d0vKH0SE9uyoRXYdgxfg6tVBj325y4zsqYC6yXgxYhbOfgI7MzYhdAlXpU9D4djxk9syYexAydt5xZxbb9RXT5wUUjsWqHghJ9f5txagzd9oPOY5IzsZB7STKz21eQMvJD49Y8689D8GQYuHsnjslFMyfdNPPCmudwIVqtTmODTYPCcflV1n0vp++v1h3d7B/vhO2tTSh+FnqrwmlnTQo3lNIlPcQKN5TzKJKaTOMonqdQJzMVSmgEm1HI4id0EEkcJ3pr6lEDiKe3bUWI7scqxrrSSOoWKRI7UlFqb3z7lRcghTFYVYIDmdy6+GePHbqXLzSXZBw0MOUQK9j+cQatGYg5pzDzieJsnfPmKTwySgYEj0h9oa2jGp1mCi9VHp7AMK724U0PC8+/bTJPgpJbCyiY8Him9k3qTGAQoJ9QJzEtroZBOZRDN0SUJrUgA8D9JMBruZNHJ3QUyARFLIVUTMBJWKAVKukVHm20abxfzxdjDt08//wFIvxVvihUAAA==" \ No newline at end of file diff --git a/docs/assets/search.js b/docs/assets/search.js index 046e5838..a735f598 100644 --- a/docs/assets/search.js +++ b/docs/assets/search.js @@ -1 +1 @@ -window.searchData = "data:application/octet-stream;base64,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"; \ No newline at end of file +window.searchData = "data:application/octet-stream;base64,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"; \ No newline at end of file diff --git a/docs/classes/AbstractPool.html b/docs/classes/AbstractPool.html index b4b8a781..bcf1047c 100644 --- a/docs/classes/AbstractPool.html +++ b/docs/classes/AbstractPool.html @@ -1,8 +1,8 @@ -AbstractPool | poolifier - v4.0.1

Class AbstractPool<Worker, Data, Response>Abstract

Base class that implements some shared logic for all poolifier pools.

+AbstractPool | poolifier - v4.0.13

Class AbstractPool<Worker, Data, Response>Abstract

Base class that implements some shared logic for all poolifier pools.

Type Parameters

  • Worker extends IWorker

    Type of worker which manages this pool.

  • Data = unknown

    Type of data sent to the worker. This can only be structured-cloneable data.

  • Response = unknown

    Type of execution response. This can only be structured-cloneable data.

    -

Hierarchy (view full)

Implements

Constructors

Hierarchy (view full)

Implements

Constructors

Properties

  • filePath: string

    Path to the worker file.

  • opts: PoolOptions<Worker>

    Options for the pool.

  • Optional maximumNumberOfWorkers: number

    Maximum number of workers that this pool manages.

    -
  • Returns AbstractPool<Worker, Data, Response>

    Properties

    destroying: boolean

    Whether the pool is destroying or not.

    -
    emitter?: EventEmitterAsyncResource

    Pool event emitter integrated with async resource. +

    Returns AbstractPool<Worker, Data, Response>

    Properties

    destroying: boolean

    Whether the pool is destroying or not.

    +
    emitter?: EventEmitterAsyncResource

    Pool event emitter integrated with async resource. The async tracking tooling identifier is poolifier:<PoolType>-<WorkerType>-pool.

    Events that can currently be listened to:

      @@ -130,120 +130,124 @@ The async tracking tooling identifier is poolifier:<PoolType>-<Wo
    • 'taskError': Emitted when an error occurs while executing a task.
    • 'backPressure': Emitted when all worker nodes have back pressure (i.e. their tasks queue is full: queue size >= maximum queue size).
    -
    filePath: string

    Path to the worker file.

    -
    maximumNumberOfWorkers?: number

    Maximum number of workers that this pool manages.

    -
    minimumNumberOfWorkers: number

    Minimum number of workers that this pool manages.

    -

    Options for the pool.

    -
    promiseResponseMap: Map<string, PromiseResponseWrapper<Response>> = ...

    The task execution response promise map:

    +
    filePath: string

    Path to the worker file.

    +
    maximumNumberOfWorkers?: number

    Maximum number of workers that this pool manages.

    +
    minimumNumberOfWorkers: number

    Minimum number of workers that this pool manages.

    +

    Options for the pool.

    +
    promiseResponseMap: Map<`${string}-${string}-${string}-${string}-${string}`, PromiseResponseWrapper<Response>> = ...

    The task execution response promise map:

    • key: The message id of each submitted task.
    • value: An object that contains task's worker node key, execution response promise resolve and reject callbacks, async resource.

    When we receive a message from the worker, we get a map entry with the promise resolve/reject bound to the message id.

    -
    readyEventEmitted: boolean

    Whether the pool ready event has been emitted or not.

    -
    startTimestamp?: number

    The start timestamp of the pool.

    -
    started: boolean

    Whether the pool is started or not.

    -
    starting: boolean

    Whether the pool is starting or not.

    -
    startingMinimumNumberOfWorkers: boolean

    Whether the minimum number of workers is starting or not.

    -
    taskFunctions: Map<string, TaskFunctionObject<Data, Response>>

    The task functions added at runtime map:

    +
    readyEventEmitted: boolean

    Whether the pool ready event has been emitted or not.

    +
    startTimestamp?: number

    The start timestamp of the pool.

    +
    started: boolean

    Whether the pool is started or not.

    +
    starting: boolean

    Whether the pool is starting or not.

    +
    startingMinimumNumberOfWorkers: boolean

    Whether the minimum number of workers is starting or not.

    +
    taskFunctions: Map<string, TaskFunctionObject<Data, Response>>

    The task functions added at runtime map:

    • key: The task function name.
    • value: The task function object.
    -
    workerChoiceStrategiesContext?: WorkerChoiceStrategiesContext<Worker, Data, Response>

    Worker choice strategies context referencing worker choice algorithms implementation.

    -
    workerNodes: IWorkerNode<Worker, Data>[] = []

    Pool worker nodes.

    -

    Accessors

    workerChoiceStrategiesContext?: WorkerChoiceStrategiesContext<Worker, Data, Response>

    Worker choice strategies context referencing worker choice algorithms implementation.

    +
    workerNodes: IWorkerNode<Worker, Data>[] = []

    Pool worker nodes.

    +

    Accessors

    • get type(): "fixed" | "dynamic"
    • The pool type.

      If it is 'dynamic', it provides the max property.

      -

      Returns "fixed" | "dynamic"

    Methods

    Methods

    • Hook executed after the worker task execution. Can be overridden.

      Parameters

      • workerNodeKey: number

        The worker node key.

      • message: MessageValue<Response, unknown>

        The received message.

        -

      Returns void

    • Method hooked up after a worker node has been newly created. +

    Returns void

    • Method hooked up after a worker node has been newly created. Can be overridden.

      Parameters

      • workerNodeKey: number

        The newly created worker node key.

        -

      Returns void

    • Hook executed before the worker task execution. +

    Returns void

    • Hook executed before the worker task execution. Can be overridden.

      Parameters

      • workerNodeKey: number

        The worker node key.

      • task: Task<Data>

        The task to execute.

        -

      Returns void

    • Checks if the worker id sent in the received message from a worker is valid.

      +

    Returns void

    • Parameters

      • minimumNumberOfWorkers: undefined | number

      Returns void

    • Chooses a worker node for the next task given the worker choice strategy.

      -

      Parameters

      • Optional workerChoiceStrategy: "ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN"

        The worker choice strategy.

        -

      Returns number

      The chosen worker node key

      -
    • Parameters

      • minimumNumberOfWorkers: undefined | number

      Returns void

    • Chooses a worker node for the next task.

      +

      Parameters

      • Optional name: string

        The task function name.

        +

      Returns number

      The chosen worker node key.

      +
    • Creates a new, completely set up dynamic worker node.

      Returns number

      New, completely set up dynamic worker node key.

      -
    • Creates a new, completely set up worker node.

      Returns number

      New, completely set up worker node key.

      -
    • Deregisters a listener callback on the worker given its worker node key.

      Type Parameters

      • Message

      Parameters

      • workerNodeKey: number

        The worker node key.

      • listener: ((message) => void)

        The message listener callback.

        -

      Returns void

    • Terminates the worker node given its worker node key.

      +

    Returns void

    • Terminates the worker node given its worker node key.

      Parameters

      • workerNodeKey: number

        The worker node key.

        -

      Returns Promise<void>

    • Executes the given task on the worker given its worker node key.

      +

    Returns Promise<void>

    • Executes the given task on the worker given its worker node key.

      Parameters

      • workerNodeKey: number

        The worker node key.

      • task: Task<Data>

        The task to execute.

        -

      Returns void

    • Gets task function strategy, if any.

      +

    Returns void

    • Gets task function worker choice strategy, if any.

      Parameters

      • Optional name: string

        The task function name.

      Returns undefined | "ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN"

      The task function worker choice strategy if the task function worker choice strategy is defined, undefined otherwise.

      -
    • Gets the worker choice strategies registered in this pool.

      +

      Returns Set<"ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN">

      The worker choice strategies.

      +
    • Gets the worker information given its worker node key.

      Parameters

      • workerNodeKey: number

        The worker node key.

      Returns undefined | WorkerInfo

      The worker information.

      -
    • Gets the worker node key given its worker id.

      Parameters

      • workerId: undefined | number

        The worker id.

      Returns number

      The worker node key if the worker id is found in the pool worker nodes, -1 otherwise.

      -
    • Gets worker node task function priority, if any.

      +
    • Gets worker node task function priority, if any.

      Parameters

      • workerNodeKey: number

        The worker node key.

      • Optional name: string

        The task function name.

        -

      Returns undefined | number

      The task function worker choice priority if the task function worker choice priority is defined, undefined otherwise.

      -
    • Gets the worker choice strategies registered in this pool.

      -

      Returns Set<"ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN">

      The worker choice strategies.

      -
    • Initializes the worker node usage with sensible default values gathered during runtime.

      +

    Returns undefined | number

    The worker node task function priority if the worker node task function priority is defined, undefined otherwise.

    +
    • Gets worker node task function worker choice strategy, if any.

      +

      Parameters

      • workerNodeKey: number

        The worker node key.

        +
      • Optional name: string

        The task function name.

        +

      Returns undefined | "ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN"

      The worker node task function worker choice strategy if the worker node task function worker choice strategy is defined, undefined otherwise.

      +
    • Whether worker nodes are executing concurrently their tasks quota or not.

      +

    Returns void

    • Whether worker nodes are executing concurrently their tasks quota or not.

      Returns boolean

      Worker nodes busyness boolean status.

      -
    • Returns whether the worker is the main worker or not.

      Returns boolean

      true if the worker is the main worker, false otherwise.

      -
    • Registers once a listener callback on the worker given its worker node key.

      +
    • Registers once a listener callback on the worker given its worker node key.

      Type Parameters

      • Message

      Parameters

      • workerNodeKey: number

        The worker node key.

      • listener: ((message) => void)

        The message listener callback.

        -

      Returns void

    • Registers a listener callback on the worker given its worker node key.

      +

    Returns void

    • Registers a listener callback on the worker given its worker node key.

      Type Parameters

      • Message

      Parameters

      • workerNodeKey: number

        The worker node key.

      • listener: ((message) => void)

        The message listener callback.

        -

      Returns void

    • Removes the worker node from the pool worker nodes.

      +

    Returns void

    • Parameters

      • workerNodeKey: number
      • taskName: string

      Returns void

    • Sends the startup message to worker given its worker node key.

      +

    Returns void

    • Parameters

      • workerNodeKey: number
      • taskName: string

      Returns void

    • Sends the startup message to worker given its worker node key.

      Parameters

      • workerNodeKey: number

        The worker node key.

        -

      Returns void

    • Sends the statistics message to worker given its worker node key.

      +

    Returns void

    • Sends the statistics message to worker given its worker node key.

      Parameters

      • workerNodeKey: number

        The worker node key.

        -

      Returns void

    • Sends a message to worker given its worker node key.

      +

    Returns void

    • Sends a message to worker given its worker node key.

      Parameters

      • workerNodeKey: number

        The worker node key.

      • message: MessageValue<Data, unknown>

        The message.

      • Optional transferList: readonly TransferListItem[]

        The optional array of transferable objects.

        -

      Returns void

    • Setup hook to execute code before worker nodes are created in the abstract constructor. +

    Returns void

    • Setup hook to execute code before worker nodes are created in the abstract constructor. Can be overridden.

      -

      Returns void

    • Conditions for dynamic worker creation.

      Returns boolean

      Whether to create a dynamic worker or not.

      -
    • Whether the worker node shall update its task function worker usage or not.

      +
    • Whether the worker node shall update its task function worker usage or not.

      Parameters

      • workerNodeKey: number

        The worker node key.

      Returns boolean

      true if the worker node shall update its task function worker usage, false otherwise.

      -
    • Starts the minimum number of workers.

      -

      Parameters

      • initWorkerNodeUsage: boolean = false

      Returns void

    • Parameters

      • workerNodeKey: number
      • taskName: string

      Returns void

    • Parameters

      • workerNodeKey: number

      Returns void

    • Parameters

      • workerNodeKey: number
      • taskName: string

      Returns void

    \ No newline at end of file +
    • Starts the minimum number of workers.

      +

      Parameters

      • initWorkerNodeUsage: boolean = false

      Returns void

    • Parameters

      • workerNodeKey: number
      • taskName: string
      • Optional previousTaskName: string

      Returns void

    • Parameters

      • workerNodeKey: number
      • taskName: string

      Returns void

    \ No newline at end of file diff --git a/docs/classes/AbstractWorker.html b/docs/classes/AbstractWorker.html index e3e05343..3320ed35 100644 --- a/docs/classes/AbstractWorker.html +++ b/docs/classes/AbstractWorker.html @@ -1,8 +1,8 @@ -AbstractWorker | poolifier - v4.0.1

    Class AbstractWorker<MainWorker, Data, Response>Abstract

    Base class that implements some shared logic for all poolifier workers.

    +AbstractWorker | poolifier - v4.0.13

    Class AbstractWorker<MainWorker, Data, Response>Abstract

    Base class that implements some shared logic for all poolifier workers.

    Type Parameters

    • MainWorker extends Worker | MessagePort

      Type of main worker.

    • Data = unknown

      Type of data this worker receives from pool's execution. This can only be structured-cloneable data.

    • Response = unknown

      Type of response the worker sends back to the main worker. This can only be structured-cloneable data.

      -

    Hierarchy (view full)

    Constructors

    Hierarchy (view full)

    Constructors

    Properties

    activeInterval? id isMain @@ -41,58 +41,58 @@
  • mainWorker: undefined | null | MainWorker

    Reference to main worker.

  • taskFunctions: TaskFunction<Data, Response> | TaskFunctions<Data, Response>

    Task function(s) processed by the worker when the pool's execution function is invoked. The first function is the default function.

  • opts: WorkerOptions = DEFAULT_WORKER_OPTIONS

    Options for the worker.

    -
  • Returns AbstractWorker<MainWorker, Data, Response>

    Properties

    activeInterval?: Timeout

    Handler id of the activeInterval worker activity check.

    -
    id: number

    Worker id.

    -
    isMain: undefined | boolean

    Whether this is the main worker or not.

    -
    lastTaskTimestamp: number

    Timestamp of the last task processed by this worker.

    -
    mainWorker: undefined | null | MainWorker

    Reference to main worker.

    -
    opts: WorkerOptions = DEFAULT_WORKER_OPTIONS

    Options for the worker.

    -
    statistics?: WorkerStatistics

    Performance statistics computation requirements.

    -
    taskFunctions: Map<string, TaskFunctionObject<Data, Response>>

    Task function object(s) processed by the worker when the pool's execution function is invoked.

    -

    Methods

    Returns AbstractWorker<MainWorker, Data, Response>

    Properties

    activeInterval?: Timeout

    Handler id of the activeInterval worker activity check.

    +
    id: number

    Worker id.

    +
    isMain: undefined | boolean

    Whether this is the main worker or not.

    +
    lastTaskTimestamp: number

    Timestamp of the last task processed by this worker.

    +
    mainWorker: undefined | null | MainWorker

    Reference to main worker.

    +
    opts: WorkerOptions = DEFAULT_WORKER_OPTIONS

    Options for the worker.

    +
    statistics?: WorkerStatistics

    Performance statistics computation requirements.

    +
    taskFunctions: Map<string, TaskFunctionObject<Data, Response>>

    Task function object(s) processed by the worker when the pool's execution function is invoked.

    +

    Methods

    • Returns the main worker.

      +

    Returns void

    • Handles an error and convert it to a string so it can be sent back to the main worker.

      Parameters

      • error: string | Error

        The error raised by the worker.

      Returns string

      The error message.

      -

    Returns void

    Returns void

    • Runs the given task function asynchronously.

      +

    Returns void

    • Runs the given task function synchronously.

      +

    Returns void

    • Sends a message to main worker.

      +

    Returns void

    Returns void

    \ No newline at end of file +
    \ No newline at end of file diff --git a/docs/classes/CircularArray.html b/docs/classes/CircularArray.html deleted file mode 100644 index f0bc7c13..00000000 --- a/docs/classes/CircularArray.html +++ /dev/null @@ -1,184 +0,0 @@ -CircularArray | poolifier - v4.0.1

    Class CircularArray<T>Internal

    Array with a maximum length and shifting items when full.

    -

    Type Parameters

    • T

      Type of items.

      -

    Hierarchy

    • Array<T>
      • CircularArray

    Constructors

    Properties

    [unscopables]: {
        [unscopables]?: boolean;
        length?: boolean;
        [iterator]?: any;
        at?: any;
        concat?: any;
        copyWithin?: any;
        entries?: any;
        every?: any;
        fill?: any;
        filter?: any;
        find?: any;
        findIndex?: any;
        flat?: any;
        flatMap?: any;
        forEach?: any;
        includes?: any;
        indexOf?: any;
        join?: any;
        keys?: any;
        lastIndexOf?: any;
        map?: any;
        pop?: any;
        push?: any;
        reduce?: any;
        reduceRight?: any;
        reverse?: any;
        shift?: any;
        slice?: any;
        some?: any;
        sort?: any;
        splice?: any;
        toLocaleString?: any;
        toString?: any;
        unshift?: any;
        values?: any;
    }

    Is an object whose properties have the value 'true' -when they will be absent when used in a 'with' statement.

    -

    Type declaration

    • Optional Readonly [unscopables]?: boolean

      Is an object whose properties have the value 'true' -when they will be absent when used in a 'with' statement.

      -
    • Optional length?: boolean

      Gets or sets the length of the array. This is a number one higher than the highest index in the array.

      -
    length: number

    Gets or sets the length of the array. This is a number one higher than the highest index in the array.

    -
    size: number
    [species]: ArrayConstructor

    Methods

    • Iterator

      -

      Returns IterableIterator<T>

    • Returns the item located at the specified index.

      -

      Parameters

      • index: number

        The zero-based index of the desired code unit. A negative index will count back from the last item.

        -

      Returns undefined | T

    • Returns the this object after copying a section of the array identified by start and end -to the same array starting at position target

      -

      Parameters

      • target: number

        If target is negative, it is treated as length+target where length is the -length of the array.

        -
      • start: number

        If start is negative, it is treated as length+start. If end is negative, it -is treated as length+end.

        -
      • Optional end: number

        If not specified, length of the this object is used as its default value.

        -

      Returns this

    • Returns an iterable of key, value pairs for every entry in the array

      -

      Returns IterableIterator<[number, T]>

    • Determines whether all the members of an array satisfy the specified test.

      -

      Type Parameters

      • S

      Parameters

      • predicate: ((value, index, array) => value is S)

        A function that accepts up to three arguments. The every method calls -the predicate function for each element in the array until the predicate returns a value -which is coercible to the Boolean value false, or until the end of the array.

        -
          • (value, index, array): value is S
          • Parameters

            • value: T
            • index: number
            • array: T[]

            Returns value is S

      • Optional thisArg: any

        An object to which the this keyword can refer in the predicate function. -If thisArg is omitted, undefined is used as the this value.

        -

      Returns this is S[]

    • Determines whether all the members of an array satisfy the specified test.

      -

      Parameters

      • predicate: ((value, index, array) => unknown)

        A function that accepts up to three arguments. The every method calls -the predicate function for each element in the array until the predicate returns a value -which is coercible to the Boolean value false, or until the end of the array.

        -
          • (value, index, array): unknown
          • Parameters

            • value: T
            • index: number
            • array: T[]

            Returns unknown

      • Optional thisArg: any

        An object to which the this keyword can refer in the predicate function. -If thisArg is omitted, undefined is used as the this value.

        -

      Returns boolean

    • Changes all array elements from start to end index to a static value and returns the modified array

      -

      Parameters

      • value: T

        value to fill array section with

        -
      • Optional start: number

        index to start filling the array at. If start is negative, it is treated as -length+start where length is the length of the array.

        -
      • Optional end: number

        index to stop filling the array at. If end is negative, it is treated as -length+end.

        -

      Returns this

    • Returns the elements of an array that meet the condition specified in a callback function.

      -

      Type Parameters

      • S

      Parameters

      • predicate: ((value, index, array) => value is S)

        A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.

        -
          • (value, index, array): value is S
          • Parameters

            • value: T
            • index: number
            • array: T[]

            Returns value is S

      • Optional thisArg: any

        An object to which the this keyword can refer in the predicate function. If thisArg is omitted, undefined is used as the this value.

        -

      Returns S[]

    • Returns the elements of an array that meet the condition specified in a callback function.

      -

      Parameters

      • predicate: ((value, index, array) => unknown)

        A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.

        -
          • (value, index, array): unknown
          • Parameters

            • value: T
            • index: number
            • array: T[]

            Returns unknown

      • Optional thisArg: any

        An object to which the this keyword can refer in the predicate function. If thisArg is omitted, undefined is used as the this value.

        -

      Returns T[]

    • Returns the value of the first element in the array where predicate is true, and undefined -otherwise.

      -

      Type Parameters

      • S

      Parameters

      • predicate: ((value, index, obj) => value is S)

        find calls predicate once for each element of the array, in ascending -order, until it finds one where predicate returns true. If such an element is found, find -immediately returns that element value. Otherwise, find returns undefined.

        -
          • (value, index, obj): value is S
          • Parameters

            • value: T
            • index: number
            • obj: T[]

            Returns value is S

      • Optional thisArg: any

        If provided, it will be used as the this value for each invocation of -predicate. If it is not provided, undefined is used instead.

        -

      Returns undefined | S

    • Parameters

      • predicate: ((value, index, obj) => unknown)
          • (value, index, obj): unknown
          • Parameters

            • value: T
            • index: number
            • obj: T[]

            Returns unknown

      • Optional thisArg: any

      Returns undefined | T

    • Returns the index of the first element in the array where predicate is true, and -1 -otherwise.

      -

      Parameters

      • predicate: ((value, index, obj) => unknown)

        find calls predicate once for each element of the array, in ascending -order, until it finds one where predicate returns true. If such an element is found, -findIndex immediately returns that element index. Otherwise, findIndex returns -1.

        -
          • (value, index, obj): unknown
          • Parameters

            • value: T
            • index: number
            • obj: T[]

            Returns unknown

      • Optional thisArg: any

        If provided, it will be used as the this value for each invocation of -predicate. If it is not provided, undefined is used instead.

        -

      Returns number

    • Returns a new array with all sub-array elements concatenated into it recursively up to the -specified depth.

      -

      Type Parameters

      • A
      • D extends number = 1

      Parameters

      • this: A
      • Optional depth: D

        The maximum recursion depth

        -

      Returns FlatArray<A, D>[]

    • Calls a defined callback function on each element of an array. Then, flattens the result into -a new array. -This is identical to a map followed by flat with depth 1.

      -

      Type Parameters

      • U
      • This = undefined

      Parameters

      • callback: ((this, value, index, array) => U | readonly U[])

        A function that accepts up to three arguments. The flatMap method calls the -callback function one time for each element in the array.

        -
          • (this, value, index, array): U | readonly U[]
          • Parameters

            • this: This
            • value: T
            • index: number
            • array: T[]

            Returns U | readonly U[]

      • Optional thisArg: This

        An object to which the this keyword can refer in the callback function. If -thisArg is omitted, undefined is used as the this value.

        -

      Returns U[]

    • Performs the specified action for each element in an array.

      -

      Parameters

      • callbackfn: ((value, index, array) => void)

        A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.

        -
          • (value, index, array): void
          • Parameters

            • value: T
            • index: number
            • array: T[]

            Returns void

      • Optional thisArg: any

        An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.

        -

      Returns void

    • Determines whether an array includes a certain element, returning true or false as appropriate.

      -

      Parameters

      • searchElement: T

        The element to search for.

        -
      • Optional fromIndex: number

        The position in this array at which to begin searching for searchElement.

        -

      Returns boolean

    • Returns the index of the first occurrence of a value in an array, or -1 if it is not present.

      -

      Parameters

      • searchElement: T

        The value to locate in the array.

        -
      • Optional fromIndex: number

        The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0.

        -

      Returns number

    • Adds all the elements of an array into a string, separated by the specified separator string.

      -

      Parameters

      • Optional separator: string

        A string used to separate one element of the array from the next in the resulting string. If omitted, the array elements are separated with a comma.

        -

      Returns string

    • Returns an iterable of keys in the array

      -

      Returns IterableIterator<number>

    • Returns the index of the last occurrence of a specified value in an array, or -1 if it is not present.

      -

      Parameters

      • searchElement: T

        The value to locate in the array.

        -
      • Optional fromIndex: number

        The array index at which to begin searching backward. If fromIndex is omitted, the search starts at the last index in the array.

        -

      Returns number

    • Calls a defined callback function on each element of an array, and returns an array that contains the results.

      -

      Type Parameters

      • U

      Parameters

      • callbackfn: ((value, index, array) => U)

        A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.

        -
          • (value, index, array): U
          • Parameters

            • value: T
            • index: number
            • array: T[]

            Returns U

      • Optional thisArg: any

        An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.

        -

      Returns U[]

    • Removes the last element from an array and returns it. -If the array is empty, undefined is returned and the array is not modified.

      -

      Returns undefined | T

    • Parameters

      • Rest ...items: T[]

      Returns number

      Inherit Doc

    • Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.

      -

      Parameters

      • callbackfn: ((previousValue, currentValue, currentIndex, array) => T)

        A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.

        -
          • (previousValue, currentValue, currentIndex, array): T
          • Parameters

            • previousValue: T
            • currentValue: T
            • currentIndex: number
            • array: T[]

            Returns T

      Returns T

    • Parameters

      • callbackfn: ((previousValue, currentValue, currentIndex, array) => T)
          • (previousValue, currentValue, currentIndex, array): T
          • Parameters

            • previousValue: T
            • currentValue: T
            • currentIndex: number
            • array: T[]

            Returns T

      • initialValue: T

      Returns T

    • Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.

      -

      Type Parameters

      • U

      Parameters

      • callbackfn: ((previousValue, currentValue, currentIndex, array) => U)

        A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.

        -
          • (previousValue, currentValue, currentIndex, array): U
          • Parameters

            • previousValue: U
            • currentValue: T
            • currentIndex: number
            • array: T[]

            Returns U

      • initialValue: U

        If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.

        -

      Returns U

    • Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.

      -

      Parameters

      • callbackfn: ((previousValue, currentValue, currentIndex, array) => T)

        A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.

        -
          • (previousValue, currentValue, currentIndex, array): T
          • Parameters

            • previousValue: T
            • currentValue: T
            • currentIndex: number
            • array: T[]

            Returns T

      Returns T

    • Parameters

      • callbackfn: ((previousValue, currentValue, currentIndex, array) => T)
          • (previousValue, currentValue, currentIndex, array): T
          • Parameters

            • previousValue: T
            • currentValue: T
            • currentIndex: number
            • array: T[]

            Returns T

      • initialValue: T

      Returns T

    • Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.

      -

      Type Parameters

      • U

      Parameters

      • callbackfn: ((previousValue, currentValue, currentIndex, array) => U)

        A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.

        -
          • (previousValue, currentValue, currentIndex, array): U
          • Parameters

            • previousValue: U
            • currentValue: T
            • currentIndex: number
            • array: T[]

            Returns U

      • initialValue: U

        If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.

        -

      Returns U

    • Reverses the elements in an array in place. -This method mutates the array and returns a reference to the same array.

      -

      Returns T[]

    • Removes the first element from an array and returns it. -If the array is empty, undefined is returned and the array is not modified.

      -

      Returns undefined | T

    • Returns a copy of a section of an array. -For both start and end, a negative index can be used to indicate an offset from the end of the array. -For example, -2 refers to the second to last element of the array.

      -

      Parameters

      • Optional start: number

        The beginning index of the specified portion of the array. -If start is undefined, then the slice begins at index 0.

        -
      • Optional end: number

        The end index of the specified portion of the array. This is exclusive of the element at the index 'end'. -If end is undefined, then the slice extends to the end of the array.

        -

      Returns T[]

    • Determines whether the specified callback function returns true for any element of an array.

      -

      Parameters

      • predicate: ((value, index, array) => unknown)

        A function that accepts up to three arguments. The some method calls -the predicate function for each element in the array until the predicate returns a value -which is coercible to the Boolean value true, or until the end of the array.

        -
          • (value, index, array): unknown
          • Parameters

            • value: T
            • index: number
            • array: T[]

            Returns unknown

      • Optional thisArg: any

        An object to which the this keyword can refer in the predicate function. -If thisArg is omitted, undefined is used as the this value.

        -

      Returns boolean

    • Sorts an array in place. -This method mutates the array and returns a reference to the same array.

      -

      Parameters

      • Optional compareFn: ((a, b) => number)

        Function used to determine the order of the elements. It is expected to return -a negative value if the first argument is less than the second argument, zero if they're equal, and a positive -value otherwise. If omitted, the elements are sorted in ascending, ASCII character order.

        -
        [11,2,22,1].sort((a, b) => a - b)
        -
        -
          • (a, b): number
          • Parameters

            Returns number

      Returns this

    • Returns a string representation of an array. The elements are converted to string using their toLocaleString methods.

      -

      Returns string

    • Returns a string representation of an array.

      -

      Returns string

    • Parameters

      • Rest ...items: T[]

      Returns number

      Inherit Doc

    • Returns an iterable of values in the array

      -

      Returns IterableIterator<T>

    • Creates an array from an array-like object.

      -

      Type Parameters

      • T

      Parameters

      • arrayLike: ArrayLike<T>

        An array-like object to convert to an array.

        -

      Returns T[]

    • Creates an array from an iterable object.

      -

      Type Parameters

      • T
      • U

      Parameters

      • arrayLike: ArrayLike<T>

        An array-like object to convert to an array.

        -
      • mapfn: ((v, k) => U)

        A mapping function to call on every element of the array.

        -
          • (v, k): U
          • Parameters

            • v: T
            • k: number

            Returns U

      • Optional thisArg: any

        Value of 'this' used to invoke the mapfn.

        -

      Returns U[]

    • Creates an array from an iterable object.

      -

      Type Parameters

      • T

      Parameters

      • iterable: Iterable<T> | ArrayLike<T>

        An iterable object to convert to an array.

        -

      Returns T[]

    • Creates an array from an iterable object.

      -

      Type Parameters

      • T
      • U

      Parameters

      • iterable: Iterable<T> | ArrayLike<T>

        An iterable object to convert to an array.

        -
      • mapfn: ((v, k) => U)

        A mapping function to call on every element of the array.

        -
          • (v, k): U
          • Parameters

            • v: T
            • k: number

            Returns U

      • Optional thisArg: any

        Value of 'this' used to invoke the mapfn.

        -

      Returns U[]

    • Parameters

      • arg: any

      Returns arg is any[]

    • Returns a new array from a set of elements.

      -

      Type Parameters

      • T

      Parameters

      • Rest ...items: T[]

        A set of elements to include in the new array object.

        -

      Returns T[]

    \ No newline at end of file diff --git a/docs/classes/CircularBuffer.html b/docs/classes/CircularBuffer.html new file mode 100644 index 00000000..996c1945 --- /dev/null +++ b/docs/classes/CircularBuffer.html @@ -0,0 +1,30 @@ +CircularBuffer | poolifier - v4.0.13

    Class CircularBufferInternal

    Circular buffer designed for positive numbers.

    +

    Constructors

    Properties

    Methods

    Constructors

    Properties

    items: Float32Array
    maxArrayIdx: number
    readIdx: number
    size: number
    writeIdx: number

    Methods

    • Checks the buffer size.

      +

      Parameters

      • size: number

        Buffer size.

        +

      Returns void

    • Checks whether the buffer is empty.

      +

      Returns boolean

      Whether the buffer is empty.

      +
    • Checks whether the buffer is full.

      +

      Returns boolean

      Whether the buffer is full.

      +
    • Gets number from buffer.

      +

      Returns undefined | number

      Number from buffer.

      +
    • Puts number into buffer.

      +

      Parameters

      • number: number

        Number to put into buffer.

        +

      Returns void

    \ No newline at end of file diff --git a/docs/classes/ClusterWorker.html b/docs/classes/ClusterWorker.html index 0e57e1f8..4c7c8415 100644 --- a/docs/classes/ClusterWorker.html +++ b/docs/classes/ClusterWorker.html @@ -1,4 +1,4 @@ -ClusterWorker | poolifier - v4.0.1

    Class ClusterWorker<Data, Response>

    A cluster worker used by a poolifier ClusterPool.

    +ClusterWorker | poolifier - v4.0.13

    Class ClusterWorker<Data, Response>

    A cluster worker used by a poolifier ClusterPool.

    When this worker is inactive for more than the given maxInactiveTime, it will send a termination request to its main worker.

    If you use a DynamicClusterPool the extra workers that were created will be terminated, @@ -7,7 +7,7 @@ but the minimum number of workers will be guaranteed.

    Since

    2.0.0

    Type Parameters

    • Data = unknown

      Type of data this worker receives from pool's execution. This can only be structured-cloneable data.

    • Response = unknown

      Type of response the worker sends back to the main worker. This can only be structured-cloneable data.

      -

    Hierarchy (view full)

    Constructors

    Hierarchy (view full)

    Constructors

    Properties

    activeInterval? isMain lastTaskTimestamp @@ -34,49 +34,49 @@ but the minimum number of workers will be guaranteed.

    Constructors

    Properties

    activeInterval?: Timeout

    Handler id of the activeInterval worker activity check.

    -
    isMain: undefined | boolean

    Whether this is the main worker or not.

    -
    lastTaskTimestamp: number

    Timestamp of the last task processed by this worker.

    -
    opts: WorkerOptions = DEFAULT_WORKER_OPTIONS

    Options for the worker.

    -
    statistics?: WorkerStatistics

    Performance statistics computation requirements.

    -
    taskFunctions: Map<string, TaskFunctionObject<Data, Response>>

    Task function object(s) processed by the worker when the pool's execution function is invoked.

    -

    Accessors

    Methods

    Returns ClusterWorker<Data, Response>

    Properties

    activeInterval?: Timeout

    Handler id of the activeInterval worker activity check.

    +
    isMain: undefined | boolean

    Whether this is the main worker or not.

    +
    lastTaskTimestamp: number

    Timestamp of the last task processed by this worker.

    +
    opts: WorkerOptions = DEFAULT_WORKER_OPTIONS

    Options for the worker.

    +
    statistics?: WorkerStatistics

    Performance statistics computation requirements.

    +
    taskFunctions: Map<string, TaskFunctionObject<Data, Response>>

    Task function object(s) processed by the worker when the pool's execution function is invoked.

    +

    Accessors

    Methods

    • Handles an error and convert it to a string so it can be sent back to the main worker.

      Parameters

      • error: string | Error

        The error raised by the worker.

      Returns string

      The error message.

      -

    Returns void

    Returns void

    • Runs the given task function asynchronously.

      +

    Returns void

    • Runs the given task function synchronously.

      +

    Returns void

    • Sends a message to main worker.

      +

    Returns void

    Returns void

    \ No newline at end of file +
    \ No newline at end of file diff --git a/docs/classes/DynamicClusterPool.html b/docs/classes/DynamicClusterPool.html index 2a05f211..a41c3399 100644 --- a/docs/classes/DynamicClusterPool.html +++ b/docs/classes/DynamicClusterPool.html @@ -1,11 +1,11 @@ -DynamicClusterPool | poolifier - v4.0.1

    Class DynamicClusterPool<Data, Response>

    A cluster pool with a dynamic number of workers, but a guaranteed minimum number of workers.

    +DynamicClusterPool | poolifier - v4.0.13

    Class DynamicClusterPool<Data, Response>

    A cluster pool with a dynamic number of workers, but a guaranteed minimum number of workers.

    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.

    Author

    Christopher Quadflieg

    Since

    2.0.0

    Type Parameters

    • Data = unknown

      Type of data sent to the worker. This can only be structured-cloneable data.

    • Response = unknown

      Type of execution response. This can only be structured-cloneable data.

      -

    Hierarchy (view full)

    Constructors

    Hierarchy (view full)

    Constructors

    Properties

    emitter? filePath maximumNumberOfWorkers? @@ -59,7 +59,7 @@ When the maximum number of workers is reached and workers are busy, an event is
  • max: number

    Maximum number of workers that can be created by this pool.

  • filePath: string

    Path to an implementation of a ClusterWorker file, which can be relative or absolute.

  • opts: ClusterPoolOptions = {}

    Options for this dynamic cluster pool.

    -
  • Returns DynamicClusterPool<Data, Response>

    Properties

    emitter?: EventEmitterAsyncResource

    Pool event emitter integrated with async resource. +

    Returns DynamicClusterPool<Data, Response>

    Properties

    emitter?: EventEmitterAsyncResource

    Pool event emitter integrated with async resource. The async tracking tooling identifier is poolifier:<PoolType>-<WorkerType>-pool.

    Events that can currently be listened to:

      @@ -72,72 +72,72 @@ The async tracking tooling identifier is poolifier:<PoolType>-<Wo
    • 'taskError': Emitted when an error occurs while executing a task.
    • 'backPressure': Emitted when all worker nodes have back pressure (i.e. their tasks queue is full: queue size >= maximum queue size).
    -
    filePath: string

    Path to the worker file.

    -
    maximumNumberOfWorkers?: number

    Maximum number of workers that this pool manages.

    -
    minimumNumberOfWorkers: number

    Minimum number of workers that this pool manages.

    -
    opts: PoolOptions<Worker>

    Options for the pool.

    -
    promiseResponseMap: Map<string, PromiseResponseWrapper<Response>> = ...

    The task execution response promise map:

    +
    filePath: string

    Path to the worker file.

    +
    maximumNumberOfWorkers?: number

    Maximum number of workers that this pool manages.

    +
    minimumNumberOfWorkers: number

    Minimum number of workers that this pool manages.

    +
    opts: PoolOptions<Worker>

    Options for the pool.

    +
    promiseResponseMap: Map<`${string}-${string}-${string}-${string}-${string}`, PromiseResponseWrapper<Response>> = ...

    The task execution response promise map:

    • key: The message id of each submitted task.
    • value: An object that contains task's worker node key, execution response promise resolve and reject callbacks, async resource.

    When we receive a message from the worker, we get a map entry with the promise resolve/reject bound to the message id.

    -
    workerChoiceStrategiesContext?: WorkerChoiceStrategiesContext<Worker, Data, Response>

    Worker choice strategies context referencing worker choice algorithms implementation.

    -
    workerNodes: IWorkerNode<Worker, Data>[] = []

    Pool worker nodes.

    -

    Accessors

    workerChoiceStrategiesContext?: WorkerChoiceStrategiesContext<Worker, Data, Response>

    Worker choice strategies context referencing worker choice algorithms implementation.

    +
    workerNodes: IWorkerNode<Worker, Data>[] = []

    Pool worker nodes.

    +

    Accessors

    • get busy(): boolean
    • Whether the pool is busy or not.

      The pool busyness boolean status.

      -

      Returns boolean

    • get full(): boolean
    • Whether the pool is full or not.

      The pool filling boolean status.

      -

      Returns boolean

    • get type(): "fixed" | "dynamic"
    • The pool type.

      If it is 'dynamic', it provides the max property.

      -

      Returns "fixed" | "dynamic"

    • get utilization(): number
    • The approximate pool utilization.

      +

      Returns "fixed" | "dynamic"

    • get utilization(): number
    • The approximate pool utilization.

      Returns number

      The pool utilization.

      -
    • get worker(): "thread" | "cluster"
    • The worker type.

      -

      Returns "thread" | "cluster"

    Methods

    • Hook executed after the worker task execution. +

    • get worker(): "thread" | "cluster"
    • The worker type.

      +

      Returns "thread" | "cluster"

    Methods

    • Method hooked up after a worker node has been newly created. +

    Returns void

    • Hook executed before the worker task execution. +

    Returns void

    • Creates a new, completely set up dynamic worker node.

      +

    Returns void

    • Terminates the worker node given its worker node key.

      +

    Returns void

    • Gets the worker information given its worker node key.

      +

    Returns Promise<void>

    • Registers a listener callback on the worker given its worker node key.

      +

    Returns void

    • Sends the startup message to worker given its worker node key.

      +

    Returns void

    • Sends a message to worker given its worker node key.

      +

    Returns void

    • Setup hook to execute code before worker nodes are created in the abstract constructor. +

    Returns void

    \ No newline at end of file +
    \ No newline at end of file diff --git a/docs/classes/DynamicThreadPool.html b/docs/classes/DynamicThreadPool.html index e89edb7e..15698fb0 100644 --- a/docs/classes/DynamicThreadPool.html +++ b/docs/classes/DynamicThreadPool.html @@ -1,11 +1,11 @@ -DynamicThreadPool | poolifier - v4.0.1

    Class DynamicThreadPool<Data, Response>

    A thread pool with a dynamic number of threads, but a guaranteed minimum number of threads.

    +DynamicThreadPool | poolifier - v4.0.13

    Class DynamicThreadPool<Data, Response>

    A thread pool with a dynamic number of threads, but a guaranteed minimum number of threads.

    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.

    Author

    Alessandro Pio Ardizio

    Since

    0.0.1

    Type Parameters

    • Data = unknown

      Type of data sent to the worker. This can only be structured-cloneable data.

    • Response = unknown

      Type of execution response. This can only be structured-cloneable data.

      -

    Hierarchy (view full)

    Constructors

    Hierarchy (view full)

    Constructors

    Properties

    emitter? filePath maximumNumberOfWorkers? @@ -59,7 +59,7 @@ When the maximum number of threads is reached and workers are busy, an event is
  • max: number

    Maximum number of threads that can be created by this pool.

  • filePath: string

    Path to an implementation of a ThreadWorker file, which can be relative or absolute.

  • opts: ThreadPoolOptions = {}

    Options for this dynamic thread pool.

    -
  • Returns DynamicThreadPool<Data, Response>

    Properties

    emitter?: EventEmitterAsyncResource

    Pool event emitter integrated with async resource. +

    Returns DynamicThreadPool<Data, Response>

    Properties

    emitter?: EventEmitterAsyncResource

    Pool event emitter integrated with async resource. The async tracking tooling identifier is poolifier:<PoolType>-<WorkerType>-pool.

    Events that can currently be listened to:

      @@ -72,73 +72,73 @@ The async tracking tooling identifier is poolifier:<PoolType>-<Wo
    • 'taskError': Emitted when an error occurs while executing a task.
    • 'backPressure': Emitted when all worker nodes have back pressure (i.e. their tasks queue is full: queue size >= maximum queue size).
    -
    filePath: string

    Path to the worker file.

    -
    maximumNumberOfWorkers?: number

    Maximum number of workers that this pool manages.

    -
    minimumNumberOfWorkers: number

    Minimum number of workers that this pool manages.

    -
    opts: PoolOptions<Worker>

    Options for the pool.

    -
    promiseResponseMap: Map<string, PromiseResponseWrapper<Response>> = ...

    The task execution response promise map:

    +
    filePath: string

    Path to the worker file.

    +
    maximumNumberOfWorkers?: number

    Maximum number of workers that this pool manages.

    +
    minimumNumberOfWorkers: number

    Minimum number of workers that this pool manages.

    +
    opts: PoolOptions<Worker>

    Options for the pool.

    +
    promiseResponseMap: Map<`${string}-${string}-${string}-${string}-${string}`, PromiseResponseWrapper<Response>> = ...

    The task execution response promise map:

    • key: The message id of each submitted task.
    • value: An object that contains task's worker node key, execution response promise resolve and reject callbacks, async resource.

    When we receive a message from the worker, we get a map entry with the promise resolve/reject bound to the message id.

    -
    workerChoiceStrategiesContext?: WorkerChoiceStrategiesContext<Worker, Data, Response>

    Worker choice strategies context referencing worker choice algorithms implementation.

    -
    workerNodes: IWorkerNode<Worker, Data>[] = []

    Pool worker nodes.

    -

    Accessors

    workerChoiceStrategiesContext?: WorkerChoiceStrategiesContext<Worker, Data, Response>

    Worker choice strategies context referencing worker choice algorithms implementation.

    +
    workerNodes: IWorkerNode<Worker, Data>[] = []

    Pool worker nodes.

    +

    Accessors

    • get busy(): boolean
    • Whether the pool is busy or not.

      The pool busyness boolean status.

      -

      Returns boolean

    • get full(): boolean
    • Whether the pool is full or not.

      The pool filling boolean status.

      -

      Returns boolean

    • get type(): "fixed" | "dynamic"
    • The pool type.

      If it is 'dynamic', it provides the max property.

      -

      Returns "fixed" | "dynamic"

    • get utilization(): number
    • The approximate pool utilization.

      +

      Returns "fixed" | "dynamic"

    • get utilization(): number
    • The approximate pool utilization.

      Returns number

      The pool utilization.

      -
    • get worker(): "thread" | "cluster"
    • The worker type.

      -

      Returns "thread" | "cluster"

    Methods

    • Hook executed after the worker task execution. +

    • get worker(): "thread" | "cluster"
    • The worker type.

      +

      Returns "thread" | "cluster"

    Methods

    • Method hooked up after a worker node has been newly created. +

    Returns void

    • Hook executed before the worker task execution. +

    Returns void

    • Creates a new, completely set up dynamic worker node.

      +

    Returns void

    • Terminates the worker node given its worker node key.

      +

    Returns void

    • Gets the worker information given its worker node key.

      +

    Returns Promise<void>

    • Registers a listener callback on the worker given its worker node key.

      +

    Returns void

    • Sends the startup message to worker given its worker node key.

      +

    Returns void

    • Sends a message to worker given its worker node key.

      +

    Returns void

    • Sends a message to worker given its worker node key.

      Parameters

      • workerNodeKey: number

        The worker node key.

      • message: MessageValue<Data, unknown>

        The message.

      • Optional transferList: readonly TransferListItem[]

        The optional array of transferable objects.

        -

      Returns void

    • Setup hook to execute code before worker nodes are created in the abstract constructor. +

    Returns void

    \ No newline at end of file +
    \ No newline at end of file diff --git a/docs/classes/FixedClusterPool.html b/docs/classes/FixedClusterPool.html index 2f268c7d..dfc514c0 100644 --- a/docs/classes/FixedClusterPool.html +++ b/docs/classes/FixedClusterPool.html @@ -1,9 +1,9 @@ -FixedClusterPool | poolifier - v4.0.1

    Class FixedClusterPool<Data, Response>

    A cluster pool with a fixed number of workers.

    +FixedClusterPool | poolifier - v4.0.13

    Class FixedClusterPool<Data, Response>

    A cluster pool with a fixed number of workers.

    Author

    Christopher Quadflieg

    Since

    2.0.0

    Type Parameters

    • Data = unknown

      Type of data sent to the worker. This can only be structured-cloneable data.

    • Response = unknown

      Type of execution response. This can only be structured-cloneable data.

      -

    Hierarchy (view full)

    Constructors

    Hierarchy (view full)

    Constructors

    Properties

    Type Parameters

    • Data = unknown
    • Response = unknown

    Parameters

    • numberOfWorkers: number

      Number of workers for this pool.

    • filePath: string

      Path to an implementation of a ClusterWorker file, which can be relative or absolute.

    • opts: ClusterPoolOptions = {}

      Options for this fixed cluster pool.

      -
    • Optional maximumNumberOfWorkers: number

    Returns FixedClusterPool<Data, Response>

    Properties

    emitter?: EventEmitterAsyncResource

    Pool event emitter integrated with async resource. +

  • Optional maximumNumberOfWorkers: number
  • Returns FixedClusterPool<Data, Response>

    Properties

    emitter?: EventEmitterAsyncResource

    Pool event emitter integrated with async resource. The async tracking tooling identifier is poolifier:<PoolType>-<WorkerType>-pool.

    Events that can currently be listened to:

      @@ -69,72 +69,72 @@ The async tracking tooling identifier is poolifier:<PoolType>-<Wo
    • 'taskError': Emitted when an error occurs while executing a task.
    • 'backPressure': Emitted when all worker nodes have back pressure (i.e. their tasks queue is full: queue size >= maximum queue size).
    -
    filePath: string

    Path to the worker file.

    -
    maximumNumberOfWorkers?: number

    Maximum number of workers that this pool manages.

    -
    minimumNumberOfWorkers: number

    Minimum number of workers that this pool manages.

    -
    opts: PoolOptions<Worker>

    Options for the pool.

    -
    promiseResponseMap: Map<string, PromiseResponseWrapper<Response>> = ...

    The task execution response promise map:

    +
    filePath: string

    Path to the worker file.

    +
    maximumNumberOfWorkers?: number

    Maximum number of workers that this pool manages.

    +
    minimumNumberOfWorkers: number

    Minimum number of workers that this pool manages.

    +
    opts: PoolOptions<Worker>

    Options for the pool.

    +
    promiseResponseMap: Map<`${string}-${string}-${string}-${string}-${string}`, PromiseResponseWrapper<Response>> = ...

    The task execution response promise map:

    • key: The message id of each submitted task.
    • value: An object that contains task's worker node key, execution response promise resolve and reject callbacks, async resource.

    When we receive a message from the worker, we get a map entry with the promise resolve/reject bound to the message id.

    -
    workerChoiceStrategiesContext?: WorkerChoiceStrategiesContext<Worker, Data, Response>

    Worker choice strategies context referencing worker choice algorithms implementation.

    -
    workerNodes: IWorkerNode<Worker, Data>[] = []

    Pool worker nodes.

    -

    Accessors

    workerChoiceStrategiesContext?: WorkerChoiceStrategiesContext<Worker, Data, Response>

    Worker choice strategies context referencing worker choice algorithms implementation.

    +
    workerNodes: IWorkerNode<Worker, Data>[] = []

    Pool worker nodes.

    +

    Accessors

    • get busy(): boolean
    • Whether the pool is busy or not.

      The pool busyness boolean status.

      -

      Returns boolean

    • get full(): boolean
    • Whether the pool is full or not.

      The pool filling boolean status.

      -

      Returns boolean

    • get type(): "fixed" | "dynamic"
    • The pool type.

      If it is 'dynamic', it provides the max property.

      -

      Returns "fixed" | "dynamic"

    • get utilization(): number
    • The approximate pool utilization.

      +

      Returns "fixed" | "dynamic"

    • get utilization(): number
    • The approximate pool utilization.

      Returns number

      The pool utilization.

      -
    • get worker(): "thread" | "cluster"
    • The worker type.

      -

      Returns "thread" | "cluster"

    Methods

    • Hook executed after the worker task execution. +

    • get worker(): "thread" | "cluster"
    • The worker type.

      +

      Returns "thread" | "cluster"

    Methods

    • Method hooked up after a worker node has been newly created. +

    Returns void

    • Hook executed before the worker task execution. +

    Returns void

    • Creates a new, completely set up dynamic worker node.

      +

    Returns void

    • Terminates the worker node given its worker node key.

      +

    Returns void

    • Gets the worker information given its worker node key.

      +

    Returns Promise<void>

    • Registers a listener callback on the worker given its worker node key.

      +

    Returns void

    • Sends the startup message to worker given its worker node key.

      +

    Returns void

    • Sends a message to worker given its worker node key.

      +

    Returns void

    • Setup hook to execute code before worker nodes are created in the abstract constructor. +

    Returns void

    \ No newline at end of file +
    \ No newline at end of file diff --git a/docs/classes/FixedPriorityQueue.html b/docs/classes/FixedPriorityQueue.html new file mode 100644 index 00000000..12964b7d --- /dev/null +++ b/docs/classes/FixedPriorityQueue.html @@ -0,0 +1,48 @@ +FixedPriorityQueue | poolifier - v4.0.13

    Class FixedPriorityQueue<T>Internal

    Fixed priority queue.

    +

    Type Parameters

    • T

      Type of fixed priority queue data.

      +

    Hierarchy (view full)

    Constructors

    • Constructs a fixed priority queue.

      +

      Type Parameters

      • T

      Parameters

      • size: number = defaultQueueSize

        Fixed priority queue size.

        +
      • enablePriority: boolean = false

        Whether to enable priority.

        +

      Returns FixedPriorityQueue<T>

      FixedPriorityQueue.

      +

      Default Value

      defaultQueueSize
      +
      +

      Default Value

      false
      +
      +

    Properties

    capacity: number

    The fixed priority queue capacity.

    +
    enablePriority: boolean

    Whether to enable priority.

    +
    size: number

    The fixed priority queue size.

    +
    start: number

    Methods

    • Dequeue data from the fixed priority queue.

      +

      Returns undefined | T

      The dequeued data or undefined if the priority queue is empty.

      +
    • Checks if the fixed priority queue is empty.

      +

      Returns boolean

      true if the fixed priority queue is empty, false otherwise.

      +
    • Enqueue data into the fixed priority queue.

      +

      Parameters

      • data: T

        Data to enqueue.

        +
      • Optional priority: number

        Priority of the data. Lower values have higher priority.

        +

      Returns number

      The new size of the priority queue.

      +

      Throws

      If the fixed priority queue is full.

      +
    • Checks if the fixed priority queue is full.

      +

      Returns boolean

      true if the fixed priority queue is full, false otherwise.

      +
    • Gets data from the fixed priority queue.

      +

      Parameters

      • index: number

        The index of the data to get.

        +

      Returns undefined | T

      The data at the index or undefined if the fixed priority queue is empty or the index is out of bounds.

      +
    \ No newline at end of file diff --git a/docs/classes/FixedThreadPool.html b/docs/classes/FixedThreadPool.html index 9a2741ea..78dbcdde 100644 --- a/docs/classes/FixedThreadPool.html +++ b/docs/classes/FixedThreadPool.html @@ -1,9 +1,9 @@ -FixedThreadPool | poolifier - v4.0.1

    Class FixedThreadPool<Data, Response>

    A thread pool with a fixed number of threads.

    +FixedThreadPool | poolifier - v4.0.13

    Class FixedThreadPool<Data, Response>

    A thread pool with a fixed number of threads.

    Author

    Alessandro Pio Ardizio

    Since

    0.0.1

    Type Parameters

    • Data = unknown

      Type of data sent to the worker. This can only be structured-cloneable data.

    • Response = unknown

      Type of execution response. This can only be structured-cloneable data.

      -

    Hierarchy (view full)

    Constructors

    Hierarchy (view full)

    Constructors

    Properties

    Type Parameters

    • Data = unknown
    • Response = unknown

    Parameters

    • numberOfThreads: number

      Number of threads for this pool.

    • filePath: string

      Path to an implementation of a ThreadWorker file, which can be relative or absolute.

    • opts: ThreadPoolOptions = {}

      Options for this fixed thread pool.

      -
    • Optional maximumNumberOfThreads: number

    Returns FixedThreadPool<Data, Response>

    Properties

    emitter?: EventEmitterAsyncResource

    Pool event emitter integrated with async resource. +

  • Optional maximumNumberOfThreads: number
  • Returns FixedThreadPool<Data, Response>

    Properties

    emitter?: EventEmitterAsyncResource

    Pool event emitter integrated with async resource. The async tracking tooling identifier is poolifier:<PoolType>-<WorkerType>-pool.

    Events that can currently be listened to:

      @@ -69,73 +69,73 @@ The async tracking tooling identifier is poolifier:<PoolType>-<Wo
    • 'taskError': Emitted when an error occurs while executing a task.
    • 'backPressure': Emitted when all worker nodes have back pressure (i.e. their tasks queue is full: queue size >= maximum queue size).
    -
    filePath: string

    Path to the worker file.

    -
    maximumNumberOfWorkers?: number

    Maximum number of workers that this pool manages.

    -
    minimumNumberOfWorkers: number

    Minimum number of workers that this pool manages.

    -
    opts: PoolOptions<Worker>

    Options for the pool.

    -
    promiseResponseMap: Map<string, PromiseResponseWrapper<Response>> = ...

    The task execution response promise map:

    +
    filePath: string

    Path to the worker file.

    +
    maximumNumberOfWorkers?: number

    Maximum number of workers that this pool manages.

    +
    minimumNumberOfWorkers: number

    Minimum number of workers that this pool manages.

    +
    opts: PoolOptions<Worker>

    Options for the pool.

    +
    promiseResponseMap: Map<`${string}-${string}-${string}-${string}-${string}`, PromiseResponseWrapper<Response>> = ...

    The task execution response promise map:

    • key: The message id of each submitted task.
    • value: An object that contains task's worker node key, execution response promise resolve and reject callbacks, async resource.

    When we receive a message from the worker, we get a map entry with the promise resolve/reject bound to the message id.

    -
    workerChoiceStrategiesContext?: WorkerChoiceStrategiesContext<Worker, Data, Response>

    Worker choice strategies context referencing worker choice algorithms implementation.

    -
    workerNodes: IWorkerNode<Worker, Data>[] = []

    Pool worker nodes.

    -

    Accessors

    workerChoiceStrategiesContext?: WorkerChoiceStrategiesContext<Worker, Data, Response>

    Worker choice strategies context referencing worker choice algorithms implementation.

    +
    workerNodes: IWorkerNode<Worker, Data>[] = []

    Pool worker nodes.

    +

    Accessors

    • get busy(): boolean
    • Whether the pool is busy or not.

      The pool busyness boolean status.

      -

      Returns boolean

    • get full(): boolean
    • Whether the pool is full or not.

      The pool filling boolean status.

      -

      Returns boolean

    • get type(): "fixed" | "dynamic"
    • The pool type.

      If it is 'dynamic', it provides the max property.

      -

      Returns "fixed" | "dynamic"

    • get utilization(): number
    • The approximate pool utilization.

      +

      Returns "fixed" | "dynamic"

    • get utilization(): number
    • The approximate pool utilization.

      Returns number

      The pool utilization.

      -
    • get worker(): "thread" | "cluster"
    • The worker type.

      -

      Returns "thread" | "cluster"

    Methods

    • Hook executed after the worker task execution. +

    • get worker(): "thread" | "cluster"
    • The worker type.

      +

      Returns "thread" | "cluster"

    Methods

    • Method hooked up after a worker node has been newly created. +

    Returns void

    • Hook executed before the worker task execution. +

    Returns void

    • Creates a new, completely set up dynamic worker node.

      +

    Returns void

    • Terminates the worker node given its worker node key.

      +

    Returns void

    • Gets the worker information given its worker node key.

      +

    Returns Promise<void>

    • Registers a listener callback on the worker given its worker node key.

      +

    Returns void

    • Sends the startup message to worker given its worker node key.

      +

    Returns void

    • Sends a message to worker given its worker node key.

      +

    Returns void

    • Sends a message to worker given its worker node key.

      Parameters

      • workerNodeKey: number

        The worker node key.

      • message: MessageValue<Data, unknown>

        The message.

      • Optional transferList: readonly TransferListItem[]

        The optional array of transferable objects.

        -

      Returns void

    • Setup hook to execute code before worker nodes are created in the abstract constructor. +

    Returns void

    \ No newline at end of file +
    \ No newline at end of file diff --git a/docs/classes/PriorityQueue.html b/docs/classes/PriorityQueue.html index c179efe0..8079f1f0 100644 --- a/docs/classes/PriorityQueue.html +++ b/docs/classes/PriorityQueue.html @@ -1,41 +1,37 @@ -PriorityQueue | poolifier - v4.0.1

    Class PriorityQueue<T>Internal

    Priority queue.

    +PriorityQueue | poolifier - v4.0.13

    Class PriorityQueue<T>Internal

    Priority queue.

    Type Parameters

    • T

      Type of priority queue data.

      -

    Constructors

    Properties

    k +

    Constructors

    • Constructs a priority queue.

      -

      Type Parameters

      • T

      Parameters

      • k: number = Infinity

        Prioritized bucket size.

        -

      Returns PriorityQueue<T>

      Default Value

      Infinity
      +

    Constructors

    • Constructs a priority queue.

      +

      Type Parameters

      • T

      Parameters

      • bucketSize: number = defaultBucketSize

        Prioritized bucket size.

        +
      • enablePriority: boolean = false

        Whether to enable priority.

        +

      Returns PriorityQueue<T>

      PriorityQueue.

      +

      Default Value

      defaultBucketSize
       
      -

    Properties

    k: number

    Prioritized bucket size.

    -
    maxSize: number

    The maximum size of the priority queue.

    -
    nodeArray: PriorityQueueNode<T>[]
    size: number

    The size of the priority queue.

    -

    Methods

    • Returns an iterator for the priority queue.

      +

      Default Value

      false
      +
      +

    Properties

    bucketSize: number
    maxSize: number

    The priority queue maximum size.

    +

    Accessors

    Methods

    • Dequeue data from the priority queue.

      -

      Parameters

    • Dequeue data from the priority queue.

      +

      Parameters

      • Optional bucket: number

        The prioritized bucket to dequeue from.

      Returns undefined | T

      The dequeued data or undefined if the priority queue is empty.

      -

      Default Value

      0
      -
      -
    • Enqueue data into the priority queue.

      Parameters

      • data: T

        Data to enqueue.

      • Optional priority: number

        Priority of the data. Lower values have higher priority.

      Returns number

      The new size of the priority queue.

      -
    • Increments the size of the priority queue.

      -

      Returns number

      The new size of the priority queue.

      -
    • Peeks at the first data.

      -

      Returns undefined | T

      The first data or undefined if the priority queue is empty.

      -
    • Peeks at the last data.

      -

      Returns undefined | T

      The last data or undefined if the priority queue is empty.

      -
    \ No newline at end of file +
    \ No newline at end of file diff --git a/docs/classes/ThreadWorker.html b/docs/classes/ThreadWorker.html index 21b68220..13c955eb 100644 --- a/docs/classes/ThreadWorker.html +++ b/docs/classes/ThreadWorker.html @@ -1,4 +1,4 @@ -ThreadWorker | poolifier - v4.0.1

    Class ThreadWorker<Data, Response>

    A thread worker used by a poolifier ThreadPool.

    +ThreadWorker | poolifier - v4.0.13

    Class ThreadWorker<Data, Response>

    A thread worker used by a poolifier ThreadPool.

    When this worker is inactive for more than the given maxInactiveTime, it will send a termination request to its main thread.

    If you use a DynamicThreadPool the extra workers that were created will be terminated, @@ -7,7 +7,7 @@ but the minimum number of workers will be guaranteed.

    Since

    0.0.1

    Type Parameters

    • Data = unknown

      Type of data this worker receives from pool's execution. This can only be structured-cloneable data.

    • Response = unknown

      Type of response the worker sends back to the main thread. This can only be structured-cloneable data.

      -

    Hierarchy (view full)

    Constructors

    Hierarchy (view full)

    Constructors

    Properties

    activeInterval? isMain lastTaskTimestamp @@ -35,50 +35,50 @@ but the minimum number of workers will be guaranteed.

    Constructors

    Properties

    activeInterval?: Timeout

    Handler id of the activeInterval worker activity check.

    -
    isMain: undefined | boolean

    Whether this is the main worker or not.

    -
    lastTaskTimestamp: number

    Timestamp of the last task processed by this worker.

    -
    opts: WorkerOptions = DEFAULT_WORKER_OPTIONS

    Options for the worker.

    -
    port?: MessagePort

    Message port used to communicate with the main worker.

    -
    statistics?: WorkerStatistics

    Performance statistics computation requirements.

    -
    taskFunctions: Map<string, TaskFunctionObject<Data, Response>>

    Task function object(s) processed by the worker when the pool's execution function is invoked.

    -

    Accessors

    Methods

    Returns ThreadWorker<Data, Response>

    Properties

    activeInterval?: Timeout

    Handler id of the activeInterval worker activity check.

    +
    isMain: undefined | boolean

    Whether this is the main worker or not.

    +
    lastTaskTimestamp: number

    Timestamp of the last task processed by this worker.

    +
    opts: WorkerOptions = DEFAULT_WORKER_OPTIONS

    Options for the worker.

    +
    port?: MessagePort

    Message port used to communicate with the main worker.

    +
    statistics?: WorkerStatistics

    Performance statistics computation requirements.

    +
    taskFunctions: Map<string, TaskFunctionObject<Data, Response>>

    Task function object(s) processed by the worker when the pool's execution function is invoked.

    +

    Accessors

    Methods

    • Handles an error and convert it to a string so it can be sent back to the main worker.

      Parameters

      • error: string | Error

        The error raised by the worker.

      Returns string

      The error message.

      -

    Returns void

    Returns void

    • Runs the given task function asynchronously.

      +

    Returns void

    • Runs the given task function synchronously.

      +

    Returns void

    • Sends a message to main worker.

      +

    Returns void

    Returns void

    \ No newline at end of file +
    \ No newline at end of file diff --git a/docs/classes/WorkerChoiceStrategiesContext.html b/docs/classes/WorkerChoiceStrategiesContext.html index 606cb15d..92dff5e9 100644 --- a/docs/classes/WorkerChoiceStrategiesContext.html +++ b/docs/classes/WorkerChoiceStrategiesContext.html @@ -1,8 +1,8 @@ -WorkerChoiceStrategiesContext | poolifier - v4.0.1

    Class WorkerChoiceStrategiesContext<Worker, Data, Response>

    The worker choice strategies context.

    +WorkerChoiceStrategiesContext | poolifier - v4.0.13

    Class WorkerChoiceStrategiesContext<Worker, Data, Response>

    The worker choice strategies context.

    Type Parameters

    • Worker extends IWorker

      Type of worker.

    • Data = unknown

      Type of data sent to the worker. This can only be structured-cloneable data.

    • Response = unknown

      Type of execution response. This can only be structured-cloneable data.

      -

    Constructors

    Constructors

    Properties

    Type Parameters

    • Worker extends IWorker
    • Data = unknown
    • Response = unknown

    Parameters

    • pool: IPool<Worker, Data, Response>

      The pool instance.

    • workerChoiceStrategies: ("ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN")[] = ...

      The worker choice strategies.

    • Optional opts: WorkerChoiceStrategyOptions

      The worker choice strategy options.

      -

    Returns WorkerChoiceStrategiesContext<Worker, Data, Response>

    Default Value

    [WorkerChoiceStrategies.ROUND_ROBIN]
    +

    Returns WorkerChoiceStrategiesContext<Worker, Data, Response>

    Default Value

    [WorkerChoiceStrategies.ROUND_ROBIN]
     
    -

    Properties

    defaultWorkerChoiceStrategy: "ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN"

    The default worker choice strategy in the context.

    -

    The pool instance.

    -
    retries: number

    The maximum number of worker choice strategies execution retries.

    -
    retriesCount: number

    The number of worker choice strategies execution retries.

    -
    workerChoiceStrategies: Map<"ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN", IWorkerChoiceStrategy>

    The worker choice strategies registered in the context.

    -
    workerChoiceStrategiesPolicy: StrategyPolicy

    The active worker choice strategies in the context policy.

    -
    workerChoiceStrategiesTaskStatisticsRequirements: TaskStatisticsRequirements

    The active worker choice strategies in the context task statistics requirements.

    -

    Methods

    Properties

    defaultWorkerChoiceStrategy: "ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN"

    The default worker choice strategy in the context.

    +

    The pool instance.

    +
    retries: number

    The maximum number of worker choice strategies execution retries.

    +
    retriesCount: number

    The number of worker choice strategies execution retries.

    +
    workerChoiceStrategies: Map<"ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN", IWorkerChoiceStrategy>

    The worker choice strategies registered in the context.

    +
    workerChoiceStrategiesPolicy: StrategyPolicy

    The active worker choice strategies in the context policy.

    +
    workerChoiceStrategiesTaskStatisticsRequirements: TaskStatisticsRequirements

    The active worker choice strategies in the context task statistics requirements.

    +

    Methods

    • Adds a worker choice strategy to the context.

      Parameters

      • workerChoiceStrategy: "ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN"

        The worker choice strategy to add.

      • pool: IPool<Worker, Data, Response>
      • Optional opts: WorkerChoiceStrategyOptions

        The worker choice strategy options.

      Returns Map<"ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN", IWorkerChoiceStrategy>

      The worker choice strategies.

      -
    • Executes the given worker choice strategy in the context algorithm.

      Parameters

      • workerChoiceStrategy: "ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN" = ...

        The worker choice strategy algorithm to execute.

      Returns number

      The key of the worker node.

      -

      Default Value

      this.defaultWorkerChoiceStrategy
      +

      Default Value

      this.defaultWorkerChoiceStrategy
       

      Throws

      https://nodejs.org/api/errors.html#class-error If after computed retries the worker node key is null or undefined.

      -
    • Removes a worker choice strategy from the context.

      Parameters

      • workerChoiceStrategy: "ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN"

        The worker choice strategy to remove.

      Returns boolean

      true if the worker choice strategy is removed, false otherwise.

      -
    • Sets the default worker choice strategy to use in the context.

      Parameters

      • workerChoiceStrategy: "ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN"

        The default worker choice strategy to set.

      • Optional opts: WorkerChoiceStrategyOptions

        The worker choice strategy options.

        -

      Returns void

    • Sets the active worker choice strategies in the context options.

      +

    Returns void

    • Synchronizes the active worker choice strategies in the context with the given worker choice strategies.

      +

    Returns void

    • Synchronizes the active worker choice strategies in the context with the given worker choice strategies.

      Parameters

      • workerChoiceStrategies: Set<"ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN">

        The worker choice strategies to synchronize.

      • Optional opts: WorkerChoiceStrategyOptions

        The worker choice strategy options.

        -

      Returns void

    • Updates the worker node key in the active worker choice strategies in the context internals.

      +

    Returns void

    \ No newline at end of file +
    \ No newline at end of file diff --git a/docs/functions/availableParallelism.html b/docs/functions/availableParallelism.html index f2cd07b6..80d6fa19 100644 --- a/docs/functions/availableParallelism.html +++ b/docs/functions/availableParallelism.html @@ -1,4 +1,4 @@ -availableParallelism | poolifier - v4.0.1

    Function availableParallelism

    • Returns safe host OS optimized estimate of the default amount of parallelism a pool should use. +availableParallelism | poolifier - v4.0.13

      Function availableParallelism

      • Returns safe host OS optimized estimate of the default amount of parallelism a pool should use. Always returns a value greater than zero.

        Returns number

        The host OS optimized maximum pool size.

        -
      \ No newline at end of file +
    \ No newline at end of file diff --git a/docs/hierarchy.html b/docs/hierarchy.html index b245b29f..4df2ae9f 100644 --- a/docs/hierarchy.html +++ b/docs/hierarchy.html @@ -1 +1 @@ -poolifier - v4.0.1
    \ No newline at end of file +poolifier - v4.0.13
    \ No newline at end of file diff --git a/docs/index.html b/docs/index.html index 864d9407..5cce207e 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,15 +1,17 @@ -poolifier - v4.0.1

    poolifier - v4.0.1

    Index

    Classes

    AbstractPool +poolifier - v4.0.13
    \ No newline at end of file +
    \ No newline at end of file diff --git a/docs/interfaces/EventLoopUtilizationMeasurementStatistics.html b/docs/interfaces/EventLoopUtilizationMeasurementStatistics.html index b07eb67e..1c8740b4 100644 --- a/docs/interfaces/EventLoopUtilizationMeasurementStatistics.html +++ b/docs/interfaces/EventLoopUtilizationMeasurementStatistics.html @@ -1,5 +1,5 @@ -EventLoopUtilizationMeasurementStatistics | poolifier - v4.0.1

    Interface EventLoopUtilizationMeasurementStatisticsInternal

    Event loop utilization measurement statistics.

    -
    interface EventLoopUtilizationMeasurementStatistics {
        active: MeasurementStatistics;
        idle: MeasurementStatistics;
        utilization?: number;
    }

    Properties

    active +EventLoopUtilizationMeasurementStatistics | poolifier - v4.0.13

    Interface EventLoopUtilizationMeasurementStatisticsInternal

    Event loop utilization measurement statistics.

    +
    interface EventLoopUtilizationMeasurementStatistics {
        active: MeasurementStatistics;
        idle: MeasurementStatistics;
        utilization?: number;
    }

    Properties

    utilization?: number
    \ No newline at end of file +

    Properties

    utilization?: number
    \ No newline at end of file diff --git a/docs/interfaces/FixedPriorityQueueNode.html b/docs/interfaces/FixedPriorityQueueNode.html new file mode 100644 index 00000000..f12e5707 --- /dev/null +++ b/docs/interfaces/FixedPriorityQueueNode.html @@ -0,0 +1,5 @@ +FixedPriorityQueueNode | poolifier - v4.0.13

    Interface FixedPriorityQueueNode<T>Internal

    Fixed priority queue node.

    +
    interface FixedPriorityQueueNode<T> {
        data: T;
        priority: number;
    }

    Type Parameters

    • T

      Type of priority queue node data.

      +

    Properties

    Properties

    data: T
    priority: number
    \ No newline at end of file diff --git a/docs/interfaces/IPool.html b/docs/interfaces/IPool.html index 6a76063e..86b5dfb4 100644 --- a/docs/interfaces/IPool.html +++ b/docs/interfaces/IPool.html @@ -1,8 +1,8 @@ -IPool | poolifier - v4.0.1

    Interface IPool<Worker, Data, Response>

    Contract definition for a poolifier pool.

    +IPool | poolifier - v4.0.13

    Interface IPool<Worker, Data, Response>

    Contract definition for a poolifier pool.

    interface IPool<Worker, Data, Response> {
        addTaskFunction: ((name, fn) => Promise<boolean>);
        destroy: (() => Promise<void>);
        emitter?: EventEmitterAsyncResource;
        enableTasksQueue: ((enable, tasksQueueOptions?) => void);
        execute: ((data?, name?, transferList?) => Promise<Response>);
        hasTaskFunction: ((name) => boolean);
        info: PoolInfo;
        listTaskFunctionsProperties: (() => TaskFunctionProperties[]);
        removeTaskFunction: ((name) => Promise<boolean>);
        setDefaultTaskFunction: ((name) => Promise<boolean>);
        setTasksQueueOptions: ((tasksQueueOptions) => void);
        setWorkerChoiceStrategy: ((workerChoiceStrategy, workerChoiceStrategyOptions?) => void);
        setWorkerChoiceStrategyOptions: ((workerChoiceStrategyOptions) => boolean);
        start: (() => void);
        workerNodes: IWorkerNode<Worker, Data>[];
    }

    Type Parameters

    • Worker extends IWorker

      Type of worker which manages this pool.

    • Data = unknown

      Type of data sent to the worker. This can only be structured-cloneable data.

    • Response = unknown

      Type of execution response. This can only be structured-cloneable data.

      -

    Implemented by

    Properties

    Implemented by

    Properties

    Properties

    addTaskFunction: ((name, fn) => Promise<boolean>)

    Adds a task function to this pool. If a task function with the same name already exists, it will be overwritten.

    Type declaration

    Returns

    true if the task function was added, false otherwise.

    Throws

    https://nodejs.org/api/errors.html#class-typeerror If the name parameter is not a string or an empty string.

    -

    Throws

    https://nodejs.org/api/errors.html#class-typeerror If the fn parameter is not a function.

    -
    destroy: (() => Promise<void>)

    Terminates all workers in this pool.

    -

    Type declaration

      • (): Promise<void>
      • Returns Promise<void>

    emitter?: EventEmitterAsyncResource

    Pool event emitter integrated with async resource. +

    Throws

    https://nodejs.org/api/errors.html#class-typeerror If the fn parameter is not a function or task function object.

    +
    destroy: (() => Promise<void>)

    Terminates all workers in this pool.

    +

    Type declaration

      • (): Promise<void>
      • Returns Promise<void>

    emitter?: EventEmitterAsyncResource

    Pool event emitter integrated with async resource. The async tracking tooling identifier is poolifier:<PoolType>-<WorkerType>-pool.

    Events that can currently be listened to:

      @@ -38,34 +38,34 @@ The async tracking tooling identifier is poolifier:<PoolType>-<Wo
    • 'taskError': Emitted when an error occurs while executing a task.
    • 'backPressure': Emitted when all worker nodes have back pressure (i.e. their tasks queue is full: queue size >= maximum queue size).
    -
    enableTasksQueue: ((enable, tasksQueueOptions?) => void)

    Enables/disables the worker node tasks queue in this pool.

    +
    enableTasksQueue: ((enable, tasksQueueOptions?) => void)

    Enables/disables the worker node tasks queue in this pool.

    Type declaration

      • (enable, tasksQueueOptions?): void
      • Parameters

        • enable: boolean

          Whether to enable or disable the worker node tasks queue.

        • Optional tasksQueueOptions: TasksQueueOptions

          The worker node tasks queue options.

          -

        Returns void

    execute: ((data?, name?, transferList?) => Promise<Response>)

    Executes the specified function in the worker constructor with the task data input parameter.

    +

    Returns void

    execute: ((data?, name?, transferList?) => Promise<Response>)

    Executes the specified function in the worker constructor with the task data input parameter.

    Type declaration

      • (data?, name?, transferList?): Promise<Response>
      • Parameters

        • Optional data: Data

          The optional task input data for the specified task function. This can only be structured-cloneable data.

        • Optional name: string

          The optional name of the task function to execute. If not specified, the default task function will be executed.

        • Optional transferList: readonly TransferListItem[]

          An optional array of transferable objects to transfer ownership of. Ownership of the transferred objects is given to the chosen pool's worker_threads worker and they should not be used in the main thread afterwards.

        Returns Promise<Response>

    Returns

    Promise that will be fulfilled when the task is completed.

    -
    hasTaskFunction: ((name) => boolean)

    Whether the specified task function exists in this pool.

    +
    hasTaskFunction: ((name) => boolean)

    Whether the specified task function exists in this pool.

    Type declaration

      • (name): boolean
      • Parameters

        • name: string

          The name of the task function.

        Returns boolean

    Returns

    true if the task function exists, false otherwise.

    -
    info: PoolInfo

    Pool information.

    -
    listTaskFunctionsProperties: (() => TaskFunctionProperties[])

    Lists the properties of task functions available in this pool.

    +
    info: PoolInfo

    Pool information.

    +
    listTaskFunctionsProperties: (() => TaskFunctionProperties[])

    Lists the properties of task functions available in this pool.

    Type declaration

    Returns

    The properties of task functions available in this pool.

    -
    removeTaskFunction: ((name) => Promise<boolean>)

    Removes a task function from this pool.

    +
    removeTaskFunction: ((name) => Promise<boolean>)

    Removes a task function from this pool.

    Type declaration

      • (name): Promise<boolean>
      • Parameters

        • name: string

          The name of the task function.

        Returns Promise<boolean>

    Returns

    true if the task function was removed, false otherwise.

    -
    setDefaultTaskFunction: ((name) => Promise<boolean>)

    Sets the default task function in this pool.

    +
    setDefaultTaskFunction: ((name) => Promise<boolean>)

    Sets the default task function in this pool.

    Type declaration

      • (name): Promise<boolean>
      • Parameters

        • name: string

          The name of the task function.

        Returns Promise<boolean>

    Returns

    true if the default task function was set, false otherwise.

    -
    setTasksQueueOptions: ((tasksQueueOptions) => void)

    Sets the worker node tasks queue options in this pool.

    +
    setTasksQueueOptions: ((tasksQueueOptions) => void)

    Sets the worker node tasks queue options in this pool.

    Type declaration

      • (tasksQueueOptions): void
      • Parameters

        Returns void

    setWorkerChoiceStrategy: ((workerChoiceStrategy, workerChoiceStrategyOptions?) => void)

    Sets the default worker choice strategy in this pool.

    +

    Returns void

    setWorkerChoiceStrategy: ((workerChoiceStrategy, workerChoiceStrategyOptions?) => void)

    Sets the default worker choice strategy in this pool.

    Type declaration

      • (workerChoiceStrategy, workerChoiceStrategyOptions?): void
      • Parameters

        • workerChoiceStrategy: "ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN"

          The default worker choice strategy.

        • Optional workerChoiceStrategyOptions: WorkerChoiceStrategyOptions

          The worker choice strategy options.

          -

        Returns void

    setWorkerChoiceStrategyOptions: ((workerChoiceStrategyOptions) => boolean)

    Sets the worker choice strategy options in this pool.

    +

    Returns void

    setWorkerChoiceStrategyOptions: ((workerChoiceStrategyOptions) => boolean)

    Sets the worker choice strategy options in this pool.

    Type declaration

      • (workerChoiceStrategyOptions): boolean
      • Parameters

        Returns boolean

    Returns

    true if the worker choice strategy options were set, false otherwise.

    -
    start: (() => void)

    Starts the minimum number of workers in this pool.

    -

    Type declaration

      • (): void
      • Returns void

    workerNodes: IWorkerNode<Worker, Data>[]

    Pool worker nodes.

    -
    \ No newline at end of file +
    start: (() => void)

    Starts the minimum number of workers in this pool.

    +

    Type declaration

      • (): void
      • Returns void

    workerNodes: IWorkerNode<Worker, Data>[]

    Pool worker nodes.

    +
    \ No newline at end of file diff --git a/docs/interfaces/IWorker.html b/docs/interfaces/IWorker.html index 3fa2259b..da4bbbc3 100644 --- a/docs/interfaces/IWorker.html +++ b/docs/interfaces/IWorker.html @@ -1,5 +1,5 @@ -IWorker | poolifier - v4.0.1

    Interface IWorker

    Worker interface.

    -
    interface IWorker {
        disconnect?: (() => void);
        id?: number;
        kill?: ((signal?) => void);
        on: ((event, handler) => this);
        once: ((event, handler) => this);
        terminate?: (() => Promise<number>);
        threadId?: number;
        unref?: (() => void);
        [captureRejectionSymbol]?<K>(error, event, ...args): void;
        addListener<K>(eventName, listener): this;
        emit<K>(eventName, ...args): boolean;
        eventNames(): (string | symbol)[];
        getMaxListeners(): number;
        listenerCount<K>(eventName, listener?): number;
        listeners<K>(eventName): Function[];
        off<K>(eventName, listener): this;
        prependListener<K>(eventName, listener): this;
        prependOnceListener<K>(eventName, listener): this;
        rawListeners<K>(eventName): Function[];
        removeAllListeners(eventName?): this;
        removeListener<K>(eventName, listener): this;
        setMaxListeners(n): this;
    }

    Hierarchy

    • EventEmitter
      • IWorker

    Properties

    disconnect? +IWorker | poolifier - v4.0.13

    Interface IWorker

    Worker interface.

    +
    interface IWorker {
        disconnect?: (() => void);
        id?: number;
        kill?: ((signal?) => void);
        on: ((event, handler) => this);
        once: ((event, handler) => this);
        terminate?: (() => Promise<number>);
        threadId?: number;
        unref?: (() => void);
        [captureRejectionSymbol]?<K>(error, event, ...args): void;
        addListener<K>(eventName, listener): this;
        emit<K>(eventName, ...args): boolean;
        eventNames(): (string | symbol)[];
        getMaxListeners(): number;
        listenerCount<K>(eventName, listener?): number;
        listeners<K>(eventName): Function[];
        off<K>(eventName, listener): this;
        prependListener<K>(eventName, listener): this;
        prependOnceListener<K>(eventName, listener): this;
        rawListeners<K>(eventName): Function[];
        removeAllListeners(eventName?): this;
        removeListener<K>(eventName, listener): this;
        setMaxListeners(n): this;
    }

    Hierarchy

    • EventEmitter
      • IWorker

    Properties

    Properties

    disconnect?: (() => void)

    Cluster worker disconnect.

    -

    Type declaration

      • (): void
      • Returns void

    id?: number

    Cluster worker id.

    -
    kill?: ((signal?) => void)

    Cluster worker kill.

    -

    Type declaration

      • (signal?): void
      • Parameters

        • Optional signal: string

        Returns void

    on: ((event, handler) => this)

    Registers an event handler.

    +

    Type declaration

      • (): void
      • Returns void

    id?: number

    Cluster worker id.

    +
    kill?: ((signal?) => void)

    Cluster worker kill.

    +

    Type declaration

      • (signal?): void
      • Parameters

        • Optional signal: string

        Returns void

    on: ((event, handler) => this)

    Registers an event handler.

    Type declaration

      • (event, handler): this
      • Parameters

        Returns this

    once: ((event, handler) => this)

    Registers once an event handler.

    +

    Returns this

    once: ((event, handler) => this)

    Registers once an event handler.

    Type declaration

      • (event, handler): this
      • Parameters

        Returns this

    terminate?: (() => Promise<number>)

    Stop all JavaScript execution in the worker thread as soon as possible. +

    Returns this

    terminate?: (() => Promise<number>)

    Stop all JavaScript execution in the worker thread as soon as possible. Returns a Promise for the exit code that is fulfilled when the 'exit' event is emitted.

    -

    Type declaration

      • (): Promise<number>
      • Returns Promise<number>

    threadId?: number

    Worker thread worker id.

    -
    unref?: (() => void)

    Calling unref() on a worker allows the thread to exit if this is the only +

    Type declaration

      • (): Promise<number>
      • Returns Promise<number>

    threadId?: number

    Worker thread worker id.

    +
    unref?: (() => void)

    Calling unref() on a worker allows the thread to exit if this is the only active handle in the event system. If the worker is already unref()ed callingunref() again has no effect.

    Type declaration

      • (): void
      • Returns void

    Since

    v10.5.0

    -

    Methods

    • Type Parameters

      • K

      Parameters

      • error: Error
      • event: string | symbol
      • Rest ...args: AnyRest

      Returns void

    Methods

    • Type Parameters

      • K

      Parameters

      • error: Error
      • event: string | symbol
      • Rest ...args: AnyRest

      Returns void

    • Alias for emitter.on(eventName, listener).

      Type Parameters

      • K

      Parameters

      • eventName: string | symbol
      • listener: ((...args) => void)
          • (...args): void
          • Parameters

            • Rest ...args: any[]

            Returns void

      Returns this

      Since

      v0.1.26

      -
    • Synchronously calls each of the listeners registered for the event namedeventName, in the order they were registered, passing the supplied arguments +

    • Synchronously calls each of the listeners registered for the event named eventName, in the order they were registered, passing the supplied arguments to each.

      Returns true if the event had listeners, false otherwise.

      -
      import { EventEmitter } from 'node:events';
      const myEmitter = new EventEmitter();

      // First listener
      myEmitter.on('event', function firstListener() {
      console.log('Helloooo! first listener');
      });
      // Second listener
      myEmitter.on('event', function secondListener(arg1, arg2) {
      console.log(`event with parameters ${arg1}, ${arg2} in second listener`);
      });
      // Third listener
      myEmitter.on('event', function thirdListener(...args) {
      const parameters = args.join(', ');
      console.log(`event with parameters ${parameters} in third listener`);
      });

      console.log(myEmitter.listeners('event'));

      myEmitter.emit('event', 1, 2, 3, 4, 5);

      // Prints:
      // [
      // [Function: firstListener],
      // [Function: secondListener],
      // [Function: thirdListener]
      // ]
      // Helloooo! first listener
      // event with parameters 1, 2 in second listener
      // event with parameters 1, 2, 3, 4, 5 in third listener +
      import { EventEmitter } from 'node:events';
      const myEmitter = new EventEmitter();

      // First listener
      myEmitter.on('event', function firstListener() {
      console.log('Helloooo! first listener');
      });
      // Second listener
      myEmitter.on('event', function secondListener(arg1, arg2) {
      console.log(`event with parameters ${arg1}, ${arg2} in second listener`);
      });
      // Third listener
      myEmitter.on('event', function thirdListener(...args) {
      const parameters = args.join(', ');
      console.log(`event with parameters ${parameters} in third listener`);
      });

      console.log(myEmitter.listeners('event'));

      myEmitter.emit('event', 1, 2, 3, 4, 5);

      // Prints:
      // [
      // [Function: firstListener],
      // [Function: secondListener],
      // [Function: thirdListener]
      // ]
      // Helloooo! first listener
      // event with parameters 1, 2 in second listener
      // event with parameters 1, 2, 3, 4, 5 in third listener

      Type Parameters

      • K

      Parameters

      • eventName: string | symbol
      • Rest ...args: AnyRest

      Returns boolean

      Since

      v0.1.26

      -
    • Returns an array listing the events for which the emitter has registered +

    • Returns an array listing the events for which the emitter has registered listeners. The values in the array are strings or Symbols.

      -
      import { EventEmitter } from 'node:events';

      const myEE = new EventEmitter();
      myEE.on('foo', () => {});
      myEE.on('bar', () => {});

      const sym = Symbol('symbol');
      myEE.on(sym, () => {});

      console.log(myEE.eventNames());
      // Prints: [ 'foo', 'bar', Symbol(symbol) ] +
      import { EventEmitter } from 'node:events';

      const myEE = new EventEmitter();
      myEE.on('foo', () => {});
      myEE.on('bar', () => {});

      const sym = Symbol('symbol');
      myEE.on(sym, () => {});

      console.log(myEE.eventNames());
      // Prints: [ 'foo', 'bar', Symbol(symbol) ]

      Returns (string | symbol)[]

      Since

      v6.0.0

      -
    • Returns the current max listener value for the EventEmitter which is either +

    • Returns the current max listener value for the EventEmitter which is either set by emitter.setMaxListeners(n) or defaults to defaultMaxListeners.

      Returns number

      Since

      v1.0.0

      -
    • Returns the number of listeners listening for the event named eventName. +

    • Returns the number of listeners listening for the event named eventName. If listener is provided, it will return how many times the listener is found in the list of the listeners of the event.

      Type Parameters

      • K

      Parameters

      • eventName: string | symbol

        The name of the event being listened for

      • Optional listener: Function

        The event handler function

      Returns number

      Since

      v3.2.0

      -
    • Returns a copy of the array of listeners for the event named eventName.

      -
      server.on('connection', (stream) => {
      console.log('someone connected!');
      });
      console.log(util.inspect(server.listeners('connection')));
      // Prints: [ [Function] ] +
    • Returns a copy of the array of listeners for the event named eventName.

      +
      server.on('connection', (stream) => {
      console.log('someone connected!');
      });
      console.log(util.inspect(server.listeners('connection')));
      // Prints: [ [Function] ]

      Type Parameters

      • K

      Parameters

      • eventName: string | symbol

      Returns Function[]

      Since

      v0.1.26

      -
    • Alias for emitter.removeListener().

      +
    • Alias for emitter.removeListener().

      Type Parameters

      • K

      Parameters

      • eventName: string | symbol
      • listener: ((...args) => void)
          • (...args): void
          • Parameters

            • Rest ...args: any[]

            Returns void

      Returns this

      Since

      v10.0.0

      -
    • Adds the listener function to the beginning of the listeners array for the +

    • Adds the listener function to the beginning of the listeners array for the event named eventName. No checks are made to see if the listener has -already been added. Multiple calls passing the same combination of eventNameand listener will result in the listener being added, and called, multiple -times.

      -
      server.prependListener('connection', (stream) => {
      console.log('someone connected!');
      }); +already been added. Multiple calls passing the same combination of eventName +and listener will result in the listener being added, and called, multiple times.

      +
      server.prependListener('connection', (stream) => {
      console.log('someone connected!');
      });

      Returns a reference to the EventEmitter, so that calls can be chained.

      Type Parameters

      • K

      Parameters

      • eventName: string | symbol

        The name of the event.

      • listener: ((...args) => void)

        The callback function

          • (...args): void
          • Parameters

            • Rest ...args: any[]

            Returns void

      Returns this

      Since

      v6.0.0

      -
    • Adds a one-timelistener function for the event named eventName to the beginning of the listeners array. The next time eventName is triggered, this +

    • Adds a one-timelistener function for the event named eventName to the beginning of the listeners array. The next time eventName is triggered, this listener is removed, and then invoked.

      -
      server.prependOnceListener('connection', (stream) => {
      console.log('Ah, we have our first user!');
      }); +
      server.prependOnceListener('connection', (stream) => {
      console.log('Ah, we have our first user!');
      });

      Returns a reference to the EventEmitter, so that calls can be chained.

      Type Parameters

      • K

      Parameters

      • eventName: string | symbol

        The name of the event.

      • listener: ((...args) => void)

        The callback function

          • (...args): void
          • Parameters

            • Rest ...args: any[]

            Returns void

      Returns this

      Since

      v6.0.0

      -
    • Returns a copy of the array of listeners for the event named eventName, +

    • Returns a copy of the array of listeners for the event named eventName, including any wrappers (such as those created by .once()).

      -
      import { EventEmitter } from 'node:events';
      const emitter = new EventEmitter();
      emitter.once('log', () => console.log('log once'));

      // Returns a new Array with a function `onceWrapper` which has a property
      // `listener` which contains the original listener bound above
      const listeners = emitter.rawListeners('log');
      const logFnWrapper = listeners[0];

      // Logs "log once" to the console and does not unbind the `once` event
      logFnWrapper.listener();

      // Logs "log once" to the console and removes the listener
      logFnWrapper();

      emitter.on('log', () => console.log('log persistently'));
      // Will return a new Array with a single function bound by `.on()` above
      const newListeners = emitter.rawListeners('log');

      // Logs "log persistently" twice
      newListeners[0]();
      emitter.emit('log'); +
      import { EventEmitter } from 'node:events';
      const emitter = new EventEmitter();
      emitter.once('log', () => console.log('log once'));

      // Returns a new Array with a function `onceWrapper` which has a property
      // `listener` which contains the original listener bound above
      const listeners = emitter.rawListeners('log');
      const logFnWrapper = listeners[0];

      // Logs "log once" to the console and does not unbind the `once` event
      logFnWrapper.listener();

      // Logs "log once" to the console and removes the listener
      logFnWrapper();

      emitter.on('log', () => console.log('log persistently'));
      // Will return a new Array with a single function bound by `.on()` above
      const newListeners = emitter.rawListeners('log');

      // Logs "log persistently" twice
      newListeners[0]();
      emitter.emit('log');

      Type Parameters

      • K

      Parameters

      • eventName: string | symbol

      Returns Function[]

      Since

      v9.4.0

      -
    • Removes all listeners, or those of the specified eventName.

      +
    • Removes all listeners, or those of the specified eventName.

      It is bad practice to remove listeners added elsewhere in the code, particularly when the EventEmitter instance was created by some other component or module (e.g. sockets or file streams).

      Returns a reference to the EventEmitter, so that calls can be chained.

      Parameters

      • Optional eventName: string | symbol

      Returns this

      Since

      v0.1.26

      -
    • Removes the specified listener from the listener array for the event namedeventName.

      -
      const callback = (stream) => {
      console.log('someone connected!');
      };
      server.on('connection', callback);
      // ...
      server.removeListener('connection', callback); +
    • Removes the specified listener from the listener array for the event named eventName.

      +
      const callback = (stream) => {
      console.log('someone connected!');
      };
      server.on('connection', callback);
      // ...
      server.removeListener('connection', callback);

      removeListener() will remove, at most, one instance of a listener from the listener array. If any single listener has been added multiple times to the listener array for the specified eventName, then removeListener() must be called multiple times to remove each instance.

      Once an event is emitted, all listeners attached to it at the -time of emitting are called in order. This implies that anyremoveListener() or removeAllListeners() calls after emitting and before the last listener finishes execution +time of emitting are called in order. This implies that any removeListener() or removeAllListeners() calls after emitting and before the last listener finishes execution will not remove them fromemit() in progress. Subsequent events behave as expected.

      -
      import { EventEmitter } from 'node:events';
      class MyEmitter extends EventEmitter {}
      const myEmitter = new MyEmitter();

      const callbackA = () => {
      console.log('A');
      myEmitter.removeListener('event', callbackB);
      };

      const callbackB = () => {
      console.log('B');
      };

      myEmitter.on('event', callbackA);

      myEmitter.on('event', callbackB);

      // callbackA removes listener callbackB but it will still be called.
      // Internal listener array at time of emit [callbackA, callbackB]
      myEmitter.emit('event');
      // Prints:
      // A
      // B

      // callbackB is now removed.
      // Internal listener array [callbackA]
      myEmitter.emit('event');
      // Prints:
      // A +
      import { EventEmitter } from 'node:events';
      class MyEmitter extends EventEmitter {}
      const myEmitter = new MyEmitter();

      const callbackA = () => {
      console.log('A');
      myEmitter.removeListener('event', callbackB);
      };

      const callbackB = () => {
      console.log('B');
      };

      myEmitter.on('event', callbackA);

      myEmitter.on('event', callbackB);

      // callbackA removes listener callbackB but it will still be called.
      // Internal listener array at time of emit [callbackA, callbackB]
      myEmitter.emit('event');
      // Prints:
      // A
      // B

      // callbackB is now removed.
      // Internal listener array [callbackA]
      myEmitter.emit('event');
      // Prints:
      // A

      Because listeners are managed using an internal array, calling this will change the position indices of any listener registered after the listener @@ -112,15 +112,15 @@ but it means that any copies of the listener array as returned by the emitter.listeners() method will need to be recreated.

      When a single function has been added as a handler multiple times for a single event (as in the example below), removeListener() will remove the most -recently added instance. In the example the once('ping')listener is removed:

      -
      import { EventEmitter } from 'node:events';
      const ee = new EventEmitter();

      function pong() {
      console.log('pong');
      }

      ee.on('ping', pong);
      ee.once('ping', pong);
      ee.removeListener('ping', pong);

      ee.emit('ping');
      ee.emit('ping'); +recently added instance. In the example the once('ping') listener is removed:

      +
      import { EventEmitter } from 'node:events';
      const ee = new EventEmitter();

      function pong() {
      console.log('pong');
      }

      ee.on('ping', pong);
      ee.once('ping', pong);
      ee.removeListener('ping', pong);

      ee.emit('ping');
      ee.emit('ping');

      Returns a reference to the EventEmitter, so that calls can be chained.

      Type Parameters

      • K

      Parameters

      • eventName: string | symbol
      • listener: ((...args) => void)
          • (...args): void
          • Parameters

            • Rest ...args: any[]

            Returns void

      Returns this

      Since

      v0.1.26

      -
    • By default EventEmitters will print a warning if more than 10 listeners are +

    • By default EventEmitters will print a warning if more than 10 listeners are added for a particular event. This is a useful default that helps finding memory leaks. The emitter.setMaxListeners() method allows the limit to be -modified for this specific EventEmitter instance. The value can be set toInfinity (or 0) to indicate an unlimited number of listeners.

      +modified for this specific EventEmitter instance. The value can be set to Infinity (or 0) to indicate an unlimited number of listeners.

      Returns a reference to the EventEmitter, so that calls can be chained.

      Parameters

      • n: number

      Returns this

      Since

      v0.3.5

      -
    \ No newline at end of file +
    \ No newline at end of file diff --git a/docs/interfaces/IWorkerChoiceStrategy.html b/docs/interfaces/IWorkerChoiceStrategy.html index 4921a0ca..cf851a23 100644 --- a/docs/interfaces/IWorkerChoiceStrategy.html +++ b/docs/interfaces/IWorkerChoiceStrategy.html @@ -1,5 +1,5 @@ -IWorkerChoiceStrategy | poolifier - v4.0.1

    Interface IWorkerChoiceStrategyInternal

    Worker choice strategy interface.

    -
    interface IWorkerChoiceStrategy {
        choose: (() => undefined | number);
        remove: ((workerNodeKey) => boolean);
        reset: (() => boolean);
        setOptions: ((opts) => void);
        strategyPolicy: StrategyPolicy;
        taskStatisticsRequirements: TaskStatisticsRequirements;
        update: ((workerNodeKey) => boolean);
    }

    Properties

    choose +IWorkerChoiceStrategy | poolifier - v4.0.13

    Interface IWorkerChoiceStrategyInternal

    Worker choice strategy interface.

    +
    interface IWorkerChoiceStrategy {
        choose: (() => undefined | number);
        remove: ((workerNodeKey) => boolean);
        reset: (() => boolean);
        setOptions: ((opts) => void);
        strategyPolicy: StrategyPolicy;
        taskStatisticsRequirements: TaskStatisticsRequirements;
        update: ((workerNodeKey) => boolean);
    }

    Properties

    choose remove reset setOptions @@ -10,16 +10,16 @@ If no worker nodes are not eligible, undefined is returned. If undefined is returned, the caller retry.

    Type declaration

      • (): undefined | number
      • Returns undefined | number

    Returns

    The worker node key or undefined.

    -
    remove: ((workerNodeKey) => boolean)

    Removes the worker node key from strategy internals.

    +
    remove: ((workerNodeKey) => boolean)

    Removes the worker node key from strategy internals.

    Type declaration

      • (workerNodeKey): boolean
      • Parameters

        • workerNodeKey: number

          The worker node key.

        Returns boolean

    Returns

    true if the worker node key is removed, false otherwise.

    -
    reset: (() => boolean)

    Resets strategy internals.

    +
    reset: (() => boolean)

    Resets strategy internals.

    Type declaration

      • (): boolean
      • Returns boolean

    Returns

    true if the reset is successful, false otherwise.

    -
    setOptions: ((opts) => void)

    Sets the worker choice strategy options.

    +
    setOptions: ((opts) => void)

    Sets the worker choice strategy options.

    Type declaration

    strategyPolicy: StrategyPolicy

    Strategy policy.

    -
    taskStatisticsRequirements: TaskStatisticsRequirements

    Tasks statistics requirements.

    -
    update: ((workerNodeKey) => boolean)

    Updates the worker node key strategy internals. +

    Returns void

    strategyPolicy: StrategyPolicy

    Strategy policy.

    +
    taskStatisticsRequirements: TaskStatisticsRequirements

    Tasks statistics requirements.

    +
    update: ((workerNodeKey) => boolean)

    Updates the worker node key strategy internals. This is called after a task has been executed on a worker node.

    Type declaration

      • (workerNodeKey): boolean
      • Parameters

        • workerNodeKey: number

        Returns boolean

    Returns

    true if the update is successful, false otherwise.

    -
    \ No newline at end of file +
    \ No newline at end of file diff --git a/docs/interfaces/IWorkerNode.html b/docs/interfaces/IWorkerNode.html index b550427b..06da4b3c 100644 --- a/docs/interfaces/IWorkerNode.html +++ b/docs/interfaces/IWorkerNode.html @@ -1,8 +1,9 @@ -IWorkerNode | poolifier - v4.0.1

    Interface IWorkerNode<Worker, Data>Internal

    Worker node interface.

    -
    interface IWorkerNode<Worker, Data> {
        clearTasksQueue: (() => void);
        deleteTaskFunctionWorkerUsage: ((name) => boolean);
        dequeueTask: ((bucket?) => undefined | Task<Data>);
        enqueueTask: ((task) => number);
        getTaskFunctionWorkerUsage: ((name) => undefined | WorkerUsage);
        hasBackPressure: (() => boolean);
        info: WorkerInfo;
        messageChannel?: MessageChannel;
        registerOnceWorkerEventHandler: ((event, handler) => void);
        registerWorkerEventHandler: ((event, handler) => void);
        strategyData?: StrategyData;
        tasksQueueBackPressureSize: number;
        tasksQueueSize: (() => number);
        terminate: (() => Promise<void>);
        usage: WorkerUsage;
        worker: Worker;
        [captureRejectionSymbol]?<K>(error, event, ...args): void;
        addListener<K>(eventName, listener): this;
        emit<K>(eventName, ...args): boolean;
        eventNames(): (string | symbol)[];
        getMaxListeners(): number;
        listenerCount<K>(eventName, listener?): number;
        listeners<K>(eventName): Function[];
        off<K>(eventName, listener): this;
        on<K>(eventName, listener): this;
        once<K>(eventName, listener): this;
        prependListener<K>(eventName, listener): this;
        prependOnceListener<K>(eventName, listener): this;
        rawListeners<K>(eventName): Function[];
        removeAllListeners(eventName?): this;
        removeListener<K>(eventName, listener): this;
        setMaxListeners(n): this;
    }

    Type Parameters

    Hierarchy

    • EventEmitter
      • IWorkerNode

    Properties

    clearTasksQueue: (() => void)

    Clears tasks queue.

    -

    Type declaration

      • (): void
      • Returns void

    deleteTaskFunctionWorkerUsage: ((name) => boolean)

    Deletes task function worker usage statistics.

    +

    Type declaration

      • (): void
      • Returns void

    deleteTaskFunctionWorkerUsage: ((name) => boolean)

    Deletes task function worker usage statistics.

    Type declaration

      • (name): boolean
      • Parameters

        • name: string

          The task function name.

        Returns boolean

    Returns

    true if the task function worker usage statistics were deleted, false otherwise.

    -
    dequeueTask: ((bucket?) => undefined | Task<Data>)

    Dequeue task.

    -

    Type declaration

      • (bucket?): undefined | Task<Data>
      • Parameters

        • Optional bucket: number

          The prioritized bucket to dequeue from.

          -

        Returns undefined | Task<Data>

    Default Value

    0
    +
    dequeueLastPrioritizedTask: (() => undefined | Task<Data>)

    Dequeue last prioritized task.

    +

    Type declaration

    Returns

    The dequeued task.

    +
    dequeueTask: ((bucket?) => undefined | Task<Data>)

    Dequeue task.

    +

    Type declaration

      • (bucket?): undefined | Task<Data>
      • Parameters

        • Optional bucket: number

          The prioritized bucket to dequeue from.

          +

        Returns undefined | Task<Data>

    Default Value

    0
     

    Returns

    The dequeued task.

    -
    enqueueTask: ((task) => number)

    Enqueue task.

    -

    Type declaration

    enqueueTask: ((task) => number)

    Enqueue task.

    +

    Type declaration

      • (task): number
      • Parameters

        Returns number

    Returns

    The tasks queue size.

    -
    getTaskFunctionWorkerUsage: ((name) => undefined | WorkerUsage)

    Gets task function worker usage statistics.

    -

    Type declaration

    getTaskFunctionWorkerUsage: ((name) => undefined | WorkerUsage)

    Gets task function worker usage statistics.

    +

    Type declaration

    Returns

    The task function worker usage statistics if the task function worker usage statistics are initialized, undefined otherwise.

    -
    hasBackPressure: (() => boolean)

    Whether the worker node has back pressure (i.e. its tasks queue is full).

    -

    Type declaration

      • (): boolean
      • Returns boolean

    Returns

    true if the worker node has back pressure, false otherwise.

    -

    Worker info.

    -
    messageChannel?: MessageChannel

    Message channel (worker thread only).

    -
    registerOnceWorkerEventHandler: ((event, handler) => void)

    Registers once a worker event handler.

    -

    Type declaration

    hasBackPressure: (() => boolean)

    Whether the worker node has back pressure (i.e. its tasks queue is full).

    +

    Type declaration

      • (): boolean
      • Returns boolean

    Returns

    true if the worker node has back pressure, false otherwise.

    +

    Worker info.

    +
    messageChannel?: MessageChannel

    Message channel (worker thread only).

    +
    registerOnceWorkerEventHandler: ((event, handler) => void)

    Registers once a worker event handler.

    +

    Type declaration

      • (event, handler): void
      • Parameters

        Returns void

    registerWorkerEventHandler: ((event, handler) => void)

    Registers a worker event handler.

    -

    Type declaration

      • (event, handler): void
      • Parameters

        • event: string

          The event.

          +

        Returns void

    registerWorkerEventHandler: ((event, handler) => void)

    Registers a worker event handler.

    +

    Type declaration

      • (event, handler): void
      • Parameters

        Returns void

    strategyData?: StrategyData

    Worker choice strategy data. +

    Returns void

    setTasksQueuePriority: ((enablePriority) => void)

    Sets tasks queue priority.

    +

    Type declaration

      • (enablePriority): void
      • Parameters

        • enablePriority: boolean

          Whether to enable tasks queue priority.

          +

        Returns void

    strategyData?: StrategyData

    Worker choice strategy data. This is used to store data that are specific to the worker choice strategy.

    -
    tasksQueueBackPressureSize: number

    Tasks queue back pressure size. +

    tasksQueueBackPressureSize: number

    Tasks queue back pressure size. This is the number of tasks that can be enqueued before the worker node has back pressure.

    -
    tasksQueueSize: (() => number)

    Tasks queue size.

    -

    Type declaration

      • (): number
      • Returns number

    Returns

    The tasks queue size.

    -
    terminate: (() => Promise<void>)

    Terminates the worker node.

    -

    Type declaration

      • (): Promise<void>
      • Returns Promise<void>

    Worker usage statistics.

    -
    worker: Worker

    Worker.

    -

    Methods

    • Type Parameters

      • K

      Parameters

      • error: Error
      • event: string | symbol
      • Rest ...args: AnyRest

      Returns void

    tasksQueueSize: (() => number)

    Tasks queue size.

    +

    Type declaration

      • (): number
      • Returns number

    Returns

    The tasks queue size.

    +
    terminate: (() => Promise<void>)

    Terminates the worker node.

    +

    Type declaration

      • (): Promise<void>
      • Returns Promise<void>

    Worker usage statistics.

    +
    worker: Worker

    Worker.

    +

    Methods

    • Type Parameters

      • K

      Parameters

      • error: Error
      • event: string | symbol
      • Rest ...args: AnyRest

      Returns void

    • Alias for emitter.on(eventName, listener).

      Type Parameters

      • K

      Parameters

      • eventName: string | symbol
      • listener: ((...args) => void)
          • (...args): void
          • Parameters

            • Rest ...args: any[]

            Returns void

      Returns this

      Since

      v0.1.26

      -
    • Synchronously calls each of the listeners registered for the event namedeventName, in the order they were registered, passing the supplied arguments +

    • Synchronously calls each of the listeners registered for the event named eventName, in the order they were registered, passing the supplied arguments to each.

      Returns true if the event had listeners, false otherwise.

      -
      import { EventEmitter } from 'node:events';
      const myEmitter = new EventEmitter();

      // First listener
      myEmitter.on('event', function firstListener() {
      console.log('Helloooo! first listener');
      });
      // Second listener
      myEmitter.on('event', function secondListener(arg1, arg2) {
      console.log(`event with parameters ${arg1}, ${arg2} in second listener`);
      });
      // Third listener
      myEmitter.on('event', function thirdListener(...args) {
      const parameters = args.join(', ');
      console.log(`event with parameters ${parameters} in third listener`);
      });

      console.log(myEmitter.listeners('event'));

      myEmitter.emit('event', 1, 2, 3, 4, 5);

      // Prints:
      // [
      // [Function: firstListener],
      // [Function: secondListener],
      // [Function: thirdListener]
      // ]
      // Helloooo! first listener
      // event with parameters 1, 2 in second listener
      // event with parameters 1, 2, 3, 4, 5 in third listener +
      import { EventEmitter } from 'node:events';
      const myEmitter = new EventEmitter();

      // First listener
      myEmitter.on('event', function firstListener() {
      console.log('Helloooo! first listener');
      });
      // Second listener
      myEmitter.on('event', function secondListener(arg1, arg2) {
      console.log(`event with parameters ${arg1}, ${arg2} in second listener`);
      });
      // Third listener
      myEmitter.on('event', function thirdListener(...args) {
      const parameters = args.join(', ');
      console.log(`event with parameters ${parameters} in third listener`);
      });

      console.log(myEmitter.listeners('event'));

      myEmitter.emit('event', 1, 2, 3, 4, 5);

      // Prints:
      // [
      // [Function: firstListener],
      // [Function: secondListener],
      // [Function: thirdListener]
      // ]
      // Helloooo! first listener
      // event with parameters 1, 2 in second listener
      // event with parameters 1, 2, 3, 4, 5 in third listener

      Type Parameters

      • K

      Parameters

      • eventName: string | symbol
      • Rest ...args: AnyRest

      Returns boolean

      Since

      v0.1.26

      -
    • Returns an array listing the events for which the emitter has registered +

    • Returns an array listing the events for which the emitter has registered listeners. The values in the array are strings or Symbols.

      -
      import { EventEmitter } from 'node:events';

      const myEE = new EventEmitter();
      myEE.on('foo', () => {});
      myEE.on('bar', () => {});

      const sym = Symbol('symbol');
      myEE.on(sym, () => {});

      console.log(myEE.eventNames());
      // Prints: [ 'foo', 'bar', Symbol(symbol) ] +
      import { EventEmitter } from 'node:events';

      const myEE = new EventEmitter();
      myEE.on('foo', () => {});
      myEE.on('bar', () => {});

      const sym = Symbol('symbol');
      myEE.on(sym, () => {});

      console.log(myEE.eventNames());
      // Prints: [ 'foo', 'bar', Symbol(symbol) ]

      Returns (string | symbol)[]

      Since

      v6.0.0

      -
    • Returns the current max listener value for the EventEmitter which is either +

    • Returns the current max listener value for the EventEmitter which is either set by emitter.setMaxListeners(n) or defaults to defaultMaxListeners.

      Returns number

      Since

      v1.0.0

      -
    • Returns the number of listeners listening for the event named eventName. +

    • Returns the number of listeners listening for the event named eventName. If listener is provided, it will return how many times the listener is found in the list of the listeners of the event.

      Type Parameters

      • K

      Parameters

      • eventName: string | symbol

        The name of the event being listened for

      • Optional listener: Function

        The event handler function

      Returns number

      Since

      v3.2.0

      -
    • Returns a copy of the array of listeners for the event named eventName.

      -
      server.on('connection', (stream) => {
      console.log('someone connected!');
      });
      console.log(util.inspect(server.listeners('connection')));
      // Prints: [ [Function] ] +
    • Returns a copy of the array of listeners for the event named eventName.

      +
      server.on('connection', (stream) => {
      console.log('someone connected!');
      });
      console.log(util.inspect(server.listeners('connection')));
      // Prints: [ [Function] ]

      Type Parameters

      • K

      Parameters

      • eventName: string | symbol

      Returns Function[]

      Since

      v0.1.26

      -
    • Alias for emitter.removeListener().

      +
    • Alias for emitter.removeListener().

      Type Parameters

      • K

      Parameters

      • eventName: string | symbol
      • listener: ((...args) => void)
          • (...args): void
          • Parameters

            • Rest ...args: any[]

            Returns void

      Returns this

      Since

      v10.0.0

      -
    • Adds the listener function to the end of the listeners array for the -event named eventName. No checks are made to see if the listener has -already been added. Multiple calls passing the same combination of eventNameand listener will result in the listener being added, and called, multiple -times.

      -
      server.on('connection', (stream) => {
      console.log('someone connected!');
      }); +
    • Adds the listener function to the end of the listeners array for the event +named eventName. No checks are made to see if the listener has already +been added. Multiple calls passing the same combination of eventName and +listener will result in the listener being added, and called, multiple times.

      +
      server.on('connection', (stream) => {
      console.log('someone connected!');
      });

      Returns a reference to the EventEmitter, so that calls can be chained.

      -

      By default, event listeners are invoked in the order they are added. Theemitter.prependListener() method can be used as an alternative to add the +

      By default, event listeners are invoked in the order they are added. The emitter.prependListener() method can be used as an alternative to add the event listener to the beginning of the listeners array.

      -
      import { EventEmitter } from 'node:events';
      const myEE = new EventEmitter();
      myEE.on('foo', () => console.log('a'));
      myEE.prependListener('foo', () => console.log('b'));
      myEE.emit('foo');
      // Prints:
      // b
      // a +
      import { EventEmitter } from 'node:events';
      const myEE = new EventEmitter();
      myEE.on('foo', () => console.log('a'));
      myEE.prependListener('foo', () => console.log('b'));
      myEE.emit('foo');
      // Prints:
      // b
      // a

      Type Parameters

      • K

      Parameters

      • eventName: string | symbol

        The name of the event.

      • listener: ((...args) => void)

        The callback function

          • (...args): void
          • Parameters

            • Rest ...args: any[]

            Returns void

      Returns this

      Since

      v0.1.101

      -
    • Adds a one-timelistener function for the event named eventName. The +

    • Adds a one-time listener function for the event named eventName. The next time eventName is triggered, this listener is removed and then invoked.

      -
      server.once('connection', (stream) => {
      console.log('Ah, we have our first user!');
      }); +
      server.once('connection', (stream) => {
      console.log('Ah, we have our first user!');
      });

      Returns a reference to the EventEmitter, so that calls can be chained.

      -

      By default, event listeners are invoked in the order they are added. Theemitter.prependOnceListener() method can be used as an alternative to add the +

      By default, event listeners are invoked in the order they are added. The emitter.prependOnceListener() method can be used as an alternative to add the event listener to the beginning of the listeners array.

      -
      import { EventEmitter } from 'node:events';
      const myEE = new EventEmitter();
      myEE.once('foo', () => console.log('a'));
      myEE.prependOnceListener('foo', () => console.log('b'));
      myEE.emit('foo');
      // Prints:
      // b
      // a +
      import { EventEmitter } from 'node:events';
      const myEE = new EventEmitter();
      myEE.once('foo', () => console.log('a'));
      myEE.prependOnceListener('foo', () => console.log('b'));
      myEE.emit('foo');
      // Prints:
      // b
      // a

      Type Parameters

      • K

      Parameters

      • eventName: string | symbol

        The name of the event.

      • listener: ((...args) => void)

        The callback function

          • (...args): void
          • Parameters

            • Rest ...args: any[]

            Returns void

      Returns this

      Since

      v0.3.0

      -
    • Adds the listener function to the beginning of the listeners array for the +

    • Adds the listener function to the beginning of the listeners array for the event named eventName. No checks are made to see if the listener has -already been added. Multiple calls passing the same combination of eventNameand listener will result in the listener being added, and called, multiple -times.

      -
      server.prependListener('connection', (stream) => {
      console.log('someone connected!');
      }); +already been added. Multiple calls passing the same combination of eventName +and listener will result in the listener being added, and called, multiple times.

      +
      server.prependListener('connection', (stream) => {
      console.log('someone connected!');
      });

      Returns a reference to the EventEmitter, so that calls can be chained.

      Type Parameters

      • K

      Parameters

      • eventName: string | symbol

        The name of the event.

      • listener: ((...args) => void)

        The callback function

          • (...args): void
          • Parameters

            • Rest ...args: any[]

            Returns void

      Returns this

      Since

      v6.0.0

      -
    • Adds a one-timelistener function for the event named eventName to the beginning of the listeners array. The next time eventName is triggered, this +

    • Adds a one-timelistener function for the event named eventName to the beginning of the listeners array. The next time eventName is triggered, this listener is removed, and then invoked.

      -
      server.prependOnceListener('connection', (stream) => {
      console.log('Ah, we have our first user!');
      }); +
      server.prependOnceListener('connection', (stream) => {
      console.log('Ah, we have our first user!');
      });

      Returns a reference to the EventEmitter, so that calls can be chained.

      Type Parameters

      • K

      Parameters

      • eventName: string | symbol

        The name of the event.

      • listener: ((...args) => void)

        The callback function

          • (...args): void
          • Parameters

            • Rest ...args: any[]

            Returns void

      Returns this

      Since

      v6.0.0

      -
    • Returns a copy of the array of listeners for the event named eventName, +

    • Returns a copy of the array of listeners for the event named eventName, including any wrappers (such as those created by .once()).

      -
      import { EventEmitter } from 'node:events';
      const emitter = new EventEmitter();
      emitter.once('log', () => console.log('log once'));

      // Returns a new Array with a function `onceWrapper` which has a property
      // `listener` which contains the original listener bound above
      const listeners = emitter.rawListeners('log');
      const logFnWrapper = listeners[0];

      // Logs "log once" to the console and does not unbind the `once` event
      logFnWrapper.listener();

      // Logs "log once" to the console and removes the listener
      logFnWrapper();

      emitter.on('log', () => console.log('log persistently'));
      // Will return a new Array with a single function bound by `.on()` above
      const newListeners = emitter.rawListeners('log');

      // Logs "log persistently" twice
      newListeners[0]();
      emitter.emit('log'); +
      import { EventEmitter } from 'node:events';
      const emitter = new EventEmitter();
      emitter.once('log', () => console.log('log once'));

      // Returns a new Array with a function `onceWrapper` which has a property
      // `listener` which contains the original listener bound above
      const listeners = emitter.rawListeners('log');
      const logFnWrapper = listeners[0];

      // Logs "log once" to the console and does not unbind the `once` event
      logFnWrapper.listener();

      // Logs "log once" to the console and removes the listener
      logFnWrapper();

      emitter.on('log', () => console.log('log persistently'));
      // Will return a new Array with a single function bound by `.on()` above
      const newListeners = emitter.rawListeners('log');

      // Logs "log persistently" twice
      newListeners[0]();
      emitter.emit('log');

      Type Parameters

      • K

      Parameters

      • eventName: string | symbol

      Returns Function[]

      Since

      v9.4.0

      -
    • Removes all listeners, or those of the specified eventName.

      +
    • Removes all listeners, or those of the specified eventName.

      It is bad practice to remove listeners added elsewhere in the code, particularly when the EventEmitter instance was created by some other component or module (e.g. sockets or file streams).

      Returns a reference to the EventEmitter, so that calls can be chained.

      Parameters

      • Optional eventName: string | symbol

      Returns this

      Since

      v0.1.26

      -
    • Removes the specified listener from the listener array for the event namedeventName.

      -
      const callback = (stream) => {
      console.log('someone connected!');
      };
      server.on('connection', callback);
      // ...
      server.removeListener('connection', callback); +
    • Removes the specified listener from the listener array for the event named eventName.

      +
      const callback = (stream) => {
      console.log('someone connected!');
      };
      server.on('connection', callback);
      // ...
      server.removeListener('connection', callback);

      removeListener() will remove, at most, one instance of a listener from the listener array. If any single listener has been added multiple times to the listener array for the specified eventName, then removeListener() must be called multiple times to remove each instance.

      Once an event is emitted, all listeners attached to it at the -time of emitting are called in order. This implies that anyremoveListener() or removeAllListeners() calls after emitting and before the last listener finishes execution +time of emitting are called in order. This implies that any removeListener() or removeAllListeners() calls after emitting and before the last listener finishes execution will not remove them fromemit() in progress. Subsequent events behave as expected.

      -
      import { EventEmitter } from 'node:events';
      class MyEmitter extends EventEmitter {}
      const myEmitter = new MyEmitter();

      const callbackA = () => {
      console.log('A');
      myEmitter.removeListener('event', callbackB);
      };

      const callbackB = () => {
      console.log('B');
      };

      myEmitter.on('event', callbackA);

      myEmitter.on('event', callbackB);

      // callbackA removes listener callbackB but it will still be called.
      // Internal listener array at time of emit [callbackA, callbackB]
      myEmitter.emit('event');
      // Prints:
      // A
      // B

      // callbackB is now removed.
      // Internal listener array [callbackA]
      myEmitter.emit('event');
      // Prints:
      // A +
      import { EventEmitter } from 'node:events';
      class MyEmitter extends EventEmitter {}
      const myEmitter = new MyEmitter();

      const callbackA = () => {
      console.log('A');
      myEmitter.removeListener('event', callbackB);
      };

      const callbackB = () => {
      console.log('B');
      };

      myEmitter.on('event', callbackA);

      myEmitter.on('event', callbackB);

      // callbackA removes listener callbackB but it will still be called.
      // Internal listener array at time of emit [callbackA, callbackB]
      myEmitter.emit('event');
      // Prints:
      // A
      // B

      // callbackB is now removed.
      // Internal listener array [callbackA]
      myEmitter.emit('event');
      // Prints:
      // A

      Because listeners are managed using an internal array, calling this will change the position indices of any listener registered after the listener @@ -169,15 +175,15 @@ but it means that any copies of the listener array as returned by the emitter.listeners() method will need to be recreated.

      When a single function has been added as a handler multiple times for a single event (as in the example below), removeListener() will remove the most -recently added instance. In the example the once('ping')listener is removed:

      -
      import { EventEmitter } from 'node:events';
      const ee = new EventEmitter();

      function pong() {
      console.log('pong');
      }

      ee.on('ping', pong);
      ee.once('ping', pong);
      ee.removeListener('ping', pong);

      ee.emit('ping');
      ee.emit('ping'); +recently added instance. In the example the once('ping') listener is removed:

      +
      import { EventEmitter } from 'node:events';
      const ee = new EventEmitter();

      function pong() {
      console.log('pong');
      }

      ee.on('ping', pong);
      ee.once('ping', pong);
      ee.removeListener('ping', pong);

      ee.emit('ping');
      ee.emit('ping');

      Returns a reference to the EventEmitter, so that calls can be chained.

      Type Parameters

      • K

      Parameters

      • eventName: string | symbol
      • listener: ((...args) => void)
          • (...args): void
          • Parameters

            • Rest ...args: any[]

            Returns void

      Returns this

      Since

      v0.1.26

      -
    • By default EventEmitters will print a warning if more than 10 listeners are +

    • By default EventEmitters will print a warning if more than 10 listeners are added for a particular event. This is a useful default that helps finding memory leaks. The emitter.setMaxListeners() method allows the limit to be -modified for this specific EventEmitter instance. The value can be set toInfinity (or 0) to indicate an unlimited number of listeners.

      +modified for this specific EventEmitter instance. The value can be set to Infinity (or 0) to indicate an unlimited number of listeners.

      Returns a reference to the EventEmitter, so that calls can be chained.

      Parameters

      • n: number

      Returns this

      Since

      v0.3.5

      -
    \ No newline at end of file +
    \ No newline at end of file diff --git a/docs/interfaces/MeasurementOptions.html b/docs/interfaces/MeasurementOptions.html index 84bdfd19..522e1f85 100644 --- a/docs/interfaces/MeasurementOptions.html +++ b/docs/interfaces/MeasurementOptions.html @@ -1,4 +1,4 @@ -MeasurementOptions | poolifier - v4.0.1

    Interface MeasurementOptions

    Measurement options.

    -
    interface MeasurementOptions {
        median: boolean;
    }

    Properties

    median +MeasurementOptions | poolifier - v4.0.13

    Interface MeasurementOptions

    Measurement options.

    +
    interface MeasurementOptions {
        median: boolean;
    }

    Properties

    Properties

    median: boolean

    Set measurement median.

    -
    \ No newline at end of file +
    \ No newline at end of file diff --git a/docs/interfaces/MeasurementStatistics.html b/docs/interfaces/MeasurementStatistics.html index acd21fd7..472cc42e 100644 --- a/docs/interfaces/MeasurementStatistics.html +++ b/docs/interfaces/MeasurementStatistics.html @@ -1,14 +1,14 @@ -MeasurementStatistics | poolifier - v4.0.1

    Interface MeasurementStatisticsInternal

    Measurement statistics.

    -
    interface MeasurementStatistics {
        aggregate?: number;
        average?: number;
        history: CircularArray<number>;
        maximum?: number;
        median?: number;
        minimum?: number;
    }

    Properties

    aggregate? +MeasurementStatistics | poolifier - v4.0.13

    Interface MeasurementStatisticsInternal

    Measurement statistics.

    +
    interface MeasurementStatistics {
        aggregate?: number;
        average?: number;
        history: CircularBuffer;
        maximum?: number;
        median?: number;
        minimum?: number;
    }

    Properties

    aggregate?: number

    Measurement aggregate.

    -
    average?: number

    Measurement average.

    -
    history: CircularArray<number>

    Measurement history.

    -
    maximum?: number

    Measurement maximum.

    -
    median?: number

    Measurement median.

    -
    minimum?: number

    Measurement minimum.

    -
    \ No newline at end of file +
    average?: number

    Measurement average.

    +

    Measurement history.

    +
    maximum?: number

    Measurement maximum.

    +
    median?: number

    Measurement median.

    +
    minimum?: number

    Measurement minimum.

    +
    \ No newline at end of file diff --git a/docs/interfaces/MeasurementStatisticsRequirements.html b/docs/interfaces/MeasurementStatisticsRequirements.html index 8fce6f7a..668acf92 100644 --- a/docs/interfaces/MeasurementStatisticsRequirements.html +++ b/docs/interfaces/MeasurementStatisticsRequirements.html @@ -1,8 +1,8 @@ -MeasurementStatisticsRequirements | poolifier - v4.0.1

    Interface MeasurementStatisticsRequirementsInternal

    Measurement statistics requirements.

    -
    interface MeasurementStatisticsRequirements {
        aggregate: boolean;
        average: boolean;
        median: boolean;
    }

    Properties

    aggregate +MeasurementStatisticsRequirements | poolifier - v4.0.13

    Interface MeasurementStatisticsRequirementsInternal

    Measurement statistics requirements.

    +
    interface MeasurementStatisticsRequirements {
        aggregate: boolean;
        average: boolean;
        median: boolean;
    }

    Properties

    aggregate: boolean

    Requires measurement aggregate.

    -
    average: boolean

    Requires measurement average.

    -
    median: boolean

    Requires measurement median.

    -
    \ No newline at end of file +
    average: boolean

    Requires measurement average.

    +
    median: boolean

    Requires measurement median.

    +
    \ No newline at end of file diff --git a/docs/interfaces/MessageValue.html b/docs/interfaces/MessageValue.html index ac84acbc..fe1ed165 100644 --- a/docs/interfaces/MessageValue.html +++ b/docs/interfaces/MessageValue.html @@ -1,7 +1,7 @@ -MessageValue | poolifier - v4.0.1

    Interface MessageValue<Data, ErrorData>Internal

    Message object that is passed between main worker and worker.

    +MessageValue | poolifier - v4.0.13

    Interface MessageValue<Data, ErrorData>Internal

    Message object that is passed between main worker and worker.

    interface MessageValue<Data, ErrorData> {
        checkActive?: boolean;
        data?: Data;
        kill?: true | "success" | "SOFT" | "HARD" | "failure";
        name?: string;
        port?: MessagePort;
        priority?: number;
        ready?: boolean;
        statistics?: WorkerStatistics;
        strategy?: "ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN";
        taskFunction?: string;
        taskFunctionOperation?: "add" | "default" | "remove";
        taskFunctionOperationStatus?: boolean;
        taskFunctionProperties?: TaskFunctionProperties;
        taskFunctionsProperties?: TaskFunctionProperties[];
        taskId?: `${string}-${string}-${string}-${string}-${string}`;
        taskPerformance?: TaskPerformance;
        timestamp?: number;
        transferList?: readonly TransferListItem[];
        workerError?: WorkerError<ErrorData>;
        workerId?: number;
    }

    Type Parameters

    • Data = unknown

      Type of data sent to the worker or execution response. This can only be structured-cloneable data.

    • ErrorData = unknown

      Type of data sent to the worker triggering an error. This can only be structured-cloneable data.

      -

    Hierarchy (view full)

    Properties

    Hierarchy (view full)

    Properties

    Properties

    checkActive?: boolean

    Whether the worker starts or stops its activity check.

    -
    data?: Data

    Task input data that will be passed to the worker.

    -
    kill?: true | "success" | "SOFT" | "HARD" | "failure"

    Kill code.

    -
    name?: string

    Task name.

    -
    port?: MessagePort

    Message port.

    -
    priority?: number

    Task priority. Lower values have higher priority.

    -

    Default Value

    0
    +
    data?: Data

    Task input data that will be passed to the worker.

    +
    kill?: true | "success" | "SOFT" | "HARD" | "failure"

    Kill code.

    +
    name?: string

    Task name.

    +
    port?: MessagePort

    Message port.

    +
    priority?: number

    Task priority. Lower values have higher priority.

    +

    Default Value

    0
     
    -
    ready?: boolean

    Whether the worker is ready or not.

    -
    statistics?: WorkerStatistics

    Whether the worker computes the given statistics or not.

    -
    strategy?: "ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN"

    Task worker choice strategy.

    -
    taskFunction?: string

    Task function serialized to string.

    -
    taskFunctionOperation?: "add" | "default" | "remove"

    Task function operation:

    +
    ready?: boolean

    Whether the worker is ready or not.

    +
    statistics?: WorkerStatistics

    Whether the worker computes the given statistics or not.

    +
    strategy?: "ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN"

    Task worker choice strategy.

    +
    taskFunction?: string

    Task function serialized to string.

    +
    taskFunctionOperation?: "add" | "default" | "remove"

    Task function operation:

    • 'add' - Add a task function.
    • 'remove' - Remove a task function.
    • 'default' - Set a task function as default.
    -
    taskFunctionOperationStatus?: boolean

    Whether the task function operation is successful or not.

    -
    taskFunctionProperties?: TaskFunctionProperties

    Task function properties.

    -
    taskFunctionsProperties?: TaskFunctionProperties[]

    Task functions properties.

    -
    taskId?: `${string}-${string}-${string}-${string}-${string}`

    Task UUID.

    -
    taskPerformance?: TaskPerformance

    Task performance.

    -
    timestamp?: number

    Timestamp.

    -
    transferList?: readonly TransferListItem[]

    Array of transferable objects.

    -
    workerError?: WorkerError<ErrorData>

    Worker error.

    -
    workerId?: number

    Worker id.

    -
    \ No newline at end of file +
    taskFunctionOperationStatus?: boolean

    Whether the task function operation is successful or not.

    +
    taskFunctionProperties?: TaskFunctionProperties

    Task function properties.

    +
    taskFunctionsProperties?: TaskFunctionProperties[]

    Task functions properties.

    +
    taskId?: `${string}-${string}-${string}-${string}-${string}`

    Task UUID.

    +
    taskPerformance?: TaskPerformance

    Task performance.

    +
    timestamp?: number

    Timestamp.

    +
    transferList?: readonly TransferListItem[]

    Array of transferable objects.

    +
    workerError?: WorkerError<ErrorData>

    Worker error.

    +
    workerId?: number

    Worker id.

    +
    \ No newline at end of file diff --git a/docs/interfaces/PoolInfo.html b/docs/interfaces/PoolInfo.html index 2910d306..8c911dd5 100644 --- a/docs/interfaces/PoolInfo.html +++ b/docs/interfaces/PoolInfo.html @@ -1,7 +1,8 @@ -PoolInfo | poolifier - v4.0.1

    Interface PoolInfo

    Pool information.

    -
    interface PoolInfo {
        backPressure?: boolean;
        busyWorkerNodes: number;
        defaultStrategy: "ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN";
        executedTasks: number;
        executingTasks: number;
        failedTasks: number;
        idleWorkerNodes: number;
        maxQueuedTasks?: number;
        maxSize: number;
        minSize: number;
        queuedTasks?: number;
        ready: boolean;
        runTime?: {
            average?: number;
            maximum: number;
            median?: number;
            minimum: number;
        };
        started: boolean;
        stealingWorkerNodes?: number;
        stolenTasks?: number;
        strategyRetries: number;
        type: "fixed" | "dynamic";
        utilization?: number;
        version: string;
        waitTime?: {
            average?: number;
            maximum: number;
            median?: number;
            minimum: number;
        };
        worker: "thread" | "cluster";
        workerNodes: number;
    }

    Properties

    backPressure? +PoolInfo | poolifier - v4.0.13

    Interface PoolInfo

    Pool information.

    +
    interface PoolInfo {
        backPressure?: boolean;
        busyWorkerNodes: number;
        defaultStrategy: "ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN";
        elu?: {
            active: {
                average?: number;
                maximum: number;
                median?: number;
                minimum: number;
            };
            idle: {
                average?: number;
                maximum: number;
                median?: number;
                minimum: number;
            };
            utilization: {
                average?: number;
                median?: number;
            };
        };
        executedTasks: number;
        executingTasks: number;
        failedTasks: number;
        idleWorkerNodes: number;
        maxQueuedTasks?: number;
        maxSize: number;
        minSize: number;
        queuedTasks?: number;
        ready: boolean;
        runTime?: {
            average?: number;
            maximum: number;
            median?: number;
            minimum: number;
        };
        started: boolean;
        stealingWorkerNodes?: number;
        stolenTasks?: number;
        strategyRetries: number;
        type: "fixed" | "dynamic";
        utilization?: number;
        version: string;
        waitTime?: {
            average?: number;
            maximum: number;
            median?: number;
            minimum: number;
        };
        worker: "thread" | "cluster";
        workerNodes: number;
    }

    Properties

    backPressure?: boolean
    busyWorkerNodes: number

    Pool busy worker nodes.

    -
    defaultStrategy: "ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN"
    executedTasks: number
    executingTasks: number
    failedTasks: number
    idleWorkerNodes: number

    Pool idle worker nodes.

    -
    maxQueuedTasks?: number
    maxSize: number
    minSize: number
    queuedTasks?: number
    ready: boolean
    runTime?: {
        average?: number;
        maximum: number;
        median?: number;
        minimum: number;
    }

    Type declaration

    • Optional Readonly average?: number
    • Readonly maximum: number
    • Optional Readonly median?: number
    • Readonly minimum: number
    started: boolean
    stealingWorkerNodes?: number

    Pool stealing worker nodes.

    -
    stolenTasks?: number
    strategyRetries: number
    type: "fixed" | "dynamic"
    utilization?: number

    Pool utilization.

    -
    version: string
    waitTime?: {
        average?: number;
        maximum: number;
        median?: number;
        minimum: number;
    }

    Type declaration

    • Optional Readonly average?: number
    • Readonly maximum: number
    • Optional Readonly median?: number
    • Readonly minimum: number
    worker: "thread" | "cluster"
    workerNodes: number

    Pool total worker nodes.

    -
    \ No newline at end of file +

    Properties

    backPressure?: boolean
    busyWorkerNodes: number

    Pool busy worker nodes.

    +
    defaultStrategy: "ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN"
    elu?: {
        active: {
            average?: number;
            maximum: number;
            median?: number;
            minimum: number;
        };
        idle: {
            average?: number;
            maximum: number;
            median?: number;
            minimum: number;
        };
        utilization: {
            average?: number;
            median?: number;
        };
    }

    Type declaration

    • active: {
          average?: number;
          maximum: number;
          median?: number;
          minimum: number;
      }
      • Optional Readonly average?: number
      • Readonly maximum: number
      • Optional Readonly median?: number
      • Readonly minimum: number
    • idle: {
          average?: number;
          maximum: number;
          median?: number;
          minimum: number;
      }
      • Optional Readonly average?: number
      • Readonly maximum: number
      • Optional Readonly median?: number
      • Readonly minimum: number
    • utilization: {
          average?: number;
          median?: number;
      }
      • Optional Readonly average?: number
      • Optional Readonly median?: number
    executedTasks: number
    executingTasks: number
    failedTasks: number
    idleWorkerNodes: number

    Pool idle worker nodes.

    +
    maxQueuedTasks?: number
    maxSize: number
    minSize: number
    queuedTasks?: number
    ready: boolean
    runTime?: {
        average?: number;
        maximum: number;
        median?: number;
        minimum: number;
    }

    Type declaration

    • Optional Readonly average?: number
    • Readonly maximum: number
    • Optional Readonly median?: number
    • Readonly minimum: number
    started: boolean
    stealingWorkerNodes?: number

    Pool stealing worker nodes.

    +
    stolenTasks?: number
    strategyRetries: number
    type: "fixed" | "dynamic"
    utilization?: number

    Pool utilization.

    +
    version: string
    waitTime?: {
        average?: number;
        maximum: number;
        median?: number;
        minimum: number;
    }

    Type declaration

    • Optional Readonly average?: number
    • Readonly maximum: number
    • Optional Readonly median?: number
    • Readonly minimum: number
    worker: "thread" | "cluster"
    workerNodes: number

    Pool total worker nodes.

    +
    \ No newline at end of file diff --git a/docs/interfaces/PoolOptions.html b/docs/interfaces/PoolOptions.html index e4e1fb16..a84884dd 100644 --- a/docs/interfaces/PoolOptions.html +++ b/docs/interfaces/PoolOptions.html @@ -1,6 +1,6 @@ -PoolOptions | poolifier - v4.0.1

    Interface PoolOptions<Worker>

    Options for a poolifier pool.

    +PoolOptions | poolifier - v4.0.13

    Interface PoolOptions<Worker>

    Options for a poolifier pool.

    interface PoolOptions<Worker> {
        enableEvents?: boolean;
        enableTasksQueue?: boolean;
        env?: Record<string, unknown>;
        errorHandler?: ErrorHandler<Worker>;
        exitHandler?: ExitHandler<Worker>;
        messageHandler?: MessageHandler<Worker>;
        onlineHandler?: OnlineHandler<Worker>;
        restartWorkerOnError?: boolean;
        settings?: ClusterSettings;
        startWorkers?: boolean;
        tasksQueueOptions?: TasksQueueOptions;
        workerChoiceStrategy?: "ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN";
        workerChoiceStrategyOptions?: WorkerChoiceStrategyOptions;
        workerOptions?: WorkerOptions;
    }

    Type Parameters

    • Worker extends IWorker

      Type of worker.

      -

    Properties

    Properties

    enableEvents?: boolean

    Pool events integrated with async resource emission.

    -

    Default Value

    true
    +

    Default Value

    true
     
    -
    enableTasksQueue?: boolean

    Pool worker node tasks queue.

    -

    Default Value

    false
    +
    enableTasksQueue?: boolean

    Pool worker node tasks queue.

    +

    Default Value

    false
     
    -
    env?: Record<string, unknown>

    Key/value pairs to add to worker process environment.

    +
    env?: Record<string, unknown>

    Key/value pairs to add to worker process environment.

    errorHandler?: ErrorHandler<Worker>

    A function that will listen for error event on each worker.

    +
    errorHandler?: ErrorHandler<Worker>

    A function that will listen for error event on each worker.

    Default Value

    () => {}

    -
    exitHandler?: ExitHandler<Worker>

    A function that will listen for exit event on each worker.

    +
    exitHandler?: ExitHandler<Worker>

    A function that will listen for exit event on each worker.

    Default Value

    () => {}

    -
    messageHandler?: MessageHandler<Worker>

    A function that will listen for message event on each worker.

    +
    messageHandler?: MessageHandler<Worker>

    A function that will listen for message event on each worker.

    Default Value

    () => {}

    -
    onlineHandler?: OnlineHandler<Worker>

    A function that will listen for online event on each worker.

    +
    onlineHandler?: OnlineHandler<Worker>

    A function that will listen for online event on each worker.

    Default Value

    () => {}

    -
    restartWorkerOnError?: boolean

    Restart worker on error.

    -
    settings?: ClusterSettings

    Cluster settings.

    +
    restartWorkerOnError?: boolean

    Restart worker on error.

    +
    settings?: ClusterSettings

    Cluster settings.

    startWorkers?: boolean

    Whether to start the minimum number of workers at pool initialization.

    -

    Default Value

    true
    +
    startWorkers?: boolean

    Whether to start the minimum number of workers at pool initialization.

    +

    Default Value

    true
     
    -
    tasksQueueOptions?: TasksQueueOptions

    Pool worker node tasks queue options.

    -
    workerChoiceStrategy?: "ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN"

    The default worker choice strategy to use in this pool.

    -

    Default Value

    WorkerChoiceStrategies.ROUND_ROBIN
    +
    tasksQueueOptions?: TasksQueueOptions

    Pool worker node tasks queue options.

    +
    workerChoiceStrategy?: "ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN"

    The default worker choice strategy to use in this pool.

    +

    Default Value

    WorkerChoiceStrategies.ROUND_ROBIN
     
    -
    workerChoiceStrategyOptions?: WorkerChoiceStrategyOptions

    The worker choice strategy options.

    -
    workerOptions?: WorkerOptions

    Worker options.

    +
    workerChoiceStrategyOptions?: WorkerChoiceStrategyOptions

    The worker choice strategy options.

    +
    workerOptions?: WorkerOptions

    Worker options.

    \ No newline at end of file +
    \ No newline at end of file diff --git a/docs/interfaces/PriorityQueueNode.html b/docs/interfaces/PriorityQueueNode.html index 34c7fc9b..ba628076 100644 --- a/docs/interfaces/PriorityQueueNode.html +++ b/docs/interfaces/PriorityQueueNode.html @@ -1,5 +1,35 @@ -PriorityQueueNode | poolifier - v4.0.1

    Interface PriorityQueueNode<T>Internal

    Priority queue node.

    -
    interface PriorityQueueNode<T> {
        data: T;
        priority: number;
    }

    Type Parameters

    • T

      Type of priority queue node data.

      -

    Properties

    Properties

    data: T
    priority: number
    \ No newline at end of file +PriorityQueueNode | poolifier - v4.0.13

    Interface PriorityQueueNode<T>Internal

    Priority queue node.

    +
    interface PriorityQueueNode<T> {
        capacity: number;
        enablePriority: boolean;
        next?: FixedPriorityQueue<T>;
        size: number;
        [iterator](): Iterator<T, any, undefined>;
        clear(): void;
        dequeue(): undefined | T;
        empty(): boolean;
        enqueue(data, priority?): number;
        full(): boolean;
        get(index): undefined | T;
    }

    Type Parameters

    • T

      Type of priority queue node data.

      +

    Hierarchy (view full)

    Properties

    capacity: number

    The fixed priority queue capacity.

    +
    enablePriority: boolean

    Whether to enable priority.

    +
    size: number

    The fixed priority queue size.

    +

    Methods

    • Enqueue data into the fixed priority queue.

      +

      Parameters

      • data: T

        Data to enqueue.

        +
      • Optional priority: number

        Priority of the data. Lower values have higher priority.

        +

      Returns number

      The new size of the priority queue.

      +

      Throws

      If the fixed priority queue is full.

      +
    • Gets data from the fixed priority queue.

      +

      Parameters

      • index: number

        The index of the data to get.

        +

      Returns undefined | T

      The data at the index or undefined if the fixed priority queue is empty or the index is out of bounds.

      +
    \ No newline at end of file diff --git a/docs/interfaces/PromiseResponseWrapper.html b/docs/interfaces/PromiseResponseWrapper.html index 35756f46..560d8e66 100644 --- a/docs/interfaces/PromiseResponseWrapper.html +++ b/docs/interfaces/PromiseResponseWrapper.html @@ -1,11 +1,11 @@ -PromiseResponseWrapper | poolifier - v4.0.1

    Interface PromiseResponseWrapper<Response>Internal

    An object holding the task execution response promise resolve/reject callbacks.

    +PromiseResponseWrapper | poolifier - v4.0.13

    Interface PromiseResponseWrapper<Response>Internal

    An object holding the task execution response promise resolve/reject callbacks.

    interface PromiseResponseWrapper<Response> {
        asyncResource?: AsyncResource;
        reject: ((reason?) => void);
        resolve: ((value) => void);
        workerNodeKey: number;
    }

    Type Parameters

    • Response = unknown

      Type of execution response. This can only be structured-cloneable data.

      -

    Properties

    Properties

    asyncResource?: AsyncResource

    The asynchronous resource used to track the task execution.

    -
    reject: ((reason?) => void)

    Reject callback to reject the promise.

    -

    Type declaration

      • (reason?): void
      • Parameters

        • Optional reason: unknown

        Returns void

    resolve: ((value) => void)

    Resolve callback to fulfill the promise.

    -

    Type declaration

    workerNodeKey: number

    The worker node key executing the task.

    -
    \ No newline at end of file +
    reject: ((reason?) => void)

    Reject callback to reject the promise.

    +

    Type declaration

      • (reason?): void
      • Parameters

        • Optional reason: unknown

        Returns void

    resolve: ((value) => void)

    Resolve callback to fulfill the promise.

    +

    Type declaration

    workerNodeKey: number

    The worker node key executing the task.

    +
    \ No newline at end of file diff --git a/docs/interfaces/StrategyData.html b/docs/interfaces/StrategyData.html index 1e31ffa5..4be75f46 100644 --- a/docs/interfaces/StrategyData.html +++ b/docs/interfaces/StrategyData.html @@ -1,3 +1,3 @@ -StrategyData | poolifier - v4.0.1

    Interface StrategyDataInternal

    Worker choice strategy data.

    -
    interface StrategyData {
        virtualTaskEndTimestamp?: number;
    }

    Properties

    virtualTaskEndTimestamp?: number
    \ No newline at end of file +StrategyData | poolifier - v4.0.13

    Interface StrategyDataInternal

    Worker choice strategy data.

    +
    interface StrategyData {
        virtualTaskEndTimestamp?: number;
    }

    Properties

    virtualTaskEndTimestamp?: number
    \ No newline at end of file diff --git a/docs/interfaces/StrategyPolicy.html b/docs/interfaces/StrategyPolicy.html index 389fb4b2..1f3526ca 100644 --- a/docs/interfaces/StrategyPolicy.html +++ b/docs/interfaces/StrategyPolicy.html @@ -1,6 +1,6 @@ -StrategyPolicy | poolifier - v4.0.1

    Interface StrategyPolicyInternal

    Strategy policy.

    -
    interface StrategyPolicy {
        dynamicWorkerReady: boolean;
        dynamicWorkerUsage: boolean;
    }

    Properties

    dynamicWorkerReady +StrategyPolicy | poolifier - v4.0.13

    Interface StrategyPolicyInternal

    Strategy policy.

    +
    interface StrategyPolicy {
        dynamicWorkerReady: boolean;
        dynamicWorkerUsage: boolean;
    }

    Properties

    dynamicWorkerReady: boolean

    Expects the newly created dynamic worker to be flagged as ready.

    -
    dynamicWorkerUsage: boolean

    Expects tasks execution on the newly created dynamic worker.

    -
    \ No newline at end of file +
    dynamicWorkerUsage: boolean

    Expects tasks execution on the newly created dynamic worker.

    +
    \ No newline at end of file diff --git a/docs/interfaces/Task.html b/docs/interfaces/Task.html index 285fef5f..13e59edb 100644 --- a/docs/interfaces/Task.html +++ b/docs/interfaces/Task.html @@ -1,6 +1,6 @@ -Task | poolifier - v4.0.1

    Interface Task<Data>Internal

    Message object that is passed as a task between main worker and worker.

    +Task | poolifier - v4.0.13

    Interface Task<Data>Internal

    Message object that is passed as a task between main worker and worker.

    interface Task<Data> {
        data?: Data;
        name?: string;
        priority?: number;
        strategy?: "ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN";
        taskId?: `${string}-${string}-${string}-${string}-${string}`;
        timestamp?: number;
        transferList?: readonly TransferListItem[];
    }

    Type Parameters

    • Data = unknown

      Type of data sent to the worker. This can only be structured-cloneable data.

      -

    Hierarchy (view full)

    Properties

    Hierarchy (view full)

    Properties

    Properties

    data?: Data

    Task input data that will be passed to the worker.

    -
    name?: string

    Task name.

    -
    priority?: number

    Task priority. Lower values have higher priority.

    -

    Default Value

    0
    +
    name?: string

    Task name.

    +
    priority?: number

    Task priority. Lower values have higher priority.

    +

    Default Value

    0
     
    -
    strategy?: "ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN"

    Task worker choice strategy.

    -
    taskId?: `${string}-${string}-${string}-${string}-${string}`

    Task UUID.

    -
    timestamp?: number

    Timestamp.

    -
    transferList?: readonly TransferListItem[]

    Array of transferable objects.

    -
    \ No newline at end of file +
    strategy?: "ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN"

    Task worker choice strategy.

    +
    taskId?: `${string}-${string}-${string}-${string}-${string}`

    Task UUID.

    +
    timestamp?: number

    Timestamp.

    +
    transferList?: readonly TransferListItem[]

    Array of transferable objects.

    +
    \ No newline at end of file diff --git a/docs/interfaces/TaskFunctionObject.html b/docs/interfaces/TaskFunctionObject.html index ae6b04d8..0bf19371 100644 --- a/docs/interfaces/TaskFunctionObject.html +++ b/docs/interfaces/TaskFunctionObject.html @@ -1,10 +1,10 @@ -TaskFunctionObject | poolifier - v4.0.1

    Interface TaskFunctionObject<Data, Response>

    Task function object.

    +TaskFunctionObject | poolifier - v4.0.13

    Interface TaskFunctionObject<Data, Response>

    Task function object.

    interface TaskFunctionObject<Data, Response> {
        priority?: number;
        strategy?: "ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN";
        taskFunction: TaskFunction<Data, Response>;
    }

    Type Parameters

    • Data = unknown

      Type of data sent to the worker. This can only be structured-cloneable data.

    • Response = unknown

      Type of execution response. This can only be structured-cloneable data.

      -

    Properties

    Properties

    priority?: number

    Task function priority. Lower values have higher priority.

    -
    strategy?: "ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN"

    Task function worker choice strategy.

    -
    taskFunction: TaskFunction<Data, Response>

    Task function.

    -
    \ No newline at end of file +
    strategy?: "ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN"

    Task function worker choice strategy.

    +
    taskFunction: TaskFunction<Data, Response>

    Task function.

    +
    \ No newline at end of file diff --git a/docs/interfaces/TaskFunctionOperationResult.html b/docs/interfaces/TaskFunctionOperationResult.html index b1065020..f2222aba 100644 --- a/docs/interfaces/TaskFunctionOperationResult.html +++ b/docs/interfaces/TaskFunctionOperationResult.html @@ -1,4 +1,4 @@ -TaskFunctionOperationResult | poolifier - v4.0.1

    Interface TaskFunctionOperationResult

    Task function operation result.

    -
    interface TaskFunctionOperationResult {
        error?: Error;
        status: boolean;
    }

    Properties

    error? +TaskFunctionOperationResult | poolifier - v4.0.13

    Interface TaskFunctionOperationResult

    Task function operation result.

    +
    interface TaskFunctionOperationResult {
        error?: Error;
        status: boolean;
    }

    Properties

    Properties

    error?: Error
    status: boolean
    \ No newline at end of file +

    Properties

    error?: Error
    status: boolean
    \ No newline at end of file diff --git a/docs/interfaces/TaskFunctionProperties.html b/docs/interfaces/TaskFunctionProperties.html index 4eefbcc6..d196f012 100644 --- a/docs/interfaces/TaskFunctionProperties.html +++ b/docs/interfaces/TaskFunctionProperties.html @@ -1,8 +1,8 @@ -TaskFunctionProperties | poolifier - v4.0.1

    Interface TaskFunctionProperties

    Task function properties.

    -
    interface TaskFunctionProperties {
        name: string;
        priority?: number;
        strategy?: "ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN";
    }

    Properties

    name +TaskFunctionProperties | poolifier - v4.0.13

    Interface TaskFunctionProperties

    Task function properties.

    +
    interface TaskFunctionProperties {
        name: string;
        priority?: number;
        strategy?: "ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN";
    }

    Properties

    name: string

    Task function name.

    -
    priority?: number

    Task function priority. Lower values have higher priority.

    -
    strategy?: "ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN"

    Task function worker choice strategy.

    -
    \ No newline at end of file +
    priority?: number

    Task function priority. Lower values have higher priority.

    +
    strategy?: "ROUND_ROBIN" | "LEAST_USED" | "LEAST_BUSY" | "LEAST_ELU" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN" | "INTERLEAVED_WEIGHTED_ROUND_ROBIN"

    Task function worker choice strategy.

    +
    \ No newline at end of file diff --git a/docs/interfaces/TaskPerformance.html b/docs/interfaces/TaskPerformance.html index 6a3c8a2c..aea4e405 100644 --- a/docs/interfaces/TaskPerformance.html +++ b/docs/interfaces/TaskPerformance.html @@ -1,10 +1,10 @@ -TaskPerformance | poolifier - v4.0.1

    Interface TaskPerformanceInternal

    Task performance.

    -
    interface TaskPerformance {
        elu?: EventLoopUtilization;
        name: string;
        runTime?: number;
        timestamp: number;
    }

    Properties

    elu? +TaskPerformance | poolifier - v4.0.13

    Interface TaskPerformanceInternal

    Task performance.

    +
    interface TaskPerformance {
        elu?: EventLoopUtilization;
        name: string;
        runTime?: number;
        timestamp: number;
    }

    Properties

    elu?: EventLoopUtilization

    Task event loop utilization.

    -
    name: string

    Task name.

    -
    runTime?: number

    Task runtime.

    -
    timestamp: number

    Task performance timestamp.

    -
    \ No newline at end of file +
    name: string

    Task name.

    +
    runTime?: number

    Task runtime.

    +
    timestamp: number

    Task performance timestamp.

    +
    \ No newline at end of file diff --git a/docs/interfaces/TaskStatistics.html b/docs/interfaces/TaskStatistics.html index 04ae4de6..3902ff77 100644 --- a/docs/interfaces/TaskStatistics.html +++ b/docs/interfaces/TaskStatistics.html @@ -1,5 +1,5 @@ -TaskStatistics | poolifier - v4.0.1

    Interface TaskStatisticsInternal

    Task statistics.

    -
    interface TaskStatistics {
        executed: number;
        executing: number;
        failed: number;
        maxQueued?: number;
        queued: number;
        sequentiallyStolen: number;
        stolen: number;
    }

    Properties

    executed +TaskStatistics | poolifier - v4.0.13

    Interface TaskStatisticsInternal

    Task statistics.

    +
    interface TaskStatistics {
        executed: number;
        executing: number;
        failed: number;
        maxQueued?: number;
        queued: number;
        sequentiallyStolen: number;
        stolen: number;
    }

    Properties

    executed: number

    Number of executed tasks.

    -
    executing: number

    Number of executing tasks.

    -
    failed: number

    Number of failed tasks.

    -
    maxQueued?: number

    Maximum number of queued tasks.

    -
    queued: number

    Number of queued tasks.

    -
    sequentiallyStolen: number

    Number of sequentially stolen tasks.

    -
    stolen: number

    Number of stolen tasks.

    -
    \ No newline at end of file +
    executing: number

    Number of executing tasks.

    +
    failed: number

    Number of failed tasks.

    +
    maxQueued?: number

    Maximum number of queued tasks.

    +
    queued: number

    Number of queued tasks.

    +
    sequentiallyStolen: number

    Number of sequentially stolen tasks.

    +
    stolen: number

    Number of stolen tasks.

    +
    \ No newline at end of file diff --git a/docs/interfaces/TaskStatisticsRequirements.html b/docs/interfaces/TaskStatisticsRequirements.html index 3f67ffd6..2dbe2d46 100644 --- a/docs/interfaces/TaskStatisticsRequirements.html +++ b/docs/interfaces/TaskStatisticsRequirements.html @@ -1,8 +1,8 @@ -TaskStatisticsRequirements | poolifier - v4.0.1

    Interface TaskStatisticsRequirementsInternal

    Pool worker node worker usage statistics requirements.

    -
    interface TaskStatisticsRequirements {
        elu: MeasurementStatisticsRequirements;
        runTime: MeasurementStatisticsRequirements;
        waitTime: MeasurementStatisticsRequirements;
    }

    Properties

    elu +TaskStatisticsRequirements | poolifier - v4.0.13

    Interface TaskStatisticsRequirementsInternal

    Pool worker node worker usage statistics requirements.

    +
    interface TaskStatisticsRequirements {
        elu: MeasurementStatisticsRequirements;
        runTime: MeasurementStatisticsRequirements;
        waitTime: MeasurementStatisticsRequirements;
    }

    Properties

    Properties

    Tasks event loop utilization requirements.

    -

    Tasks runtime requirements.

    -

    Tasks wait time requirements.

    -
    \ No newline at end of file +

    Tasks runtime requirements.

    +

    Tasks wait time requirements.

    +
    \ No newline at end of file diff --git a/docs/interfaces/TasksQueueOptions.html b/docs/interfaces/TasksQueueOptions.html index ef3593ae..ec465fdd 100644 --- a/docs/interfaces/TasksQueueOptions.html +++ b/docs/interfaces/TasksQueueOptions.html @@ -1,22 +1,22 @@ -TasksQueueOptions | poolifier - v4.0.1

    Interface TasksQueueOptions

    Worker node tasks queue options.

    -
    interface TasksQueueOptions {
        concurrency?: number;
        size?: number;
        taskStealing?: boolean;
        tasksFinishedTimeout?: number;
        tasksStealingOnBackPressure?: boolean;
    }

    Properties

    concurrency? +TasksQueueOptions | poolifier - v4.0.13

    Interface TasksQueueOptions

    Worker node tasks queue options.

    +
    interface TasksQueueOptions {
        concurrency?: number;
        size?: number;
        taskStealing?: boolean;
        tasksFinishedTimeout?: number;
        tasksStealingOnBackPressure?: boolean;
    }

    Properties

    concurrency?: number

    Maximum number of tasks that can be executed concurrently on a worker node.

    -

    Default Value

    1
    +

    Default Value

    1
     
    -
    size?: number

    Maximum tasks queue size per worker node flagging it as back pressured.

    -

    Default Value

    (pool maximum size)^2
    +
    size?: number

    Maximum tasks queue size per worker node flagging it as back pressured.

    +

    Default Value

    (pool maximum size)^2
     
    -
    taskStealing?: boolean

    Whether to enable task stealing on idle.

    -

    Default Value

    true
    +
    taskStealing?: boolean

    Whether to enable task stealing on idle.

    +

    Default Value

    true
     
    -
    tasksFinishedTimeout?: number

    Queued tasks finished timeout in milliseconds at worker node termination.

    -

    Default Value

    2000
    +
    tasksFinishedTimeout?: number

    Queued tasks finished timeout in milliseconds at worker node termination.

    +

    Default Value

    2000
     
    -
    tasksStealingOnBackPressure?: boolean

    Whether to enable tasks stealing under back pressure.

    -

    Default Value

    true
    +
    tasksStealingOnBackPressure?: boolean

    Whether to enable tasks stealing under back pressure.

    +

    Default Value

    false
     
    -
    \ No newline at end of file +
    \ No newline at end of file diff --git a/docs/interfaces/WorkerChoiceStrategyOptions.html b/docs/interfaces/WorkerChoiceStrategyOptions.html index 280d070d..6a9ddaf7 100644 --- a/docs/interfaces/WorkerChoiceStrategyOptions.html +++ b/docs/interfaces/WorkerChoiceStrategyOptions.html @@ -1,21 +1,21 @@ -WorkerChoiceStrategyOptions | poolifier - v4.0.1

    Interface WorkerChoiceStrategyOptions

    Worker choice strategy options.

    -
    interface WorkerChoiceStrategyOptions {
        elu?: MeasurementOptions;
        measurement?: "runTime" | "waitTime" | "elu";
        runTime?: MeasurementOptions;
        waitTime?: MeasurementOptions;
        weights?: Record<number, number>;
    }

    Properties

    elu? +WorkerChoiceStrategyOptions | poolifier - v4.0.13

    Interface WorkerChoiceStrategyOptions

    Worker choice strategy options.

    +
    interface WorkerChoiceStrategyOptions {
        elu?: MeasurementOptions;
        measurement?: "runTime" | "waitTime" | "elu";
        runTime?: MeasurementOptions;
        waitTime?: MeasurementOptions;
        weights?: Record<number, number>;
    }

    Properties

    Event loop utilization options.

    -

    Default Value

    { median: false }
    +

    Default Value

    { median: false }
     
    -
    measurement?: "runTime" | "waitTime" | "elu"

    Measurement to use in worker choice strategy supporting it.

    -

    Runtime options.

    -

    Default Value

    { median: false }
    +
    measurement?: "runTime" | "waitTime" | "elu"

    Measurement to use in worker choice strategy supporting it.

    +

    Runtime options.

    +

    Default Value

    { median: false }
     
    -

    Wait time options.

    -

    Default Value

    { median: false }
    +

    Wait time options.

    +

    Default Value

    { median: false }
     
    -
    weights?: Record<number, number>

    Worker weights to use for weighted round robin worker selection strategies. +

    weights?: Record<number, number>

    Worker weights to use for weighted round robin worker selection strategies. A weight is tasks maximum execution time in milliseconds for a worker node.

    -

    Default Value

    Weights computed automatically given the CPU performance.
    +

    Default Value

    Weights computed automatically given the CPU performance.
     
    -
    \ No newline at end of file +
    \ No newline at end of file diff --git a/docs/interfaces/WorkerError.html b/docs/interfaces/WorkerError.html index eaae092f..42f3f670 100644 --- a/docs/interfaces/WorkerError.html +++ b/docs/interfaces/WorkerError.html @@ -1,9 +1,9 @@ -WorkerError | poolifier - v4.0.1

    Interface WorkerError<Data>

    Worker error.

    +WorkerError | poolifier - v4.0.13

    Interface WorkerError<Data>

    Worker error.

    interface WorkerError<Data> {
        data?: Data;
        message: string;
        name: string;
    }

    Type Parameters

    • Data = unknown

      Type of data sent to the worker triggering an error. This can only be structured-cloneable data.

      -

    Properties

    Properties

    Properties

    data?: Data

    Data triggering the error.

    -
    message: string

    Error message.

    -
    name: string

    Task function name triggering the error.

    -
    \ No newline at end of file +
    message: string

    Error message.

    +
    name: string

    Task function name triggering the error.

    +
    \ No newline at end of file diff --git a/docs/interfaces/WorkerInfo.html b/docs/interfaces/WorkerInfo.html index b8552bfd..3b790504 100644 --- a/docs/interfaces/WorkerInfo.html +++ b/docs/interfaces/WorkerInfo.html @@ -1,15 +1,18 @@ -WorkerInfo | poolifier - v4.0.1

    Interface WorkerInfoInternal

    Worker information.

    -
    interface WorkerInfo {
        dynamic: boolean;
        id: undefined | number;
        ready: boolean;
        stealing: boolean;
        taskFunctionsProperties?: TaskFunctionProperties[];
        type: "thread" | "cluster";
    }

    Properties

    dynamic +WorkerInfo | poolifier - v4.0.13

    Interface WorkerInfoInternal

    Worker information.

    +
    interface WorkerInfo {
        backPressure: boolean;
        dynamic: boolean;
        id: undefined | number;
        ready: boolean;
        stealing: boolean;
        taskFunctionsProperties?: TaskFunctionProperties[];
        type: "thread" | "cluster";
    }

    Properties

    dynamic: boolean

    Dynamic flag.

    -
    id: undefined | number

    Worker id.

    -
    ready: boolean

    Ready flag.

    -
    stealing: boolean

    Stealing flag. +

    Properties

    backPressure: boolean

    Back pressure flag. +This flag is set to true when worker node tasks queue has back pressure.

    +
    dynamic: boolean

    Dynamic flag.

    +
    id: undefined | number

    Worker id.

    +
    ready: boolean

    Ready flag.

    +
    stealing: boolean

    Stealing flag. This flag is set to true when worker node is stealing tasks from another worker node.

    -
    taskFunctionsProperties?: TaskFunctionProperties[]

    Task functions properties.

    -
    type: "thread" | "cluster"

    Worker type.

    -
    \ No newline at end of file +
    taskFunctionsProperties?: TaskFunctionProperties[]

    Task functions properties.

    +
    type: "thread" | "cluster"

    Worker type.

    +
    \ No newline at end of file diff --git a/docs/interfaces/WorkerNodeEventDetail.html b/docs/interfaces/WorkerNodeEventDetail.html index c0baa635..f6011f57 100644 --- a/docs/interfaces/WorkerNodeEventDetail.html +++ b/docs/interfaces/WorkerNodeEventDetail.html @@ -1,4 +1,4 @@ -WorkerNodeEventDetail | poolifier - v4.0.1

    Interface WorkerNodeEventDetailInternal

    Worker node event detail.

    -
    interface WorkerNodeEventDetail {
        workerId?: number;
        workerNodeKey?: number;
    }

    Properties

    workerId? +WorkerNodeEventDetail | poolifier - v4.0.13

    Interface WorkerNodeEventDetailInternal

    Worker node event detail.

    +
    interface WorkerNodeEventDetail {
        workerId?: number;
        workerNodeKey?: number;
    }

    Properties

    workerId?: number
    workerNodeKey?: number
    \ No newline at end of file +

    Properties

    workerId?: number
    workerNodeKey?: number
    \ No newline at end of file diff --git a/docs/interfaces/WorkerNodeOptions.html b/docs/interfaces/WorkerNodeOptions.html index 3e055dd5..b3a8049a 100644 --- a/docs/interfaces/WorkerNodeOptions.html +++ b/docs/interfaces/WorkerNodeOptions.html @@ -1,6 +1,7 @@ -WorkerNodeOptions | poolifier - v4.0.1

    Interface WorkerNodeOptionsInternal

    Worker node options.

    -
    interface WorkerNodeOptions {
        env?: Record<string, unknown>;
        tasksQueueBackPressureSize: undefined | number;
        tasksQueueBucketSize: undefined | number;
        workerOptions?: WorkerOptions;
    }

    Properties

    env? +WorkerNodeOptions | poolifier - v4.0.13

    Interface WorkerNodeOptionsInternal

    Worker node options.

    +
    interface WorkerNodeOptions {
        env?: Record<string, unknown>;
        tasksQueueBackPressureSize: undefined | number;
        tasksQueueBucketSize: undefined | number;
        tasksQueuePriority: undefined | boolean;
        workerOptions?: WorkerOptions;
    }

    Properties

    env?: Record<string, unknown>
    tasksQueueBackPressureSize: undefined | number
    tasksQueueBucketSize: undefined | number
    workerOptions?: WorkerOptions
    \ No newline at end of file +

    Properties

    env?: Record<string, unknown>
    tasksQueueBackPressureSize: undefined | number
    tasksQueueBucketSize: undefined | number
    tasksQueuePriority: undefined | boolean
    workerOptions?: WorkerOptions
    \ No newline at end of file diff --git a/docs/interfaces/WorkerOptions.html b/docs/interfaces/WorkerOptions.html index 37204b37..c9063107 100644 --- a/docs/interfaces/WorkerOptions.html +++ b/docs/interfaces/WorkerOptions.html @@ -1,18 +1,18 @@ -WorkerOptions | poolifier - v4.0.1

    Interface WorkerOptions

    Options for workers.

    -
    interface WorkerOptions {
        killBehavior?: "SOFT" | "HARD";
        killHandler?: KillHandler;
        maxInactiveTime?: number;
    }

    Properties

    killBehavior? +WorkerOptions | poolifier - v4.0.13

    Interface WorkerOptions

    Options for workers.

    +
    interface WorkerOptions {
        killBehavior?: "SOFT" | "HARD";
        killHandler?: KillHandler;
        maxInactiveTime?: number;
    }

    Properties

    killBehavior?: "SOFT" | "HARD"

    killBehavior dictates if your worker will be deleted in case a task is active on it.

      -
    • SOFT: If currentTime - lastActiveTime is greater than maxInactiveTime but a task is still executing or queued, then the worker won't be deleted.
    • -
    • HARD: If currentTime - lastActiveTime is greater than maxInactiveTime but a task is still executing or queued, then the worker will be deleted.
    • +
    • SOFT: If currentTime - lastActiveTime is greater than maxInactiveTime but the worker is stealing tasks or a task is executing or queued, then the worker won't be deleted.
    • +
    • HARD: If currentTime - lastActiveTime is greater than maxInactiveTime but the worker is stealing tasks or a task is executing or queued, then the worker will be deleted.

    This option only apply to the newly created workers.

    -

    Default Value

    KillBehaviors.SOFT
    +

    Default Value

    KillBehaviors.SOFT
     
    -
    killHandler?: KillHandler

    The function to call when a worker is killed.

    +
    killHandler?: KillHandler

    The function to call when a worker is killed.

    Default Value

    () => {}

    -
    maxInactiveTime?: number

    Maximum waiting time in milliseconds for tasks on newly created workers. It must be greater or equal than 5.

    +
    maxInactiveTime?: number

    Maximum waiting time in milliseconds for tasks on newly created workers. It must be greater or equal than 5.

    After this time, newly created workers will be terminated. The last active time of your worker will be updated when it terminates a task.

      @@ -20,6 +20,6 @@ The last active time of your worker will be updated when it terminates a task.
    • If killBehavior is set to KillBehaviors.SOFT your tasks have no timeout and your workers will not be terminated until your task is completed.
    -

    Default Value

    60000
    +

    Default Value

    60000
     
    -
    \ No newline at end of file +
    \ No newline at end of file diff --git a/docs/interfaces/WorkerStatistics.html b/docs/interfaces/WorkerStatistics.html index 29a15c1c..4cb2af64 100644 --- a/docs/interfaces/WorkerStatistics.html +++ b/docs/interfaces/WorkerStatistics.html @@ -1,6 +1,6 @@ -WorkerStatistics | poolifier - v4.0.1

    Interface WorkerStatisticsInternal

    Worker task performance statistics computation settings.

    -
    interface WorkerStatistics {
        elu: boolean;
        runTime: boolean;
    }

    Properties

    elu +WorkerStatistics | poolifier - v4.0.13

    Interface WorkerStatisticsInternal

    Worker task performance statistics computation settings.

    +
    interface WorkerStatistics {
        elu: boolean;
        runTime: boolean;
    }

    Properties

    Properties

    elu: boolean

    Whether the worker computes the task event loop utilization (ELU) or not.

    -
    runTime: boolean

    Whether the worker computes the task runtime or not.

    -
    \ No newline at end of file +
    runTime: boolean

    Whether the worker computes the task runtime or not.

    +
    \ No newline at end of file diff --git a/docs/interfaces/WorkerUsage.html b/docs/interfaces/WorkerUsage.html index caf05691..5347bdf5 100644 --- a/docs/interfaces/WorkerUsage.html +++ b/docs/interfaces/WorkerUsage.html @@ -1,10 +1,10 @@ -WorkerUsage | poolifier - v4.0.1

    Interface WorkerUsageInternal

    Worker usage statistics.

    -
    interface WorkerUsage {
        elu: EventLoopUtilizationMeasurementStatistics;
        runTime: MeasurementStatistics;
        tasks: TaskStatistics;
        waitTime: MeasurementStatistics;
    }

    Properties

    elu +WorkerUsage | poolifier - v4.0.13

    Interface WorkerUsageInternal

    Worker usage statistics.

    +
    interface WorkerUsage {
        elu: EventLoopUtilizationMeasurementStatistics;
        runTime: MeasurementStatistics;
        tasks: TaskStatistics;
        waitTime: MeasurementStatistics;
    }

    Properties

    Tasks event loop utilization statistics.

    -

    Tasks runtime statistics.

    -

    Tasks statistics.

    -

    Tasks wait time statistics.

    -
    \ No newline at end of file +

    Tasks runtime statistics.

    +

    Tasks statistics.

    +

    Tasks wait time statistics.

    +
    \ No newline at end of file diff --git a/docs/types/ClusterPoolOptions.html b/docs/types/ClusterPoolOptions.html index 76d2668a..eec1b1b2 100644 --- a/docs/types/ClusterPoolOptions.html +++ b/docs/types/ClusterPoolOptions.html @@ -1,2 +1,2 @@ -ClusterPoolOptions | poolifier - v4.0.1

    Type alias ClusterPoolOptions

    ClusterPoolOptions: PoolOptions<Worker>

    Options for a poolifier cluster pool.

    -
    \ No newline at end of file +ClusterPoolOptions | poolifier - v4.0.13

    Type alias ClusterPoolOptions

    ClusterPoolOptions: PoolOptions<Worker>

    Options for a poolifier cluster pool.

    +
    \ No newline at end of file diff --git a/docs/types/ErrorHandler.html b/docs/types/ErrorHandler.html index b1747011..cd486ad1 100644 --- a/docs/types/ErrorHandler.html +++ b/docs/types/ErrorHandler.html @@ -1,3 +1,3 @@ -ErrorHandler | poolifier - v4.0.1

    Type alias ErrorHandler<Worker>

    ErrorHandler<Worker>: ((this, error) => void)

    Callback invoked if the worker raised an error.

    +ErrorHandler | poolifier - v4.0.13

    Type alias ErrorHandler<Worker>

    ErrorHandler<Worker>: ((this, error) => void)

    Callback invoked if the worker raised an error.

    Type Parameters

    • Worker extends IWorker

      Type of worker.

      -

    Type declaration

      • (this, error): void
      • Parameters

        Returns void

    \ No newline at end of file +

    Type declaration

      • (this, error): void
      • Parameters

        Returns void

    \ No newline at end of file diff --git a/docs/types/EventHandler.html b/docs/types/EventHandler.html index 8acd9332..374257a8 100644 --- a/docs/types/EventHandler.html +++ b/docs/types/EventHandler.html @@ -1,3 +1,3 @@ -EventHandler | poolifier - v4.0.1

    Type alias EventHandler<Worker>

    Worker event handler.

    +EventHandler | poolifier - v4.0.13

    Type alias EventHandler<Worker>

    Worker event handler.

    Type Parameters

    • Worker extends IWorker

      Type of worker.

      -
    \ No newline at end of file +
    \ No newline at end of file diff --git a/docs/types/ExitHandler.html b/docs/types/ExitHandler.html index 747ecaa2..cbe17ef8 100644 --- a/docs/types/ExitHandler.html +++ b/docs/types/ExitHandler.html @@ -1,3 +1,3 @@ -ExitHandler | poolifier - v4.0.1

    Type alias ExitHandler<Worker>

    ExitHandler<Worker>: ((this, exitCode) => void)

    Callback invoked when the worker exits successfully.

    +ExitHandler | poolifier - v4.0.13

    Type alias ExitHandler<Worker>

    ExitHandler<Worker>: ((this, exitCode) => void)

    Callback invoked when the worker exits successfully.

    Type Parameters

    • Worker extends IWorker

      Type of worker.

      -

    Type declaration

      • (this, exitCode): void
      • Parameters

        Returns void

    \ No newline at end of file +

    Type declaration

      • (this, exitCode): void
      • Parameters

        Returns void

    \ No newline at end of file diff --git a/docs/types/KillBehavior.html b/docs/types/KillBehavior.html index b4f3c153..d6080c8e 100644 --- a/docs/types/KillBehavior.html +++ b/docs/types/KillBehavior.html @@ -1,2 +1,2 @@ -KillBehavior | poolifier - v4.0.1

    Type alias KillBehavior

    KillBehavior: keyof typeof KillBehaviors

    Kill behavior.

    -
    \ No newline at end of file +KillBehavior | poolifier - v4.0.13

    Type alias KillBehavior

    KillBehavior: keyof typeof KillBehaviors

    Kill behavior.

    +
    \ No newline at end of file diff --git a/docs/types/KillHandler.html b/docs/types/KillHandler.html index bb912b7c..fcceabf9 100644 --- a/docs/types/KillHandler.html +++ b/docs/types/KillHandler.html @@ -1,2 +1,2 @@ -KillHandler | poolifier - v4.0.1

    Type alias KillHandler

    KillHandler: (() => void | Promise<void>)

    Handler called when a worker is killed.

    -

    Type declaration

      • (): void | Promise<void>
      • Returns void | Promise<void>

    \ No newline at end of file +KillHandler | poolifier - v4.0.13

    Type alias KillHandler

    KillHandler: (() => void | Promise<void>)

    Handler called when a worker is killed.

    +

    Type declaration

      • (): void | Promise<void>
      • Returns void | Promise<void>

    \ No newline at end of file diff --git a/docs/types/Measurement.html b/docs/types/Measurement.html index 92ebf641..351a8072 100644 --- a/docs/types/Measurement.html +++ b/docs/types/Measurement.html @@ -1,2 +1,2 @@ -Measurement | poolifier - v4.0.1

    Type alias Measurement

    Measurement: keyof typeof Measurements

    Measurement.

    -
    \ No newline at end of file +Measurement | poolifier - v4.0.13

    Type alias Measurement

    Measurement: keyof typeof Measurements

    Measurement.

    +
    \ No newline at end of file diff --git a/docs/types/MessageHandler.html b/docs/types/MessageHandler.html index ff71974b..543ae1c6 100644 --- a/docs/types/MessageHandler.html +++ b/docs/types/MessageHandler.html @@ -1,3 +1,3 @@ -MessageHandler | poolifier - v4.0.1

    Type alias MessageHandler<Worker>

    MessageHandler<Worker>: ((this, message) => void)

    Callback invoked if the worker has received a message.

    +MessageHandler | poolifier - v4.0.13

    Type alias MessageHandler<Worker>

    MessageHandler<Worker>: ((this, message) => void)

    Callback invoked if the worker has received a message.

    Type Parameters

    • Worker extends IWorker

      Type of worker.

      -

    Type declaration

      • (this, message): void
      • Parameters

        Returns void

    \ No newline at end of file +

    Type declaration

      • (this, message): void
      • Parameters

        Returns void

    \ No newline at end of file diff --git a/docs/types/OnlineHandler.html b/docs/types/OnlineHandler.html index 4f6a59a4..bff9472d 100644 --- a/docs/types/OnlineHandler.html +++ b/docs/types/OnlineHandler.html @@ -1,3 +1,3 @@ -OnlineHandler | poolifier - v4.0.1

    Type alias OnlineHandler<Worker>

    OnlineHandler<Worker>: ((this) => void)

    Callback invoked when the worker has started successfully.

    +OnlineHandler | poolifier - v4.0.13

    Type alias OnlineHandler<Worker>

    OnlineHandler<Worker>: ((this) => void)

    Callback invoked when the worker has started successfully.

    Type Parameters

    • Worker extends IWorker

      Type of worker.

      -

    Type declaration

      • (this): void
      • Parameters

        Returns void

    \ No newline at end of file +

    Type declaration

      • (this): void
      • Parameters

        Returns void

    \ No newline at end of file diff --git a/docs/types/PoolEvent.html b/docs/types/PoolEvent.html index 04d77e67..3c1928fa 100644 --- a/docs/types/PoolEvent.html +++ b/docs/types/PoolEvent.html @@ -1,2 +1,2 @@ -PoolEvent | poolifier - v4.0.1

    Type alias PoolEvent

    PoolEvent: keyof typeof PoolEvents

    Pool event.

    -
    \ No newline at end of file +PoolEvent | poolifier - v4.0.13

    Type alias PoolEvent

    PoolEvent: keyof typeof PoolEvents

    Pool event.

    +
    \ No newline at end of file diff --git a/docs/types/PoolType.html b/docs/types/PoolType.html index c488158e..964cdc61 100644 --- a/docs/types/PoolType.html +++ b/docs/types/PoolType.html @@ -1,2 +1,2 @@ -PoolType | poolifier - v4.0.1

    Type alias PoolType

    PoolType: keyof typeof PoolTypes

    Pool type.

    -
    \ No newline at end of file +PoolType | poolifier - v4.0.13

    Type alias PoolType

    PoolType: keyof typeof PoolTypes

    Pool type.

    +
    \ No newline at end of file diff --git a/docs/types/TaskAsyncFunction.html b/docs/types/TaskAsyncFunction.html index d47d492a..5c50a3ea 100644 --- a/docs/types/TaskAsyncFunction.html +++ b/docs/types/TaskAsyncFunction.html @@ -1,7 +1,7 @@ -TaskAsyncFunction | poolifier - v4.0.1

    Type alias TaskAsyncFunction<Data, Response>

    TaskAsyncFunction<Data, Response>: ((data?) => Promise<Response>)

    Task asynchronous function that can be executed. +TaskAsyncFunction | poolifier - v4.0.13

    Type alias TaskAsyncFunction<Data, Response>

    TaskAsyncFunction<Data, Response>: ((data?) => Promise<Response>)

    Task asynchronous function that can be executed. This function must return a promise.

    Type Parameters

    • Data = unknown

      Type of data sent to the worker. This can only be structured-cloneable data.

    • Response = unknown

      Type of execution response. This can only be structured-cloneable data.

    Type declaration

      • (data?): Promise<Response>
      • Parameters

        • Optional data: Data

          Data sent to the worker.

        Returns Promise<Response>

    Returns

    Execution response promise.

    -
    \ No newline at end of file +
    \ No newline at end of file diff --git a/docs/types/TaskFunction.html b/docs/types/TaskFunction.html index 11a2cca4..52deb654 100644 --- a/docs/types/TaskFunction.html +++ b/docs/types/TaskFunction.html @@ -1,5 +1,5 @@ -TaskFunction | poolifier - v4.0.1

    Type alias TaskFunction<Data, Response>

    Task function that can be executed. +TaskFunction | poolifier - v4.0.13

    Type alias TaskFunction<Data, Response>

    Task function that can be executed. This function can be synchronous or asynchronous.

    Type Parameters

    • Data = unknown

      Type of data sent to the worker. This can only be structured-cloneable data.

    • Response = unknown

      Type of execution response. This can only be structured-cloneable data.

      -
    \ No newline at end of file +
    \ No newline at end of file diff --git a/docs/types/TaskFunctions.html b/docs/types/TaskFunctions.html index 5dd46406..80fef2ac 100644 --- a/docs/types/TaskFunctions.html +++ b/docs/types/TaskFunctions.html @@ -1,6 +1,6 @@ -TaskFunctions | poolifier - v4.0.1

    Type alias TaskFunctions<Data, Response>

    TaskFunctions<Data, Response>: Record<string, TaskFunction<Data, Response> | TaskFunctionObject<Data, Response>>

    Tasks functions that can be executed. +TaskFunctions | poolifier - v4.0.13

    Type alias TaskFunctions<Data, Response>

    TaskFunctions<Data, Response>: Record<string, TaskFunction<Data, Response> | TaskFunctionObject<Data, Response>>

    Tasks functions that can be executed. The key is the name of the task function or task function object. The value is the task function or task function object.

    Type Parameters

    • Data = unknown

      Type of data sent to the worker. This can only be structured-cloneable data.

    • Response = unknown

      Type of execution response. This can only be structured-cloneable data.

      -
    \ No newline at end of file +
    \ No newline at end of file diff --git a/docs/types/TaskSyncFunction.html b/docs/types/TaskSyncFunction.html index 818cb340..2b3b8a52 100644 --- a/docs/types/TaskSyncFunction.html +++ b/docs/types/TaskSyncFunction.html @@ -1,6 +1,6 @@ -TaskSyncFunction | poolifier - v4.0.1

    Type alias TaskSyncFunction<Data, Response>

    TaskSyncFunction<Data, Response>: ((data?) => Response)

    Task synchronous function that can be executed.

    +TaskSyncFunction | poolifier - v4.0.13

    Type alias TaskSyncFunction<Data, Response>

    TaskSyncFunction<Data, Response>: ((data?) => Response)

    Task synchronous function that can be executed.

    Type Parameters

    • Data = unknown

      Type of data sent to the worker. This can only be structured-cloneable data.

    • Response = unknown

      Type of execution response. This can only be structured-cloneable data.

    Type declaration

    Returns

    Execution response.

    -
    \ No newline at end of file +
    \ No newline at end of file diff --git a/docs/types/ThreadPoolOptions.html b/docs/types/ThreadPoolOptions.html index 6a6a7808..60866656 100644 --- a/docs/types/ThreadPoolOptions.html +++ b/docs/types/ThreadPoolOptions.html @@ -1,2 +1,2 @@ -ThreadPoolOptions | poolifier - v4.0.1

    Type alias ThreadPoolOptions

    ThreadPoolOptions: PoolOptions<Worker>

    Options for a poolifier thread pool.

    -
    \ No newline at end of file +ThreadPoolOptions | poolifier - v4.0.13

    Type alias ThreadPoolOptions

    ThreadPoolOptions: PoolOptions<Worker>

    Options for a poolifier thread pool.

    +
    \ No newline at end of file diff --git a/docs/types/WorkerChoiceStrategy.html b/docs/types/WorkerChoiceStrategy.html index 665ce422..881d71ee 100644 --- a/docs/types/WorkerChoiceStrategy.html +++ b/docs/types/WorkerChoiceStrategy.html @@ -1,2 +1,2 @@ -WorkerChoiceStrategy | poolifier - v4.0.1

    Type alias WorkerChoiceStrategy

    WorkerChoiceStrategy: keyof typeof WorkerChoiceStrategies

    Worker choice strategy.

    -
    \ No newline at end of file +WorkerChoiceStrategy | poolifier - v4.0.13

    Type alias WorkerChoiceStrategy

    WorkerChoiceStrategy: keyof typeof WorkerChoiceStrategies

    Worker choice strategy.

    +
    \ No newline at end of file diff --git a/docs/types/WorkerType.html b/docs/types/WorkerType.html index bd65e7f1..5ec8b296 100644 --- a/docs/types/WorkerType.html +++ b/docs/types/WorkerType.html @@ -1,2 +1,2 @@ -WorkerType | poolifier - v4.0.1

    Type alias WorkerType

    WorkerType: keyof typeof WorkerTypes

    Worker type.

    -
    \ No newline at end of file +WorkerType | poolifier - v4.0.13

    Type alias WorkerType

    WorkerType: keyof typeof WorkerTypes

    Worker type.

    +
    \ No newline at end of file diff --git a/docs/types/Writable.html b/docs/types/Writable.html index fb4ef75d..82dc113e 100644 --- a/docs/types/Writable.html +++ b/docs/types/Writable.html @@ -1 +1 @@ -Writable | poolifier - v4.0.1

    Type alias Writable<T>

    Writable<T>: {
        -readonly [P in keyof T]: T[P]
    }

    Type Parameters

    • T
    \ No newline at end of file +Writable | poolifier - v4.0.13

    Type alias Writable<T>

    Writable<T>: {
        -readonly [P in keyof T]: T[P]
    }

    Type Parameters

    • T
    \ No newline at end of file diff --git a/docs/variables/KillBehaviors.html b/docs/variables/KillBehaviors.html index 6c2420fa..e3b75344 100644 --- a/docs/variables/KillBehaviors.html +++ b/docs/variables/KillBehaviors.html @@ -1,2 +1,2 @@ -KillBehaviors | poolifier - v4.0.1

    Variable KillBehaviorsConst

    KillBehaviors: Readonly<{
        HARD: "HARD";
        SOFT: "SOFT";
    }> = ...

    Enumeration of kill behaviors.

    -

    Type declaration

    • HARD: "HARD"
    • SOFT: "SOFT"
    \ No newline at end of file +KillBehaviors | poolifier - v4.0.13

    Variable KillBehaviorsConst

    KillBehaviors: Readonly<{
        HARD: "HARD";
        SOFT: "SOFT";
    }> = ...

    Enumeration of kill behaviors.

    +

    Type declaration

    • HARD: "HARD"
    • SOFT: "SOFT"
    \ No newline at end of file diff --git a/docs/variables/Measurements.html b/docs/variables/Measurements.html index 16aa9904..81694e1e 100644 --- a/docs/variables/Measurements.html +++ b/docs/variables/Measurements.html @@ -1,2 +1,2 @@ -Measurements | poolifier - v4.0.1

    Variable MeasurementsConst

    Measurements: Readonly<{
        elu: "elu";
        runTime: "runTime";
        waitTime: "waitTime";
    }> = ...

    Enumeration of measurements.

    -

    Type declaration

    • elu: "elu"
    • runTime: "runTime"
    • waitTime: "waitTime"
    \ No newline at end of file +Measurements | poolifier - v4.0.13

    Variable MeasurementsConst

    Measurements: Readonly<{
        elu: "elu";
        runTime: "runTime";
        waitTime: "waitTime";
    }> = ...

    Enumeration of measurements.

    +

    Type declaration

    • elu: "elu"
    • runTime: "runTime"
    • waitTime: "waitTime"
    \ No newline at end of file diff --git a/docs/variables/PoolEvents.html b/docs/variables/PoolEvents.html index c9927090..08a42742 100644 --- a/docs/variables/PoolEvents.html +++ b/docs/variables/PoolEvents.html @@ -1,2 +1,2 @@ -PoolEvents | poolifier - v4.0.1

    Variable PoolEventsConst

    PoolEvents: Readonly<{
        backPressure: "backPressure";
        busy: "busy";
        destroy: "destroy";
        empty: "empty";
        error: "error";
        full: "full";
        ready: "ready";
        taskError: "taskError";
    }> = ...

    Enumeration of pool events.

    -

    Type declaration

    • backPressure: "backPressure"
    • busy: "busy"
    • destroy: "destroy"
    • empty: "empty"
    • error: "error"
    • full: "full"
    • ready: "ready"
    • taskError: "taskError"
    \ No newline at end of file +PoolEvents | poolifier - v4.0.13

    Variable PoolEventsConst

    PoolEvents: Readonly<{
        backPressure: "backPressure";
        busy: "busy";
        destroy: "destroy";
        empty: "empty";
        error: "error";
        full: "full";
        ready: "ready";
        taskError: "taskError";
    }> = ...

    Enumeration of pool events.

    +

    Type declaration

    • backPressure: "backPressure"
    • busy: "busy"
    • destroy: "destroy"
    • empty: "empty"
    • error: "error"
    • full: "full"
    • ready: "ready"
    • taskError: "taskError"
    \ No newline at end of file diff --git a/docs/variables/PoolTypes.html b/docs/variables/PoolTypes.html index 1d6f3568..75e23fa5 100644 --- a/docs/variables/PoolTypes.html +++ b/docs/variables/PoolTypes.html @@ -1,2 +1,2 @@ -PoolTypes | poolifier - v4.0.1

    Variable PoolTypesConst

    PoolTypes: Readonly<{
        dynamic: "dynamic";
        fixed: "fixed";
    }> = ...

    Enumeration of pool types.

    -

    Type declaration

    • dynamic: "dynamic"
    • fixed: "fixed"
    \ No newline at end of file +PoolTypes | poolifier - v4.0.13

    Variable PoolTypesConst

    PoolTypes: Readonly<{
        dynamic: "dynamic";
        fixed: "fixed";
    }> = ...

    Enumeration of pool types.

    +

    Type declaration

    • dynamic: "dynamic"
    • fixed: "fixed"
    \ No newline at end of file diff --git a/docs/variables/WorkerChoiceStrategies.html b/docs/variables/WorkerChoiceStrategies.html index af1d4682..ed0d838c 100644 --- a/docs/variables/WorkerChoiceStrategies.html +++ b/docs/variables/WorkerChoiceStrategies.html @@ -1,2 +1,2 @@ -WorkerChoiceStrategies | poolifier - v4.0.1

    Variable WorkerChoiceStrategiesConst

    WorkerChoiceStrategies: Readonly<{
        FAIR_SHARE: "FAIR_SHARE";
        INTERLEAVED_WEIGHTED_ROUND_ROBIN: "INTERLEAVED_WEIGHTED_ROUND_ROBIN";
        LEAST_BUSY: "LEAST_BUSY";
        LEAST_ELU: "LEAST_ELU";
        LEAST_USED: "LEAST_USED";
        ROUND_ROBIN: "ROUND_ROBIN";
        WEIGHTED_ROUND_ROBIN: "WEIGHTED_ROUND_ROBIN";
    }> = ...

    Enumeration of worker choice strategies.

    -

    Type declaration

    • FAIR_SHARE: "FAIR_SHARE"
    • INTERLEAVED_WEIGHTED_ROUND_ROBIN: "INTERLEAVED_WEIGHTED_ROUND_ROBIN"
    • LEAST_BUSY: "LEAST_BUSY"
    • LEAST_ELU: "LEAST_ELU"
    • LEAST_USED: "LEAST_USED"
    • ROUND_ROBIN: "ROUND_ROBIN"
    • WEIGHTED_ROUND_ROBIN: "WEIGHTED_ROUND_ROBIN"
    \ No newline at end of file +WorkerChoiceStrategies | poolifier - v4.0.13

    Variable WorkerChoiceStrategiesConst

    WorkerChoiceStrategies: Readonly<{
        FAIR_SHARE: "FAIR_SHARE";
        INTERLEAVED_WEIGHTED_ROUND_ROBIN: "INTERLEAVED_WEIGHTED_ROUND_ROBIN";
        LEAST_BUSY: "LEAST_BUSY";
        LEAST_ELU: "LEAST_ELU";
        LEAST_USED: "LEAST_USED";
        ROUND_ROBIN: "ROUND_ROBIN";
        WEIGHTED_ROUND_ROBIN: "WEIGHTED_ROUND_ROBIN";
    }> = ...

    Enumeration of worker choice strategies.

    +

    Type declaration

    • FAIR_SHARE: "FAIR_SHARE"
    • INTERLEAVED_WEIGHTED_ROUND_ROBIN: "INTERLEAVED_WEIGHTED_ROUND_ROBIN"
    • LEAST_BUSY: "LEAST_BUSY"
    • LEAST_ELU: "LEAST_ELU"
    • LEAST_USED: "LEAST_USED"
    • ROUND_ROBIN: "ROUND_ROBIN"
    • WEIGHTED_ROUND_ROBIN: "WEIGHTED_ROUND_ROBIN"
    \ No newline at end of file diff --git a/docs/variables/WorkerTypes.html b/docs/variables/WorkerTypes.html index 5f6fd631..b588a800 100644 --- a/docs/variables/WorkerTypes.html +++ b/docs/variables/WorkerTypes.html @@ -1,2 +1,2 @@ -WorkerTypes | poolifier - v4.0.1

    Variable WorkerTypesConst

    WorkerTypes: Readonly<{
        cluster: "cluster";
        thread: "thread";
    }> = ...

    Enumeration of worker types.

    -

    Type declaration

    • cluster: "cluster"
    • thread: "thread"
    \ No newline at end of file +WorkerTypes | poolifier - v4.0.13

    Variable WorkerTypesConst

    WorkerTypes: Readonly<{
        cluster: "cluster";
        thread: "thread";
    }> = ...

    Enumeration of worker types.

    +

    Type declaration

    • cluster: "cluster"
    • thread: "thread"
    \ No newline at end of file diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 00000000..67eb035e --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,118 @@ +import cspellConfigs from '@cspell/eslint-plugin/configs' +import js from '@eslint/js' +import { defineFlatConfig } from 'eslint-define-config' +import jsdoc from 'eslint-plugin-jsdoc' +import nodePlugin from 'eslint-plugin-n' +import simpleImportSort from 'eslint-plugin-simple-import-sort' +import globals from 'globals' +import neostandard from 'neostandard' +// eslint-disable-next-line n/no-extraneous-import +import tseslint from 'typescript-eslint' + +export default defineFlatConfig([ + { + ignores: ['docs/**', '**/dist/**', 'lib/**', 'outputs/**'], + }, + cspellConfigs.recommended, + js.configs.recommended, + ...nodePlugin.configs['flat/mixed-esm-and-cjs'], + jsdoc.configs['flat/recommended-typescript'], + ...tseslint.config( + ...tseslint.configs.strictTypeChecked, + ...tseslint.configs.stylisticTypeChecked + ), + ...neostandard({ + ts: true, + globals: { + ...globals.node, + ...globals.mocha, + }, + }), + { + languageOptions: { + parserOptions: { + project: true, + tsconfigRootDir: import.meta.dirname, + }, + }, + }, + { + plugins: { + 'simple-import-sort': simpleImportSort, + }, + rules: { + '@cspell/spellchecker': [ + 'warn', + { + autoFix: true, + cspell: { + words: [ + 'Alessandro', + 'Ardizio', + 'Benoit', + 'IWRR', + 'Quadflieg', + 'neostandard', + 'poolifier', + 'tseslint', + ], + }, + }, + ], + 'simple-import-sort/imports': 'error', + 'simple-import-sort/exports': 'error', + }, + }, + { + files: [ + 'src/pools/selection-strategies/fair-share-worker-choice-strategy.ts', + ], + rules: { + '@stylistic/operator-linebreak': 'off', + }, + }, + { + files: ['**/*.js', '**/*.mjs', '**/*.cjs'], + ...tseslint.configs.disableTypeChecked, + }, + // examples specific configuration + { + files: ['examples/**/*.ts'], + rules: { + '@typescript-eslint/no-unsafe-argument': 'off', + '@typescript-eslint/no-unsafe-call': 'off', + '@typescript-eslint/no-unsafe-return': 'off', + '@typescript-eslint/no-unsafe-assignment': 'off', + '@typescript-eslint/no-unsafe-member-access': 'off', + '@typescript-eslint/no-unnecessary-type-assertion': 'off', + '@typescript-eslint/no-redundant-type-constituents': 'off', + }, + }, + { + files: ['examples/**/*.js', 'examples/**/*.cjs'], + rules: { + 'n/no-missing-import': [ + 'error', + { + allowModules: ['ws'], + }, + ], + '@typescript-eslint/no-require-imports': 'off', + }, + }, + // benchmarks specific configuration + { + files: ['benchmarks/**/*.cjs'], + rules: { + '@typescript-eslint/no-require-imports': 'off', + }, + }, + // tests specific configuration + { + files: ['tests/**/*.js', 'tests/**/*.mjs', 'tests/**/*.cjs'], + rules: { + '@typescript-eslint/no-require-imports': 'off', + '@typescript-eslint/no-empty-function': 'off', + }, + }, +]) diff --git a/examples/javascript/dynamicExample.cjs b/examples/javascript/dynamicExample.cjs index a72ce3a6..ac361d08 100644 --- a/examples/javascript/dynamicExample.cjs +++ b/examples/javascript/dynamicExample.cjs @@ -2,7 +2,7 @@ const { DynamicThreadPool, PoolEvents, - availableParallelism + availableParallelism, } = require('poolifier') const pool = new DynamicThreadPool( @@ -11,7 +11,7 @@ const pool = new DynamicThreadPool( './yourWorker.js', { onlineHandler: () => console.info('worker is online'), - errorHandler: e => console.error(e) + errorHandler: e => console.error(e), } ) let poolFull = 0 diff --git a/examples/javascript/fixedExample.cjs b/examples/javascript/fixedExample.cjs index f191aa24..ac2c3bee 100644 --- a/examples/javascript/fixedExample.cjs +++ b/examples/javascript/fixedExample.cjs @@ -2,12 +2,12 @@ const { FixedThreadPool, PoolEvents, - availableParallelism + availableParallelism, } = require('poolifier') const pool = new FixedThreadPool(availableParallelism(), './yourWorker.cjs', { onlineHandler: () => console.info('worker is online'), - errorHandler: e => console.error(e) + errorHandler: e => console.error(e), }) let poolReady = 0 let poolBusy = 0 diff --git a/examples/javascript/multiFunctionExample.cjs b/examples/javascript/multiFunctionExample.cjs index 643d117a..9f92c132 100644 --- a/examples/javascript/multiFunctionExample.cjs +++ b/examples/javascript/multiFunctionExample.cjs @@ -6,7 +6,7 @@ const pool = new FixedThreadPool( './multiFunctionWorker.cjs', { onlineHandler: () => console.info('worker is online'), - errorHandler: e => console.error(e) + errorHandler: e => console.error(e), } ) diff --git a/examples/javascript/multiFunctionWorker.cjs b/examples/javascript/multiFunctionWorker.cjs index da8f972f..d49962d6 100644 --- a/examples/javascript/multiFunctionWorker.cjs +++ b/examples/javascript/multiFunctionWorker.cjs @@ -1,11 +1,19 @@ 'use strict' const { ThreadWorker } = require('poolifier') +/** + * + * @param data + */ function fn0 (data) { console.info('Executing fn0') return { data: `fn0 input text was '${data.text}'` } } +/** + * + * @param data + */ function fn1 (data) { console.info('Executing fn1') return { data: `fn1 input text was '${data.text}'` } diff --git a/examples/javascript/yourWorker.cjs b/examples/javascript/yourWorker.cjs index 073253ea..fce399bd 100644 --- a/examples/javascript/yourWorker.cjs +++ b/examples/javascript/yourWorker.cjs @@ -1,10 +1,13 @@ 'use strict' const { ThreadWorker } = require('poolifier') +/** + * + */ function yourFunction () { for (let i = 0; i <= 1000; i++) { const o = { - a: i + a: i, } JSON.stringify(o) } diff --git a/examples/typescript/build.sh b/examples/typescript/build.sh index dd6d075e..2fa1e7b7 100755 --- a/examples/typescript/build.sh +++ b/examples/typescript/build.sh @@ -13,4 +13,3 @@ do pnpm build cd - done - diff --git a/examples/typescript/http-client-pool/package.json b/examples/typescript/http-client-pool/package.json index 0c12fef4..7174816d 100644 --- a/examples/typescript/http-client-pool/package.json +++ b/examples/typescript/http-client-pool/package.json @@ -6,10 +6,10 @@ "main": "dist/main.js", "type": "module", "volta": { - "node": "22.0.0", - "pnpm": "9.0.6" + "node": "22.2.0", + "pnpm": "9.1.4" }, - "packageManager": "pnpm@9.0.6", + "packageManager": "pnpm@9.1.4", "scripts": { "build": "pnpm build:clean && tsc", "build:clean": "tsc --build --clean", @@ -21,12 +21,12 @@ "author": "", "license": "ISC", "dependencies": { - "axios": "^1.6.8", + "axios": "^1.7.2", "node-fetch": "^3.3.2", - "poolifier": "^4.0.1" + "poolifier": "^4.0.13" }, "devDependencies": { - "@types/node": "^20.12.8", + "@types/node": "^20.14.0", "typescript": "^5.4.5" } } diff --git a/examples/typescript/http-client-pool/pnpm-lock.yaml b/examples/typescript/http-client-pool/pnpm-lock.yaml index 1cd4e62d..24cf2684 100644 --- a/examples/typescript/http-client-pool/pnpm-lock.yaml +++ b/examples/typescript/http-client-pool/pnpm-lock.yaml @@ -9,32 +9,32 @@ importers: .: dependencies: axios: - specifier: ^1.6.8 - version: 1.6.8 + specifier: ^1.7.2 + version: 1.7.2 node-fetch: specifier: ^3.3.2 version: 3.3.2 poolifier: - specifier: ^4.0.1 - version: 4.0.1 + specifier: ^4.0.13 + version: 4.0.13 devDependencies: '@types/node': - specifier: ^20.12.8 - version: 20.12.8 + specifier: ^20.14.0 + version: 20.14.0 typescript: specifier: ^5.4.5 version: 5.4.5 packages: - '@types/node@20.12.8': - resolution: {integrity: sha512-NU0rJLJnshZWdE/097cdCBbyW1h4hEg0xpovcoAQYHl8dnEyp/NAOiE45pvc+Bd1Dt+2r94v2eGFpQJ4R7g+2w==} + '@types/node@20.14.0': + resolution: {integrity: sha512-5cHBxFGJx6L4s56Bubp4fglrEpmyJypsqI6RgzMfBHWUJQGWAAi8cWcgetEbZXHYXo9C2Fa4EEds/uSyS4cxmA==} asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - axios@1.6.8: - resolution: {integrity: sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==} + axios@1.7.2: + resolution: {integrity: sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==} combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} @@ -85,8 +85,8 @@ packages: resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - poolifier@4.0.1: - resolution: {integrity: sha512-1izVxQOC3yonTN1I51tualsPfZ0iUN+r5zaKY/+vEWIa0cUJMPgi1hN86DL4kwCTwr65JZ42ZrxnQWRmdnzRpA==} + poolifier@4.0.13: + resolution: {integrity: sha512-GPITJo3LZvZXGNDWn6eDpOJ+F5+rq4tvyoXFQJfyJ92w0qr4evjoOX9hymwMGmv8TuifFMIBmgCdcTvoxRdMgA==} engines: {node: '>=18.0.0', pnpm: '>=9.0.0'} proxy-from-env@1.1.0: @@ -106,13 +106,13 @@ packages: snapshots: - '@types/node@20.12.8': + '@types/node@20.14.0': dependencies: undici-types: 5.26.5 asynckit@0.4.0: {} - axios@1.6.8: + axios@1.7.2: dependencies: follow-redirects: 1.15.6 form-data: 4.0.0 @@ -159,7 +159,7 @@ snapshots: fetch-blob: 3.2.0 formdata-polyfill: 4.0.10 - poolifier@4.0.1: {} + poolifier@4.0.13: {} proxy-from-env@1.1.0: {} diff --git a/examples/typescript/http-client-pool/src/main.ts b/examples/typescript/http-client-pool/src/main.ts index 722de1e6..696671ea 100644 --- a/examples/typescript/http-client-pool/src/main.ts +++ b/examples/typescript/http-client-pool/src/main.ts @@ -18,9 +18,9 @@ for (const workerFunction of ['node_fetch', 'fetch', 'axios']) { const responses = await Promise.all(httpClientPoolPromises) const elapsedTime = performance.now() - now console.info( - `Received in ${elapsedTime.toFixed(2)}ms an array with ${ - responses.length - } responses from ${parallelism} parallel requests made with HTTP client pool task function ${workerFunction} on ${requestUrl}:\n`, + `Received in ${elapsedTime.toFixed( + 2 + )}ms an array with ${responses.length.toString()} responses from ${parallelism.toString()} parallel requests made with HTTP client pool task function ${workerFunction} on ${requestUrl}:\n`, responses ) } catch (error) { diff --git a/examples/typescript/http-client-pool/src/pool.ts b/examples/typescript/http-client-pool/src/pool.ts index 6988372e..83bec2fd 100644 --- a/examples/typescript/http-client-pool/src/pool.ts +++ b/examples/typescript/http-client-pool/src/pool.ts @@ -17,10 +17,10 @@ export const httpClientPool = new DynamicThreadPool( { enableTasksQueue: true, tasksQueueOptions: { - concurrency: 8 + concurrency: 8, }, errorHandler: (e: Error) => { console.error('Thread worker error:', e) - } + }, } ) diff --git a/examples/typescript/http-client-pool/src/types.ts b/examples/typescript/http-client-pool/src/types.ts index 6db45d5f..d21087dd 100644 --- a/examples/typescript/http-client-pool/src/types.ts +++ b/examples/typescript/http-client-pool/src/types.ts @@ -1,9 +1,9 @@ import type { URL } from 'node:url' import type { AxiosRequestConfig } from 'axios' -import { - type RequestInfo as NodeFetchRequestInfo, - type RequestInit as NodeFetchRequestInit +import type { + RequestInfo as NodeFetchRequestInfo, + RequestInit as NodeFetchRequestInit, } from 'node-fetch' export interface WorkerData { diff --git a/examples/typescript/http-client-pool/src/worker.ts b/examples/typescript/http-client-pool/src/worker.ts index 904279b4..95917d64 100644 --- a/examples/typescript/http-client-pool/src/worker.ts +++ b/examples/typescript/http-client-pool/src/worker.ts @@ -1,7 +1,7 @@ import axios from 'axios' import nodeFetch, { type RequestInfo as NodeFetchRequestInfo, - type ResponseInit as NodeFetchRequestInit + type ResponseInit as NodeFetchRequestInit, } from 'node-fetch' import { ThreadWorker } from 'poolifier' @@ -12,34 +12,37 @@ class HttpClientWorker extends ThreadWorker { super({ node_fetch: async (workerData?: WorkerData) => { const response = await nodeFetch( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion workerData!.input as URL | NodeFetchRequestInfo, workerData?.init as NodeFetchRequestInit ) // The response is not structured-cloneable, so we return the response text body instead. return { - text: await response.text() + text: await response.text(), } }, fetch: async (workerData?: WorkerData) => { const response = await fetch( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion workerData!.input as URL | RequestInfo, workerData?.init as RequestInit ) // The response is not structured-cloneable, so we return the response text body instead. return { - text: await response.text() + text: await response.text(), } }, axios: async (workerData?: WorkerData) => { const response = await axios({ method: 'get', + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion url: workerData!.input as string, - ...workerData?.axiosRequestConfig + ...workerData?.axiosRequestConfig, }) return { - text: response.data + text: response.data, } - } + }, }) } } diff --git a/examples/typescript/http-server-pool/express-cluster/package.json b/examples/typescript/http-server-pool/express-cluster/package.json index b9c83a84..09b65b07 100644 --- a/examples/typescript/http-server-pool/express-cluster/package.json +++ b/examples/typescript/http-server-pool/express-cluster/package.json @@ -6,10 +6,10 @@ "main": "dist/main.js", "type": "module", "volta": { - "node": "22.0.0", - "pnpm": "9.0.6" + "node": "22.2.0", + "pnpm": "9.1.4" }, - "packageManager": "pnpm@9.0.6", + "packageManager": "pnpm@9.1.4", "scripts": { "build": "rollup --config --configPlugin typescript", "start": "node --enable-source-maps dist/main.cjs", @@ -23,14 +23,14 @@ "license": "ISC", "dependencies": { "express": "^4.19.2", - "poolifier": "^4.0.1" + "poolifier": "^4.0.13" }, "devDependencies": { "@rollup/plugin-typescript": "^11.1.6", "@types/express": "^4.17.21", - "@types/node": "^20.12.8", + "@types/node": "^20.14.0", "autocannon": "^7.15.0", - "rollup": "^4.17.2", + "rollup": "^4.18.0", "rollup-plugin-delete": "^2.0.0", "tslib": "^2.6.2", "typescript": "^5.4.5" diff --git a/examples/typescript/http-server-pool/express-cluster/pnpm-lock.yaml b/examples/typescript/http-server-pool/express-cluster/pnpm-lock.yaml index ecd87e8b..81534372 100644 --- a/examples/typescript/http-server-pool/express-cluster/pnpm-lock.yaml +++ b/examples/typescript/http-server-pool/express-cluster/pnpm-lock.yaml @@ -12,24 +12,24 @@ importers: specifier: ^4.19.2 version: 4.19.2 poolifier: - specifier: ^4.0.1 - version: 4.0.1 + specifier: ^4.0.13 + version: 4.0.13 devDependencies: '@rollup/plugin-typescript': specifier: ^11.1.6 - version: 11.1.6(rollup@4.17.2)(tslib@2.6.2)(typescript@5.4.5) + version: 11.1.6(rollup@4.18.0)(tslib@2.6.2)(typescript@5.4.5) '@types/express': specifier: ^4.17.21 version: 4.17.21 '@types/node': - specifier: ^20.12.8 - version: 20.12.8 + specifier: ^20.14.0 + version: 20.14.0 autocannon: specifier: ^7.15.0 version: 7.15.0 rollup: - specifier: ^4.17.2 - version: 4.17.2 + specifier: ^4.18.0 + version: 4.18.0 rollup-plugin-delete: specifier: ^2.0.0 version: 2.0.0 @@ -83,83 +83,83 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.17.2': - resolution: {integrity: sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==} + '@rollup/rollup-android-arm-eabi@4.18.0': + resolution: {integrity: sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.17.2': - resolution: {integrity: sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==} + '@rollup/rollup-android-arm64@4.18.0': + resolution: {integrity: sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.17.2': - resolution: {integrity: sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==} + '@rollup/rollup-darwin-arm64@4.18.0': + resolution: {integrity: sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.17.2': - resolution: {integrity: sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==} + '@rollup/rollup-darwin-x64@4.18.0': + resolution: {integrity: sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==} cpu: [x64] os: [darwin] - '@rollup/rollup-linux-arm-gnueabihf@4.17.2': - resolution: {integrity: sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==} + '@rollup/rollup-linux-arm-gnueabihf@4.18.0': + resolution: {integrity: sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.17.2': - resolution: {integrity: sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==} + '@rollup/rollup-linux-arm-musleabihf@4.18.0': + resolution: {integrity: sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.17.2': - resolution: {integrity: sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==} + '@rollup/rollup-linux-arm64-gnu@4.18.0': + resolution: {integrity: sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.17.2': - resolution: {integrity: sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==} + '@rollup/rollup-linux-arm64-musl@4.18.0': + resolution: {integrity: sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.17.2': - resolution: {integrity: sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==} + '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': + resolution: {integrity: sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.17.2': - resolution: {integrity: sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==} + '@rollup/rollup-linux-riscv64-gnu@4.18.0': + resolution: {integrity: sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.17.2': - resolution: {integrity: sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==} + '@rollup/rollup-linux-s390x-gnu@4.18.0': + resolution: {integrity: sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.17.2': - resolution: {integrity: sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==} + '@rollup/rollup-linux-x64-gnu@4.18.0': + resolution: {integrity: sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.17.2': - resolution: {integrity: sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==} + '@rollup/rollup-linux-x64-musl@4.18.0': + resolution: {integrity: sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.17.2': - resolution: {integrity: sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==} + '@rollup/rollup-win32-arm64-msvc@4.18.0': + resolution: {integrity: sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.17.2': - resolution: {integrity: sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==} + '@rollup/rollup-win32-ia32-msvc@4.18.0': + resolution: {integrity: sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.17.2': - resolution: {integrity: sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==} + '@rollup/rollup-win32-x64-msvc@4.18.0': + resolution: {integrity: sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==} cpu: [x64] os: [win32] @@ -172,8 +172,8 @@ packages: '@types/estree@1.0.5': resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} - '@types/express-serve-static-core@4.19.0': - resolution: {integrity: sha512-bGyep3JqPCRry1wq+O5n7oiBgGWmeIJXPjXXCo8EK0u8duZGSYar7cGqd3ML2JUsLGeB7fmc06KYo9fLGWqPvQ==} + '@types/express-serve-static-core@4.19.3': + resolution: {integrity: sha512-KOzM7MhcBFlmnlr/fzISFF5vGWVSvN6fTd4T+ExOt08bA/dA5kpSzY52nMsI1KDFmUREpJelPYyuslLRSjjgCg==} '@types/express@4.17.21': resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} @@ -190,8 +190,8 @@ packages: '@types/minimatch@5.1.2': resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} - '@types/node@20.12.8': - resolution: {integrity: sha512-NU0rJLJnshZWdE/097cdCBbyW1h4hEg0xpovcoAQYHl8dnEyp/NAOiE45pvc+Bd1Dt+2r94v2eGFpQJ4R7g+2w==} + '@types/node@20.14.0': + resolution: {integrity: sha512-5cHBxFGJx6L4s56Bubp4fglrEpmyJypsqI6RgzMfBHWUJQGWAAi8cWcgetEbZXHYXo9C2Fa4EEds/uSyS4cxmA==} '@types/qs@6.9.15': resolution: {integrity: sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==} @@ -248,8 +248,8 @@ packages: brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} buffer@5.7.1: @@ -274,8 +274,8 @@ packages: resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} engines: {node: '>=6'} - cli-table3@0.6.4: - resolution: {integrity: sha512-Lm3L0p+/npIQWNIiyF/nAn7T5dnOwR3xNTHXYEBFBFVPXzCVNZ5lqEC/1eo/EVfpDsQ1I+TX4ORPQgp+UI0CRw==} + cli-table3@0.6.5: + resolution: {integrity: sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==} engines: {node: 10.* || >= 12.*} color-convert@2.0.1: @@ -385,8 +385,8 @@ packages: fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} finalhandler@1.2.0: @@ -426,6 +426,7 @@ packages: glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported globby@10.0.2: resolution: {integrity: sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==} @@ -493,6 +494,7 @@ packages: inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -537,10 +539,6 @@ packages: lodash.flatten@4.4.0: resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==} - lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - manage-path@2.0.0: resolution: {integrity: sha512-NJhyB+PJYTpxhxZJ3lecIGgh4kwIY2RAh44XvAz9UlqthlQwtPBf62uBVR8XaD8CRuSjQ6TnZH2lNJkbLPZM2A==} @@ -559,8 +557,8 @@ packages: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} engines: {node: '>= 0.6'} - micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + micromatch@4.0.7: + resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} engines: {node: '>=8.6'} mime-db@1.52.0: @@ -635,8 +633,8 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} - poolifier@4.0.1: - resolution: {integrity: sha512-1izVxQOC3yonTN1I51tualsPfZ0iUN+r5zaKY/+vEWIa0cUJMPgi1hN86DL4kwCTwr65JZ42ZrxnQWRmdnzRpA==} + poolifier@4.0.13: + resolution: {integrity: sha512-GPITJo3LZvZXGNDWn6eDpOJ+F5+rq4tvyoXFQJfyJ92w0qr4evjoOX9hymwMGmv8TuifFMIBmgCdcTvoxRdMgA==} engines: {node: '>=18.0.0', pnpm: '>=9.0.0'} pretty-bytes@5.6.0: @@ -682,14 +680,15 @@ packages: rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true rollup-plugin-delete@2.0.0: resolution: {integrity: sha512-/VpLMtDy+8wwRlDANuYmDa9ss/knGsAgrDhM+tEwB1npHwNu4DYNmDfUL55csse/GHs9Q+SMT/rw9uiaZ3pnzA==} engines: {node: '>=10'} - rollup@4.17.2: - resolution: {integrity: sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==} + rollup@4.18.0: + resolution: {integrity: sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -702,8 +701,8 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - semver@7.6.0: - resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} + semver@7.6.2: + resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} engines: {node: '>=10'} hasBin: true @@ -802,9 +801,6 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - snapshots: '@assemblyscript/loader@0.19.23': {} @@ -824,85 +820,85 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 - '@rollup/plugin-typescript@11.1.6(rollup@4.17.2)(tslib@2.6.2)(typescript@5.4.5)': + '@rollup/plugin-typescript@11.1.6(rollup@4.18.0)(tslib@2.6.2)(typescript@5.4.5)': dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.17.2) + '@rollup/pluginutils': 5.1.0(rollup@4.18.0) resolve: 1.22.8 typescript: 5.4.5 optionalDependencies: - rollup: 4.17.2 + rollup: 4.18.0 tslib: 2.6.2 - '@rollup/pluginutils@5.1.0(rollup@4.17.2)': + '@rollup/pluginutils@5.1.0(rollup@4.18.0)': dependencies: '@types/estree': 1.0.5 estree-walker: 2.0.2 picomatch: 2.3.1 optionalDependencies: - rollup: 4.17.2 + rollup: 4.18.0 - '@rollup/rollup-android-arm-eabi@4.17.2': + '@rollup/rollup-android-arm-eabi@4.18.0': optional: true - '@rollup/rollup-android-arm64@4.17.2': + '@rollup/rollup-android-arm64@4.18.0': optional: true - '@rollup/rollup-darwin-arm64@4.17.2': + '@rollup/rollup-darwin-arm64@4.18.0': optional: true - '@rollup/rollup-darwin-x64@4.17.2': + '@rollup/rollup-darwin-x64@4.18.0': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.17.2': + '@rollup/rollup-linux-arm-gnueabihf@4.18.0': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.17.2': + '@rollup/rollup-linux-arm-musleabihf@4.18.0': optional: true - '@rollup/rollup-linux-arm64-gnu@4.17.2': + '@rollup/rollup-linux-arm64-gnu@4.18.0': optional: true - '@rollup/rollup-linux-arm64-musl@4.17.2': + '@rollup/rollup-linux-arm64-musl@4.18.0': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.17.2': + '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.17.2': + '@rollup/rollup-linux-riscv64-gnu@4.18.0': optional: true - '@rollup/rollup-linux-s390x-gnu@4.17.2': + '@rollup/rollup-linux-s390x-gnu@4.18.0': optional: true - '@rollup/rollup-linux-x64-gnu@4.17.2': + '@rollup/rollup-linux-x64-gnu@4.18.0': optional: true - '@rollup/rollup-linux-x64-musl@4.17.2': + '@rollup/rollup-linux-x64-musl@4.18.0': optional: true - '@rollup/rollup-win32-arm64-msvc@4.17.2': + '@rollup/rollup-win32-arm64-msvc@4.18.0': optional: true - '@rollup/rollup-win32-ia32-msvc@4.17.2': + '@rollup/rollup-win32-ia32-msvc@4.18.0': optional: true - '@rollup/rollup-win32-x64-msvc@4.17.2': + '@rollup/rollup-win32-x64-msvc@4.18.0': optional: true '@types/body-parser@1.19.5': dependencies: '@types/connect': 3.4.38 - '@types/node': 20.12.8 + '@types/node': 20.14.0 '@types/connect@3.4.38': dependencies: - '@types/node': 20.12.8 + '@types/node': 20.14.0 '@types/estree@1.0.5': {} - '@types/express-serve-static-core@4.19.0': + '@types/express-serve-static-core@4.19.3': dependencies: - '@types/node': 20.12.8 + '@types/node': 20.14.0 '@types/qs': 6.9.15 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 @@ -910,14 +906,14 @@ snapshots: '@types/express@4.17.21': dependencies: '@types/body-parser': 1.19.5 - '@types/express-serve-static-core': 4.19.0 + '@types/express-serve-static-core': 4.19.3 '@types/qs': 6.9.15 '@types/serve-static': 1.15.7 '@types/glob@7.2.0': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 20.12.8 + '@types/node': 20.14.0 '@types/http-errors@2.0.4': {} @@ -925,7 +921,7 @@ snapshots: '@types/minimatch@5.1.2': {} - '@types/node@20.12.8': + '@types/node@20.14.0': dependencies: undici-types: 5.26.5 @@ -936,12 +932,12 @@ snapshots: '@types/send@0.17.4': dependencies: '@types/mime': 1.3.5 - '@types/node': 20.12.8 + '@types/node': 20.14.0 '@types/serve-static@1.15.7': dependencies: '@types/http-errors': 2.0.4 - '@types/node': 20.12.8 + '@types/node': 20.14.0 '@types/send': 0.17.4 accepts@1.3.8: @@ -970,7 +966,7 @@ snapshots: dependencies: chalk: 4.1.2 char-spinner: 1.0.1 - cli-table3: 0.6.4 + cli-table3: 0.6.5 color-support: 1.1.3 cross-argv: 2.0.0 form-data: 4.0.0 @@ -988,7 +984,7 @@ snapshots: progress: 2.0.3 reinterval: 1.1.0 retimer: 3.0.0 - semver: 7.6.0 + semver: 7.6.2 subarg: 1.0.0 timestring: 6.0.0 @@ -1018,9 +1014,9 @@ snapshots: balanced-match: 1.0.2 concat-map: 0.0.1 - braces@3.0.2: + braces@3.0.3: dependencies: - fill-range: 7.0.1 + fill-range: 7.1.1 buffer@5.7.1: dependencies: @@ -1046,7 +1042,7 @@ snapshots: clean-stack@2.2.0: {} - cli-table3@0.6.4: + cli-table3@0.6.5: dependencies: string-width: 4.2.3 optionalDependencies: @@ -1169,13 +1165,13 @@ snapshots: '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 - micromatch: 4.0.5 + micromatch: 4.0.7 fastq@1.17.1: dependencies: reusify: 1.0.4 - fill-range@7.0.1: + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -1329,10 +1325,6 @@ snapshots: lodash.flatten@4.4.0: {} - lru-cache@6.0.0: - dependencies: - yallist: 4.0.0 - manage-path@2.0.0: {} media-typer@0.3.0: {} @@ -1343,9 +1335,9 @@ snapshots: methods@1.1.2: {} - micromatch@4.0.5: + micromatch@4.0.7: dependencies: - braces: 3.0.2 + braces: 3.0.3 picomatch: 2.3.1 mime-db@1.52.0: {} @@ -1398,7 +1390,7 @@ snapshots: picomatch@2.3.1: {} - poolifier@4.0.1: {} + poolifier@4.0.13: {} pretty-bytes@5.6.0: {} @@ -1444,26 +1436,26 @@ snapshots: dependencies: del: 5.1.0 - rollup@4.17.2: + rollup@4.18.0: dependencies: '@types/estree': 1.0.5 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.17.2 - '@rollup/rollup-android-arm64': 4.17.2 - '@rollup/rollup-darwin-arm64': 4.17.2 - '@rollup/rollup-darwin-x64': 4.17.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.17.2 - '@rollup/rollup-linux-arm-musleabihf': 4.17.2 - '@rollup/rollup-linux-arm64-gnu': 4.17.2 - '@rollup/rollup-linux-arm64-musl': 4.17.2 - '@rollup/rollup-linux-powerpc64le-gnu': 4.17.2 - '@rollup/rollup-linux-riscv64-gnu': 4.17.2 - '@rollup/rollup-linux-s390x-gnu': 4.17.2 - '@rollup/rollup-linux-x64-gnu': 4.17.2 - '@rollup/rollup-linux-x64-musl': 4.17.2 - '@rollup/rollup-win32-arm64-msvc': 4.17.2 - '@rollup/rollup-win32-ia32-msvc': 4.17.2 - '@rollup/rollup-win32-x64-msvc': 4.17.2 + '@rollup/rollup-android-arm-eabi': 4.18.0 + '@rollup/rollup-android-arm64': 4.18.0 + '@rollup/rollup-darwin-arm64': 4.18.0 + '@rollup/rollup-darwin-x64': 4.18.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.18.0 + '@rollup/rollup-linux-arm-musleabihf': 4.18.0 + '@rollup/rollup-linux-arm64-gnu': 4.18.0 + '@rollup/rollup-linux-arm64-musl': 4.18.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.18.0 + '@rollup/rollup-linux-riscv64-gnu': 4.18.0 + '@rollup/rollup-linux-s390x-gnu': 4.18.0 + '@rollup/rollup-linux-x64-gnu': 4.18.0 + '@rollup/rollup-linux-x64-musl': 4.18.0 + '@rollup/rollup-win32-arm64-msvc': 4.18.0 + '@rollup/rollup-win32-ia32-msvc': 4.18.0 + '@rollup/rollup-win32-x64-msvc': 4.18.0 fsevents: 2.3.3 run-parallel@1.2.0: @@ -1474,9 +1466,7 @@ snapshots: safer-buffer@2.1.2: {} - semver@7.6.0: - dependencies: - lru-cache: 6.0.0 + semver@7.6.2: {} send@0.18.0: dependencies: @@ -1577,5 +1567,3 @@ snapshots: vary@1.1.2: {} wrappy@1.0.2: {} - - yallist@4.0.0: {} diff --git a/examples/typescript/http-server-pool/express-cluster/rollup.config.ts b/examples/typescript/http-server-pool/express-cluster/rollup.config.ts index 236d018c..2fd37607 100644 --- a/examples/typescript/http-server-pool/express-cluster/rollup.config.ts +++ b/examples/typescript/http-server-pool/express-cluster/rollup.config.ts @@ -11,19 +11,19 @@ export default defineConfig({ dir: './dist', sourcemap: true, entryFileNames: '[name].cjs', - chunkFileNames: '[name]-[hash].cjs' + chunkFileNames: '[name]-[hash].cjs', }, { format: 'esm', dir: './dist', - sourcemap: true - } + sourcemap: true, + }, ], external: ['express', /^node:*/, 'poolifier'], plugins: [ typescript(), del({ - targets: ['./dist/*'] - }) - ] + targets: ['./dist/*'], + }), + ], }) diff --git a/examples/typescript/http-server-pool/express-cluster/src/main.ts b/examples/typescript/http-server-pool/express-cluster/src/main.ts index 8922c9fd..0b7c45b1 100644 --- a/examples/typescript/http-server-pool/express-cluster/src/main.ts +++ b/examples/typescript/http-server-pool/express-cluster/src/main.ts @@ -21,7 +21,8 @@ const pool = new FixedClusterPool( .then(response => { if (response.status) { console.info( - `Express is listening in cluster worker on port ${response.port}` + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + `Express is listening in cluster worker on port ${response.port?.toString()}` ) } return undefined @@ -32,6 +33,6 @@ const pool = new FixedClusterPool( }, errorHandler: (e: Error) => { console.error('Cluster worker error:', e) - } + }, } ) diff --git a/examples/typescript/http-server-pool/express-cluster/src/worker.ts b/examples/typescript/http-server-pool/express-cluster/src/worker.ts index 98ca45de..6c0aad8c 100644 --- a/examples/typescript/http-server-pool/express-cluster/src/worker.ts +++ b/examples/typescript/http-server-pool/express-cluster/src/worker.ts @@ -25,6 +25,7 @@ class ExpressWorker extends ClusterWorker { private static readonly startExpress = ( workerData?: WorkerData ): WorkerResponse => { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const { port } = workerData! const application: Express = express() @@ -39,7 +40,9 @@ class ExpressWorker extends ClusterWorker { application.get('/api/factorial/:number', (req: Request, res: Response) => { const { number } = req.params res - .send({ number: ExpressWorker.factorial(parseInt(number)).toString() }) + .send({ + number: ExpressWorker.factorial(Number.parseInt(number)).toString(), + }) .end() }) @@ -47,12 +50,12 @@ class ExpressWorker extends ClusterWorker { ExpressWorker.server = application.listen(port, () => { listenerPort = (ExpressWorker.server.address() as AddressInfo).port console.info( - `⚡️[express server]: Express server is started in cluster worker at http://localhost:${listenerPort}/` + `⚡️[express server]: Express server is started in cluster worker at http://localhost:${listenerPort.toString()}/` ) }) return { status: true, - port: listenerPort ?? port + port: listenerPort ?? port, } } @@ -60,7 +63,7 @@ class ExpressWorker extends ClusterWorker { super(ExpressWorker.startExpress, { killHandler: () => { ExpressWorker.server.close() - } + }, }) } } diff --git a/examples/typescript/http-server-pool/express-hybrid/package.json b/examples/typescript/http-server-pool/express-hybrid/package.json index 83c77a2a..095a0f9c 100644 --- a/examples/typescript/http-server-pool/express-hybrid/package.json +++ b/examples/typescript/http-server-pool/express-hybrid/package.json @@ -6,10 +6,10 @@ "main": "dist/main.js", "type": "module", "volta": { - "node": "22.0.0", - "pnpm": "9.0.6" + "node": "22.2.0", + "pnpm": "9.1.4" }, - "packageManager": "pnpm@9.0.6", + "packageManager": "pnpm@9.1.4", "scripts": { "build": "rollup --config --configPlugin typescript", "start": "node --enable-source-maps dist/main.cjs", @@ -23,14 +23,14 @@ "license": "ISC", "dependencies": { "express": "^4.19.2", - "poolifier": "^4.0.1" + "poolifier": "^4.0.13" }, "devDependencies": { "@rollup/plugin-typescript": "^11.1.6", "@types/express": "^4.17.21", - "@types/node": "^20.12.8", + "@types/node": "^20.14.0", "autocannon": "^7.15.0", - "rollup": "^4.17.2", + "rollup": "^4.18.0", "rollup-plugin-delete": "^2.0.0", "tslib": "^2.6.2", "typescript": "^5.4.5" diff --git a/examples/typescript/http-server-pool/express-hybrid/pnpm-lock.yaml b/examples/typescript/http-server-pool/express-hybrid/pnpm-lock.yaml index ecd87e8b..81534372 100644 --- a/examples/typescript/http-server-pool/express-hybrid/pnpm-lock.yaml +++ b/examples/typescript/http-server-pool/express-hybrid/pnpm-lock.yaml @@ -12,24 +12,24 @@ importers: specifier: ^4.19.2 version: 4.19.2 poolifier: - specifier: ^4.0.1 - version: 4.0.1 + specifier: ^4.0.13 + version: 4.0.13 devDependencies: '@rollup/plugin-typescript': specifier: ^11.1.6 - version: 11.1.6(rollup@4.17.2)(tslib@2.6.2)(typescript@5.4.5) + version: 11.1.6(rollup@4.18.0)(tslib@2.6.2)(typescript@5.4.5) '@types/express': specifier: ^4.17.21 version: 4.17.21 '@types/node': - specifier: ^20.12.8 - version: 20.12.8 + specifier: ^20.14.0 + version: 20.14.0 autocannon: specifier: ^7.15.0 version: 7.15.0 rollup: - specifier: ^4.17.2 - version: 4.17.2 + specifier: ^4.18.0 + version: 4.18.0 rollup-plugin-delete: specifier: ^2.0.0 version: 2.0.0 @@ -83,83 +83,83 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.17.2': - resolution: {integrity: sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==} + '@rollup/rollup-android-arm-eabi@4.18.0': + resolution: {integrity: sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.17.2': - resolution: {integrity: sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==} + '@rollup/rollup-android-arm64@4.18.0': + resolution: {integrity: sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.17.2': - resolution: {integrity: sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==} + '@rollup/rollup-darwin-arm64@4.18.0': + resolution: {integrity: sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.17.2': - resolution: {integrity: sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==} + '@rollup/rollup-darwin-x64@4.18.0': + resolution: {integrity: sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==} cpu: [x64] os: [darwin] - '@rollup/rollup-linux-arm-gnueabihf@4.17.2': - resolution: {integrity: sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==} + '@rollup/rollup-linux-arm-gnueabihf@4.18.0': + resolution: {integrity: sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.17.2': - resolution: {integrity: sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==} + '@rollup/rollup-linux-arm-musleabihf@4.18.0': + resolution: {integrity: sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.17.2': - resolution: {integrity: sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==} + '@rollup/rollup-linux-arm64-gnu@4.18.0': + resolution: {integrity: sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.17.2': - resolution: {integrity: sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==} + '@rollup/rollup-linux-arm64-musl@4.18.0': + resolution: {integrity: sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.17.2': - resolution: {integrity: sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==} + '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': + resolution: {integrity: sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.17.2': - resolution: {integrity: sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==} + '@rollup/rollup-linux-riscv64-gnu@4.18.0': + resolution: {integrity: sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.17.2': - resolution: {integrity: sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==} + '@rollup/rollup-linux-s390x-gnu@4.18.0': + resolution: {integrity: sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.17.2': - resolution: {integrity: sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==} + '@rollup/rollup-linux-x64-gnu@4.18.0': + resolution: {integrity: sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.17.2': - resolution: {integrity: sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==} + '@rollup/rollup-linux-x64-musl@4.18.0': + resolution: {integrity: sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.17.2': - resolution: {integrity: sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==} + '@rollup/rollup-win32-arm64-msvc@4.18.0': + resolution: {integrity: sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.17.2': - resolution: {integrity: sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==} + '@rollup/rollup-win32-ia32-msvc@4.18.0': + resolution: {integrity: sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.17.2': - resolution: {integrity: sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==} + '@rollup/rollup-win32-x64-msvc@4.18.0': + resolution: {integrity: sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==} cpu: [x64] os: [win32] @@ -172,8 +172,8 @@ packages: '@types/estree@1.0.5': resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} - '@types/express-serve-static-core@4.19.0': - resolution: {integrity: sha512-bGyep3JqPCRry1wq+O5n7oiBgGWmeIJXPjXXCo8EK0u8duZGSYar7cGqd3ML2JUsLGeB7fmc06KYo9fLGWqPvQ==} + '@types/express-serve-static-core@4.19.3': + resolution: {integrity: sha512-KOzM7MhcBFlmnlr/fzISFF5vGWVSvN6fTd4T+ExOt08bA/dA5kpSzY52nMsI1KDFmUREpJelPYyuslLRSjjgCg==} '@types/express@4.17.21': resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} @@ -190,8 +190,8 @@ packages: '@types/minimatch@5.1.2': resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} - '@types/node@20.12.8': - resolution: {integrity: sha512-NU0rJLJnshZWdE/097cdCBbyW1h4hEg0xpovcoAQYHl8dnEyp/NAOiE45pvc+Bd1Dt+2r94v2eGFpQJ4R7g+2w==} + '@types/node@20.14.0': + resolution: {integrity: sha512-5cHBxFGJx6L4s56Bubp4fglrEpmyJypsqI6RgzMfBHWUJQGWAAi8cWcgetEbZXHYXo9C2Fa4EEds/uSyS4cxmA==} '@types/qs@6.9.15': resolution: {integrity: sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==} @@ -248,8 +248,8 @@ packages: brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} buffer@5.7.1: @@ -274,8 +274,8 @@ packages: resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} engines: {node: '>=6'} - cli-table3@0.6.4: - resolution: {integrity: sha512-Lm3L0p+/npIQWNIiyF/nAn7T5dnOwR3xNTHXYEBFBFVPXzCVNZ5lqEC/1eo/EVfpDsQ1I+TX4ORPQgp+UI0CRw==} + cli-table3@0.6.5: + resolution: {integrity: sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==} engines: {node: 10.* || >= 12.*} color-convert@2.0.1: @@ -385,8 +385,8 @@ packages: fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} finalhandler@1.2.0: @@ -426,6 +426,7 @@ packages: glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported globby@10.0.2: resolution: {integrity: sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==} @@ -493,6 +494,7 @@ packages: inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -537,10 +539,6 @@ packages: lodash.flatten@4.4.0: resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==} - lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - manage-path@2.0.0: resolution: {integrity: sha512-NJhyB+PJYTpxhxZJ3lecIGgh4kwIY2RAh44XvAz9UlqthlQwtPBf62uBVR8XaD8CRuSjQ6TnZH2lNJkbLPZM2A==} @@ -559,8 +557,8 @@ packages: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} engines: {node: '>= 0.6'} - micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + micromatch@4.0.7: + resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} engines: {node: '>=8.6'} mime-db@1.52.0: @@ -635,8 +633,8 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} - poolifier@4.0.1: - resolution: {integrity: sha512-1izVxQOC3yonTN1I51tualsPfZ0iUN+r5zaKY/+vEWIa0cUJMPgi1hN86DL4kwCTwr65JZ42ZrxnQWRmdnzRpA==} + poolifier@4.0.13: + resolution: {integrity: sha512-GPITJo3LZvZXGNDWn6eDpOJ+F5+rq4tvyoXFQJfyJ92w0qr4evjoOX9hymwMGmv8TuifFMIBmgCdcTvoxRdMgA==} engines: {node: '>=18.0.0', pnpm: '>=9.0.0'} pretty-bytes@5.6.0: @@ -682,14 +680,15 @@ packages: rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true rollup-plugin-delete@2.0.0: resolution: {integrity: sha512-/VpLMtDy+8wwRlDANuYmDa9ss/knGsAgrDhM+tEwB1npHwNu4DYNmDfUL55csse/GHs9Q+SMT/rw9uiaZ3pnzA==} engines: {node: '>=10'} - rollup@4.17.2: - resolution: {integrity: sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==} + rollup@4.18.0: + resolution: {integrity: sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -702,8 +701,8 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - semver@7.6.0: - resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} + semver@7.6.2: + resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} engines: {node: '>=10'} hasBin: true @@ -802,9 +801,6 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - snapshots: '@assemblyscript/loader@0.19.23': {} @@ -824,85 +820,85 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 - '@rollup/plugin-typescript@11.1.6(rollup@4.17.2)(tslib@2.6.2)(typescript@5.4.5)': + '@rollup/plugin-typescript@11.1.6(rollup@4.18.0)(tslib@2.6.2)(typescript@5.4.5)': dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.17.2) + '@rollup/pluginutils': 5.1.0(rollup@4.18.0) resolve: 1.22.8 typescript: 5.4.5 optionalDependencies: - rollup: 4.17.2 + rollup: 4.18.0 tslib: 2.6.2 - '@rollup/pluginutils@5.1.0(rollup@4.17.2)': + '@rollup/pluginutils@5.1.0(rollup@4.18.0)': dependencies: '@types/estree': 1.0.5 estree-walker: 2.0.2 picomatch: 2.3.1 optionalDependencies: - rollup: 4.17.2 + rollup: 4.18.0 - '@rollup/rollup-android-arm-eabi@4.17.2': + '@rollup/rollup-android-arm-eabi@4.18.0': optional: true - '@rollup/rollup-android-arm64@4.17.2': + '@rollup/rollup-android-arm64@4.18.0': optional: true - '@rollup/rollup-darwin-arm64@4.17.2': + '@rollup/rollup-darwin-arm64@4.18.0': optional: true - '@rollup/rollup-darwin-x64@4.17.2': + '@rollup/rollup-darwin-x64@4.18.0': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.17.2': + '@rollup/rollup-linux-arm-gnueabihf@4.18.0': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.17.2': + '@rollup/rollup-linux-arm-musleabihf@4.18.0': optional: true - '@rollup/rollup-linux-arm64-gnu@4.17.2': + '@rollup/rollup-linux-arm64-gnu@4.18.0': optional: true - '@rollup/rollup-linux-arm64-musl@4.17.2': + '@rollup/rollup-linux-arm64-musl@4.18.0': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.17.2': + '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.17.2': + '@rollup/rollup-linux-riscv64-gnu@4.18.0': optional: true - '@rollup/rollup-linux-s390x-gnu@4.17.2': + '@rollup/rollup-linux-s390x-gnu@4.18.0': optional: true - '@rollup/rollup-linux-x64-gnu@4.17.2': + '@rollup/rollup-linux-x64-gnu@4.18.0': optional: true - '@rollup/rollup-linux-x64-musl@4.17.2': + '@rollup/rollup-linux-x64-musl@4.18.0': optional: true - '@rollup/rollup-win32-arm64-msvc@4.17.2': + '@rollup/rollup-win32-arm64-msvc@4.18.0': optional: true - '@rollup/rollup-win32-ia32-msvc@4.17.2': + '@rollup/rollup-win32-ia32-msvc@4.18.0': optional: true - '@rollup/rollup-win32-x64-msvc@4.17.2': + '@rollup/rollup-win32-x64-msvc@4.18.0': optional: true '@types/body-parser@1.19.5': dependencies: '@types/connect': 3.4.38 - '@types/node': 20.12.8 + '@types/node': 20.14.0 '@types/connect@3.4.38': dependencies: - '@types/node': 20.12.8 + '@types/node': 20.14.0 '@types/estree@1.0.5': {} - '@types/express-serve-static-core@4.19.0': + '@types/express-serve-static-core@4.19.3': dependencies: - '@types/node': 20.12.8 + '@types/node': 20.14.0 '@types/qs': 6.9.15 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 @@ -910,14 +906,14 @@ snapshots: '@types/express@4.17.21': dependencies: '@types/body-parser': 1.19.5 - '@types/express-serve-static-core': 4.19.0 + '@types/express-serve-static-core': 4.19.3 '@types/qs': 6.9.15 '@types/serve-static': 1.15.7 '@types/glob@7.2.0': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 20.12.8 + '@types/node': 20.14.0 '@types/http-errors@2.0.4': {} @@ -925,7 +921,7 @@ snapshots: '@types/minimatch@5.1.2': {} - '@types/node@20.12.8': + '@types/node@20.14.0': dependencies: undici-types: 5.26.5 @@ -936,12 +932,12 @@ snapshots: '@types/send@0.17.4': dependencies: '@types/mime': 1.3.5 - '@types/node': 20.12.8 + '@types/node': 20.14.0 '@types/serve-static@1.15.7': dependencies: '@types/http-errors': 2.0.4 - '@types/node': 20.12.8 + '@types/node': 20.14.0 '@types/send': 0.17.4 accepts@1.3.8: @@ -970,7 +966,7 @@ snapshots: dependencies: chalk: 4.1.2 char-spinner: 1.0.1 - cli-table3: 0.6.4 + cli-table3: 0.6.5 color-support: 1.1.3 cross-argv: 2.0.0 form-data: 4.0.0 @@ -988,7 +984,7 @@ snapshots: progress: 2.0.3 reinterval: 1.1.0 retimer: 3.0.0 - semver: 7.6.0 + semver: 7.6.2 subarg: 1.0.0 timestring: 6.0.0 @@ -1018,9 +1014,9 @@ snapshots: balanced-match: 1.0.2 concat-map: 0.0.1 - braces@3.0.2: + braces@3.0.3: dependencies: - fill-range: 7.0.1 + fill-range: 7.1.1 buffer@5.7.1: dependencies: @@ -1046,7 +1042,7 @@ snapshots: clean-stack@2.2.0: {} - cli-table3@0.6.4: + cli-table3@0.6.5: dependencies: string-width: 4.2.3 optionalDependencies: @@ -1169,13 +1165,13 @@ snapshots: '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 - micromatch: 4.0.5 + micromatch: 4.0.7 fastq@1.17.1: dependencies: reusify: 1.0.4 - fill-range@7.0.1: + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -1329,10 +1325,6 @@ snapshots: lodash.flatten@4.4.0: {} - lru-cache@6.0.0: - dependencies: - yallist: 4.0.0 - manage-path@2.0.0: {} media-typer@0.3.0: {} @@ -1343,9 +1335,9 @@ snapshots: methods@1.1.2: {} - micromatch@4.0.5: + micromatch@4.0.7: dependencies: - braces: 3.0.2 + braces: 3.0.3 picomatch: 2.3.1 mime-db@1.52.0: {} @@ -1398,7 +1390,7 @@ snapshots: picomatch@2.3.1: {} - poolifier@4.0.1: {} + poolifier@4.0.13: {} pretty-bytes@5.6.0: {} @@ -1444,26 +1436,26 @@ snapshots: dependencies: del: 5.1.0 - rollup@4.17.2: + rollup@4.18.0: dependencies: '@types/estree': 1.0.5 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.17.2 - '@rollup/rollup-android-arm64': 4.17.2 - '@rollup/rollup-darwin-arm64': 4.17.2 - '@rollup/rollup-darwin-x64': 4.17.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.17.2 - '@rollup/rollup-linux-arm-musleabihf': 4.17.2 - '@rollup/rollup-linux-arm64-gnu': 4.17.2 - '@rollup/rollup-linux-arm64-musl': 4.17.2 - '@rollup/rollup-linux-powerpc64le-gnu': 4.17.2 - '@rollup/rollup-linux-riscv64-gnu': 4.17.2 - '@rollup/rollup-linux-s390x-gnu': 4.17.2 - '@rollup/rollup-linux-x64-gnu': 4.17.2 - '@rollup/rollup-linux-x64-musl': 4.17.2 - '@rollup/rollup-win32-arm64-msvc': 4.17.2 - '@rollup/rollup-win32-ia32-msvc': 4.17.2 - '@rollup/rollup-win32-x64-msvc': 4.17.2 + '@rollup/rollup-android-arm-eabi': 4.18.0 + '@rollup/rollup-android-arm64': 4.18.0 + '@rollup/rollup-darwin-arm64': 4.18.0 + '@rollup/rollup-darwin-x64': 4.18.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.18.0 + '@rollup/rollup-linux-arm-musleabihf': 4.18.0 + '@rollup/rollup-linux-arm64-gnu': 4.18.0 + '@rollup/rollup-linux-arm64-musl': 4.18.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.18.0 + '@rollup/rollup-linux-riscv64-gnu': 4.18.0 + '@rollup/rollup-linux-s390x-gnu': 4.18.0 + '@rollup/rollup-linux-x64-gnu': 4.18.0 + '@rollup/rollup-linux-x64-musl': 4.18.0 + '@rollup/rollup-win32-arm64-msvc': 4.18.0 + '@rollup/rollup-win32-ia32-msvc': 4.18.0 + '@rollup/rollup-win32-x64-msvc': 4.18.0 fsevents: 2.3.3 run-parallel@1.2.0: @@ -1474,9 +1466,7 @@ snapshots: safer-buffer@2.1.2: {} - semver@7.6.0: - dependencies: - lru-cache: 6.0.0 + semver@7.6.2: {} send@0.18.0: dependencies: @@ -1577,5 +1567,3 @@ snapshots: vary@1.1.2: {} wrappy@1.0.2: {} - - yallist@4.0.0: {} diff --git a/examples/typescript/http-server-pool/express-hybrid/rollup.config.ts b/examples/typescript/http-server-pool/express-hybrid/rollup.config.ts index 9c29f004..cd2a4a98 100644 --- a/examples/typescript/http-server-pool/express-hybrid/rollup.config.ts +++ b/examples/typescript/http-server-pool/express-hybrid/rollup.config.ts @@ -6,7 +6,7 @@ export default defineConfig({ input: [ './src/main.ts', './src/express-worker.ts', - './src/request-handler-worker.ts' + './src/request-handler-worker.ts', ], strictDeprecations: true, output: [ @@ -15,19 +15,19 @@ export default defineConfig({ dir: './dist', sourcemap: true, entryFileNames: '[name].cjs', - chunkFileNames: '[name]-[hash].cjs' + chunkFileNames: '[name]-[hash].cjs', }, { format: 'esm', dir: './dist', - sourcemap: true - } + sourcemap: true, + }, ], external: ['express', /^node:*/, 'poolifier'], plugins: [ typescript(), del({ - targets: ['./dist/*'] - }) - ] + targets: ['./dist/*'], + }), + ], }) diff --git a/examples/typescript/http-server-pool/express-hybrid/src/express-worker.ts b/examples/typescript/http-server-pool/express-hybrid/src/express-worker.ts index 7ba9f374..2089b3ef 100644 --- a/examples/typescript/http-server-pool/express-hybrid/src/express-worker.ts +++ b/examples/typescript/http-server-pool/express-hybrid/src/express-worker.ts @@ -5,15 +5,15 @@ import express, { type Express, type Request, type Response } from 'express' import { availableParallelism, ClusterWorker, - DynamicThreadPool + DynamicThreadPool, } from 'poolifier' -import { - type ClusterWorkerData, - type ClusterWorkerResponse, - type DataPayload, - type ThreadWorkerData, - type ThreadWorkerResponse +import type { + ClusterWorkerData, + ClusterWorkerResponse, + DataPayload, + ThreadWorkerData, + ThreadWorkerResponse, } from './types.js' const emptyFunction = (): void => { @@ -21,24 +21,25 @@ const emptyFunction = (): void => { } class ExpressWorker extends ClusterWorker< -ClusterWorkerData, -ClusterWorkerResponse + ClusterWorkerData, + ClusterWorkerResponse > { private static server: Server private static requestHandlerPool: DynamicThreadPool< - ThreadWorkerData, - ThreadWorkerResponse + ThreadWorkerData, + ThreadWorkerResponse > private static readonly startExpress = ( workerData?: ClusterWorkerData ): ClusterWorkerResponse => { const { port, workerFile, minWorkers, maxWorkers, ...poolOptions } = + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion workerData! ExpressWorker.requestHandlerPool = new DynamicThreadPool< - ThreadWorkerData, - ThreadWorkerResponse + ThreadWorkerData, + ThreadWorkerResponse >( minWorkers ?? 1, maxWorkers ?? availableParallelism(), @@ -63,7 +64,7 @@ ClusterWorkerResponse application.get('/api/factorial/:number', (req: Request, res: Response) => { const { number } = req.params ExpressWorker.requestHandlerPool - .execute({ data: { number: parseInt(number) } }, 'factorial') + .execute({ data: { number: Number.parseInt(number) } }, 'factorial') .then(response => { return res.send(response.data).end() }) @@ -74,12 +75,12 @@ ClusterWorkerResponse ExpressWorker.server = application.listen(port, () => { listenerPort = (ExpressWorker.server.address() as AddressInfo).port console.info( - `⚡️[express server]: Express server is started in cluster worker at http://localhost:${listenerPort}/` + `⚡️[express server]: Express server is started in cluster worker at http://localhost:${listenerPort.toString()}/` ) }) return { status: true, - port: listenerPort ?? port + port: listenerPort ?? port, } } @@ -88,7 +89,7 @@ ClusterWorkerResponse killHandler: async () => { await ExpressWorker.requestHandlerPool.destroy() ExpressWorker.server.close() - } + }, }) } } diff --git a/examples/typescript/http-server-pool/express-hybrid/src/main.ts b/examples/typescript/http-server-pool/express-hybrid/src/main.ts index 69a329b6..d7b6c89d 100644 --- a/examples/typescript/http-server-pool/express-hybrid/src/main.ts +++ b/examples/typescript/http-server-pool/express-hybrid/src/main.ts @@ -31,16 +31,17 @@ const pool = new FixedClusterPool( workerFile: requestHandlerWorkerFile, enableTasksQueue: true, tasksQueueOptions: { - concurrency: 8 + concurrency: 8, }, errorHandler: (e: Error) => { console.error('Thread worker error:', e) - } + }, }) .then(response => { if (response.status) { console.info( - `Express is listening in cluster worker on port ${response.port}` + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + `Express is listening in cluster worker on port ${response.port?.toString()}` ) } return undefined @@ -51,6 +52,6 @@ const pool = new FixedClusterPool( }, errorHandler: (e: Error) => { console.error('Cluster worker error:', e) - } + }, } ) diff --git a/examples/typescript/http-server-pool/express-hybrid/src/request-handler-worker.ts b/examples/typescript/http-server-pool/express-hybrid/src/request-handler-worker.ts index b7ff8b16..5297de12 100644 --- a/examples/typescript/http-server-pool/express-hybrid/src/request-handler-worker.ts +++ b/examples/typescript/http-server-pool/express-hybrid/src/request-handler-worker.ts @@ -1,9 +1,9 @@ import { ThreadWorker } from 'poolifier' -import { - type DataPayload, - type ThreadWorkerData, - type ThreadWorkerResponse +import type { + DataPayload, + ThreadWorkerData, + ThreadWorkerResponse, } from './types.js' class RequestHandlerWorker< @@ -32,16 +32,17 @@ class RequestHandlerWorker< return { data: { number: RequestHandlerWorker.factorial( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion workerData!.data.number! - ).toString() - } + ).toString(), + }, } as unknown as Response - } + }, }) } } export const requestHandlerWorker = new RequestHandlerWorker< -ThreadWorkerData, -ThreadWorkerResponse + ThreadWorkerData, + ThreadWorkerResponse >() diff --git a/examples/typescript/http-server-pool/express-worker_threads/package.json b/examples/typescript/http-server-pool/express-worker_threads/package.json index a6ba0f5f..4b2b9989 100644 --- a/examples/typescript/http-server-pool/express-worker_threads/package.json +++ b/examples/typescript/http-server-pool/express-worker_threads/package.json @@ -6,10 +6,10 @@ "main": "dist/main.js", "type": "module", "volta": { - "node": "22.0.0", - "pnpm": "9.0.6" + "node": "22.2.0", + "pnpm": "9.1.4" }, - "packageManager": "pnpm@9.0.6", + "packageManager": "pnpm@9.1.4", "scripts": { "build": "pnpm build:clean && tsc", "build:clean": "tsc --build --clean", @@ -23,11 +23,11 @@ "license": "ISC", "dependencies": { "express": "^4.19.2", - "poolifier": "^4.0.1" + "poolifier": "^4.0.13" }, "devDependencies": { "@types/express": "^4.17.21", - "@types/node": "^20.12.8", + "@types/node": "^20.14.0", "autocannon": "^7.15.0", "typescript": "^5.4.5" } diff --git a/examples/typescript/http-server-pool/express-worker_threads/pnpm-lock.yaml b/examples/typescript/http-server-pool/express-worker_threads/pnpm-lock.yaml index 0fce5143..2571c2ca 100644 --- a/examples/typescript/http-server-pool/express-worker_threads/pnpm-lock.yaml +++ b/examples/typescript/http-server-pool/express-worker_threads/pnpm-lock.yaml @@ -12,15 +12,15 @@ importers: specifier: ^4.19.2 version: 4.19.2 poolifier: - specifier: ^4.0.1 - version: 4.0.1 + specifier: ^4.0.13 + version: 4.0.13 devDependencies: '@types/express': specifier: ^4.17.21 version: 4.17.21 '@types/node': - specifier: ^20.12.8 - version: 20.12.8 + specifier: ^20.14.0 + version: 20.14.0 autocannon: specifier: ^7.15.0 version: 7.15.0 @@ -43,8 +43,8 @@ packages: '@types/connect@3.4.38': resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} - '@types/express-serve-static-core@4.19.0': - resolution: {integrity: sha512-bGyep3JqPCRry1wq+O5n7oiBgGWmeIJXPjXXCo8EK0u8duZGSYar7cGqd3ML2JUsLGeB7fmc06KYo9fLGWqPvQ==} + '@types/express-serve-static-core@4.19.3': + resolution: {integrity: sha512-KOzM7MhcBFlmnlr/fzISFF5vGWVSvN6fTd4T+ExOt08bA/dA5kpSzY52nMsI1KDFmUREpJelPYyuslLRSjjgCg==} '@types/express@4.17.21': resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} @@ -55,8 +55,8 @@ packages: '@types/mime@1.3.5': resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} - '@types/node@20.12.8': - resolution: {integrity: sha512-NU0rJLJnshZWdE/097cdCBbyW1h4hEg0xpovcoAQYHl8dnEyp/NAOiE45pvc+Bd1Dt+2r94v2eGFpQJ4R7g+2w==} + '@types/node@20.14.0': + resolution: {integrity: sha512-5cHBxFGJx6L4s56Bubp4fglrEpmyJypsqI6RgzMfBHWUJQGWAAi8cWcgetEbZXHYXo9C2Fa4EEds/uSyS4cxmA==} '@types/qs@6.9.15': resolution: {integrity: sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==} @@ -117,8 +117,8 @@ packages: char-spinner@1.0.1: resolution: {integrity: sha512-acv43vqJ0+N0rD+Uw3pDHSxP30FHrywu2NO6/wBaHChJIizpDeBUd6NjqhNhy9LGaEAhZAXn46QzmlAvIWd16g==} - cli-table3@0.6.4: - resolution: {integrity: sha512-Lm3L0p+/npIQWNIiyF/nAn7T5dnOwR3xNTHXYEBFBFVPXzCVNZ5lqEC/1eo/EVfpDsQ1I+TX4ORPQgp+UI0CRw==} + cli-table3@0.6.5: + resolution: {integrity: sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==} engines: {node: 10.* || >= 12.*} color-convert@2.0.1: @@ -299,10 +299,6 @@ packages: lodash.flatten@4.4.0: resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==} - lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - manage-path@2.0.0: resolution: {integrity: sha512-NJhyB+PJYTpxhxZJ3lecIGgh4kwIY2RAh44XvAz9UlqthlQwtPBf62uBVR8XaD8CRuSjQ6TnZH2lNJkbLPZM2A==} @@ -364,8 +360,8 @@ packages: path-to-regexp@0.1.7: resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} - poolifier@4.0.1: - resolution: {integrity: sha512-1izVxQOC3yonTN1I51tualsPfZ0iUN+r5zaKY/+vEWIa0cUJMPgi1hN86DL4kwCTwr65JZ42ZrxnQWRmdnzRpA==} + poolifier@4.0.13: + resolution: {integrity: sha512-GPITJo3LZvZXGNDWn6eDpOJ+F5+rq4tvyoXFQJfyJ92w0qr4evjoOX9hymwMGmv8TuifFMIBmgCdcTvoxRdMgA==} engines: {node: '>=18.0.0', pnpm: '>=9.0.0'} pretty-bytes@5.6.0: @@ -404,8 +400,8 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - semver@7.6.0: - resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} + semver@7.6.2: + resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} engines: {node: '>=10'} hasBin: true @@ -486,9 +482,6 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} - yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - snapshots: '@assemblyscript/loader@0.19.23': {} @@ -499,15 +492,15 @@ snapshots: '@types/body-parser@1.19.5': dependencies: '@types/connect': 3.4.38 - '@types/node': 20.12.8 + '@types/node': 20.14.0 '@types/connect@3.4.38': dependencies: - '@types/node': 20.12.8 + '@types/node': 20.14.0 - '@types/express-serve-static-core@4.19.0': + '@types/express-serve-static-core@4.19.3': dependencies: - '@types/node': 20.12.8 + '@types/node': 20.14.0 '@types/qs': 6.9.15 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 @@ -515,7 +508,7 @@ snapshots: '@types/express@4.17.21': dependencies: '@types/body-parser': 1.19.5 - '@types/express-serve-static-core': 4.19.0 + '@types/express-serve-static-core': 4.19.3 '@types/qs': 6.9.15 '@types/serve-static': 1.15.7 @@ -523,7 +516,7 @@ snapshots: '@types/mime@1.3.5': {} - '@types/node@20.12.8': + '@types/node@20.14.0': dependencies: undici-types: 5.26.5 @@ -534,12 +527,12 @@ snapshots: '@types/send@0.17.4': dependencies: '@types/mime': 1.3.5 - '@types/node': 20.12.8 + '@types/node': 20.14.0 '@types/serve-static@1.15.7': dependencies: '@types/http-errors': 2.0.4 - '@types/node': 20.12.8 + '@types/node': 20.14.0 '@types/send': 0.17.4 accepts@1.3.8: @@ -561,7 +554,7 @@ snapshots: dependencies: chalk: 4.1.2 char-spinner: 1.0.1 - cli-table3: 0.6.4 + cli-table3: 0.6.5 color-support: 1.1.3 cross-argv: 2.0.0 form-data: 4.0.0 @@ -579,7 +572,7 @@ snapshots: progress: 2.0.3 reinterval: 1.1.0 retimer: 3.0.0 - semver: 7.6.0 + semver: 7.6.2 subarg: 1.0.0 timestring: 6.0.0 @@ -624,7 +617,7 @@ snapshots: char-spinner@1.0.1: {} - cli-table3@0.6.4: + cli-table3@0.6.5: dependencies: string-width: 4.2.3 optionalDependencies: @@ -816,10 +809,6 @@ snapshots: lodash.flatten@4.4.0: {} - lru-cache@6.0.0: - dependencies: - yallist: 4.0.0 - manage-path@2.0.0: {} media-typer@0.3.0: {} @@ -858,7 +847,7 @@ snapshots: path-to-regexp@0.1.7: {} - poolifier@4.0.1: {} + poolifier@4.0.13: {} pretty-bytes@5.6.0: {} @@ -890,9 +879,7 @@ snapshots: safer-buffer@2.1.2: {} - semver@7.6.0: - dependencies: - lru-cache: 6.0.0 + semver@7.6.2: {} send@0.18.0: dependencies: @@ -981,5 +968,3 @@ snapshots: uuid@8.3.2: {} vary@1.1.2: {} - - yallist@4.0.0: {} diff --git a/examples/typescript/http-server-pool/express-worker_threads/src/main.ts b/examples/typescript/http-server-pool/express-worker_threads/src/main.ts index fc0f2d84..61514364 100644 --- a/examples/typescript/http-server-pool/express-worker_threads/src/main.ts +++ b/examples/typescript/http-server-pool/express-worker_threads/src/main.ts @@ -33,7 +33,7 @@ expressApp.all('/api/echo', (req: Request, res: Response) => { expressApp.get('/api/factorial/:number', (req: Request, res: Response) => { const { number } = req.params requestHandlerPool - .execute({ body: { number: parseInt(number) } }, 'factorial') + .execute({ body: { number: Number.parseInt(number) } }, 'factorial') .then(response => { return res.send(response.body).end() }) @@ -43,7 +43,7 @@ expressApp.get('/api/factorial/:number', (req: Request, res: Response) => { try { expressApp.listen(port, () => { console.info( - `⚡️[express server]: Express server is started at http://localhost:${port}/` + `⚡️[express server]: Express server is started at http://localhost:${port.toString()}/` ) }) } catch (err) { diff --git a/examples/typescript/http-server-pool/express-worker_threads/src/pool.ts b/examples/typescript/http-server-pool/express-worker_threads/src/pool.ts index 98ae657d..29bf4ef7 100644 --- a/examples/typescript/http-server-pool/express-worker_threads/src/pool.ts +++ b/examples/typescript/http-server-pool/express-worker_threads/src/pool.ts @@ -3,11 +3,7 @@ import { fileURLToPath } from 'node:url' import { availableParallelism, DynamicThreadPool } from 'poolifier' -import { - type BodyPayload, - type WorkerData, - type WorkerResponse -} from './types.js' +import type { BodyPayload, WorkerData, WorkerResponse } from './types.js' const workerFile = join( dirname(fileURLToPath(import.meta.url)), @@ -15,14 +11,14 @@ const workerFile = join( ) export const requestHandlerPool = new DynamicThreadPool< -WorkerData, -WorkerResponse + WorkerData, + WorkerResponse >(1, availableParallelism(), workerFile, { enableTasksQueue: true, tasksQueueOptions: { - concurrency: 8 + concurrency: 8, }, errorHandler: (e: Error) => { console.error('Thread worker error:', e) - } + }, }) diff --git a/examples/typescript/http-server-pool/express-worker_threads/src/worker.ts b/examples/typescript/http-server-pool/express-worker_threads/src/worker.ts index 18e5c8a3..c5819f83 100644 --- a/examples/typescript/http-server-pool/express-worker_threads/src/worker.ts +++ b/examples/typescript/http-server-pool/express-worker_threads/src/worker.ts @@ -1,10 +1,6 @@ import { ThreadWorker } from 'poolifier' -import { - type BodyPayload, - type WorkerData, - type WorkerResponse -} from './types.js' +import type { BodyPayload, WorkerData, WorkerResponse } from './types.js' class RequestHandlerWorker< Data extends WorkerData, @@ -32,16 +28,17 @@ class RequestHandlerWorker< return { body: { number: RequestHandlerWorker.factorial( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion workerData!.body.number! - ).toString() - } + ).toString(), + }, } as unknown as Response - } + }, }) } } export const requestHandlerWorker = new RequestHandlerWorker< -WorkerData, -WorkerResponse + WorkerData, + WorkerResponse >() diff --git a/examples/typescript/http-server-pool/fastify-cluster/package.json b/examples/typescript/http-server-pool/fastify-cluster/package.json index 38b2f975..b2d1f776 100644 --- a/examples/typescript/http-server-pool/fastify-cluster/package.json +++ b/examples/typescript/http-server-pool/fastify-cluster/package.json @@ -6,10 +6,10 @@ "main": "dist/main.js", "type": "module", "volta": { - "node": "22.0.0", - "pnpm": "9.0.6" + "node": "22.2.0", + "pnpm": "9.1.4" }, - "packageManager": "pnpm@9.0.6", + "packageManager": "pnpm@9.1.4", "scripts": { "build": "rollup --config --configPlugin typescript", "start": "node --enable-source-maps dist/main.cjs", @@ -22,14 +22,14 @@ "author": "", "license": "ISC", "dependencies": { - "fastify": "^4.26.2", - "poolifier": "^4.0.1" + "fastify": "^4.27.0", + "poolifier": "^4.0.13" }, "devDependencies": { "@rollup/plugin-typescript": "^11.1.6", - "@types/node": "^20.12.8", + "@types/node": "^20.14.0", "autocannon": "^7.15.0", - "rollup": "^4.17.2", + "rollup": "^4.18.0", "rollup-plugin-delete": "^2.0.0", "tslib": "^2.6.2", "typescript": "^5.4.5" diff --git a/examples/typescript/http-server-pool/fastify-cluster/pnpm-lock.yaml b/examples/typescript/http-server-pool/fastify-cluster/pnpm-lock.yaml index 52868773..cedd6f14 100644 --- a/examples/typescript/http-server-pool/fastify-cluster/pnpm-lock.yaml +++ b/examples/typescript/http-server-pool/fastify-cluster/pnpm-lock.yaml @@ -9,24 +9,24 @@ importers: .: dependencies: fastify: - specifier: ^4.26.2 - version: 4.26.2 + specifier: ^4.27.0 + version: 4.27.0 poolifier: - specifier: ^4.0.1 - version: 4.0.1 + specifier: ^4.0.13 + version: 4.0.13 devDependencies: '@rollup/plugin-typescript': specifier: ^11.1.6 - version: 11.1.6(rollup@4.17.2)(tslib@2.6.2)(typescript@5.4.5) + version: 11.1.6(rollup@4.18.0)(tslib@2.6.2)(typescript@5.4.5) '@types/node': - specifier: ^20.12.8 - version: 20.12.8 + specifier: ^20.14.0 + version: 20.14.0 autocannon: specifier: ^7.15.0 version: 7.15.0 rollup: - specifier: ^4.17.2 - version: 4.17.2 + specifier: ^4.18.0 + version: 4.18.0 rollup-plugin-delete: specifier: ^2.0.0 version: 2.0.0 @@ -92,83 +92,83 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.17.2': - resolution: {integrity: sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==} + '@rollup/rollup-android-arm-eabi@4.18.0': + resolution: {integrity: sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.17.2': - resolution: {integrity: sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==} + '@rollup/rollup-android-arm64@4.18.0': + resolution: {integrity: sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.17.2': - resolution: {integrity: sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==} + '@rollup/rollup-darwin-arm64@4.18.0': + resolution: {integrity: sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.17.2': - resolution: {integrity: sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==} + '@rollup/rollup-darwin-x64@4.18.0': + resolution: {integrity: sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==} cpu: [x64] os: [darwin] - '@rollup/rollup-linux-arm-gnueabihf@4.17.2': - resolution: {integrity: sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==} + '@rollup/rollup-linux-arm-gnueabihf@4.18.0': + resolution: {integrity: sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.17.2': - resolution: {integrity: sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==} + '@rollup/rollup-linux-arm-musleabihf@4.18.0': + resolution: {integrity: sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.17.2': - resolution: {integrity: sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==} + '@rollup/rollup-linux-arm64-gnu@4.18.0': + resolution: {integrity: sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.17.2': - resolution: {integrity: sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==} + '@rollup/rollup-linux-arm64-musl@4.18.0': + resolution: {integrity: sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.17.2': - resolution: {integrity: sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==} + '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': + resolution: {integrity: sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.17.2': - resolution: {integrity: sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==} + '@rollup/rollup-linux-riscv64-gnu@4.18.0': + resolution: {integrity: sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.17.2': - resolution: {integrity: sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==} + '@rollup/rollup-linux-s390x-gnu@4.18.0': + resolution: {integrity: sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.17.2': - resolution: {integrity: sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==} + '@rollup/rollup-linux-x64-gnu@4.18.0': + resolution: {integrity: sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.17.2': - resolution: {integrity: sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==} + '@rollup/rollup-linux-x64-musl@4.18.0': + resolution: {integrity: sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.17.2': - resolution: {integrity: sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==} + '@rollup/rollup-win32-arm64-msvc@4.18.0': + resolution: {integrity: sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.17.2': - resolution: {integrity: sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==} + '@rollup/rollup-win32-ia32-msvc@4.18.0': + resolution: {integrity: sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.17.2': - resolution: {integrity: sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==} + '@rollup/rollup-win32-x64-msvc@4.18.0': + resolution: {integrity: sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==} cpu: [x64] os: [win32] @@ -181,8 +181,8 @@ packages: '@types/minimatch@5.1.2': resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} - '@types/node@20.12.8': - resolution: {integrity: sha512-NU0rJLJnshZWdE/097cdCBbyW1h4hEg0xpovcoAQYHl8dnEyp/NAOiE45pvc+Bd1Dt+2r94v2eGFpQJ4R7g+2w==} + '@types/node@20.14.0': + resolution: {integrity: sha512-5cHBxFGJx6L4s56Bubp4fglrEpmyJypsqI6RgzMfBHWUJQGWAAi8cWcgetEbZXHYXo9C2Fa4EEds/uSyS4cxmA==} abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} @@ -211,8 +211,8 @@ packages: ajv: optional: true - ajv@8.13.0: - resolution: {integrity: sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==} + ajv@8.14.0: + resolution: {integrity: sha512-oYs1UUtO97ZO2lJ4bwnWeQW8/zvOIQLGKcvPTsWmvc2SYgBb+upuNS5NxoLaMU4h8Ju3Nbj6Cq8mD2LQoqVKFA==} ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} @@ -222,9 +222,6 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} - archy@1.0.0: - resolution: {integrity: sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==} - array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} @@ -240,8 +237,8 @@ packages: resolution: {integrity: sha512-NaP2rQyA+tcubOJMFv2+oeW9jv2pq/t+LM6BL3cfJic0HEfscEcnWgAyU5YovE/oTHUzAgTliGdLPR+RQAWUbg==} hasBin: true - avvio@8.3.0: - resolution: {integrity: sha512-VBVH0jubFr9LdFASy/vNtm5giTrnbVquWBhT0fyizuNK2rQ7e7ONU2plZQWUNqtE1EmxFEb+kbSkFRkstiaS9Q==} + avvio@8.3.2: + resolution: {integrity: sha512-st8e519GWHa/azv8S87mcJvZs4WsgTBjOw/Ih1CP6u+8SZvcOeAYNG6JbsIrAUUJJ7JfmrnOkR8ipDS+u9SIRQ==} balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -252,8 +249,8 @@ packages: brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} buffer@5.7.1: @@ -273,8 +270,8 @@ packages: resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} engines: {node: '>=6'} - cli-table3@0.6.4: - resolution: {integrity: sha512-Lm3L0p+/npIQWNIiyF/nAn7T5dnOwR3xNTHXYEBFBFVPXzCVNZ5lqEC/1eo/EVfpDsQ1I+TX4ORPQgp+UI0CRw==} + cli-table3@0.6.5: + resolution: {integrity: sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==} engines: {node: 10.* || >= 12.*} color-convert@2.0.1: @@ -302,15 +299,6 @@ packages: cross-argv@2.0.0: resolution: {integrity: sha512-YIaY9TR5Nxeb8SMdtrU8asWVM4jqJDNDYlKV21LxtYcfNJhp1kEsgSa6qXwXgzN0WQWGODps0+TlGp2xQSHwOg==} - debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - del@5.1.0: resolution: {integrity: sha512-wH9xOVHnczo9jN2IW68BabcecVPxacIA3g/7z6vhSU/4stOKQzeCRK0yD0A24WiAAUJmmVpWqrERcTxnLo3AnA==} engines: {node: '>=8'} @@ -350,8 +338,8 @@ packages: resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} engines: {node: '>=8.6.0'} - fast-json-stringify@5.15.0: - resolution: {integrity: sha512-BUEAAyDKb64u+kmkINYfXUUiKjBKerSmVu/dzotfaWSHBxR44JFrOZgkhMO6VxDhDfiuAoi8mx4drd5nvNdA4Q==} + fast-json-stringify@5.16.0: + resolution: {integrity: sha512-A4bg6E15QrkuVO3f0SwIASgzMzR6XC4qTyTqhf3hYXy0iazbAdZKwkE+ox4WgzKyzM6ygvbdq3r134UjOaaAnA==} fast-querystring@1.1.2: resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==} @@ -363,14 +351,14 @@ packages: fast-uri@2.3.0: resolution: {integrity: sha512-eel5UKGn369gGEWOqBShmFJWfq/xSJvsgDzgLYC845GneayWvXBf0lJCBn5qTABfewy1ZDPoaR5OZCP+kssfuw==} - fastify@4.26.2: - resolution: {integrity: sha512-90pjTuPGrfVKtdpLeLzND5nyC4woXZN5VadiNQCicj/iJU4viNHKhsAnb7jmv1vu2IzkLXyBiCzdWuzeXgQ5Ug==} + fastify@4.27.0: + resolution: {integrity: sha512-ci9IXzbigB8dyi0mSy3faa3Bsj0xWAPb9JeT4KRzubdSb6pNhcADRUaXCBml6V1Ss/a05kbtQls5LBmhHydoTA==} fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} find-my-way@8.2.0: @@ -402,6 +390,7 @@ packages: glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported globby@10.0.2: resolution: {integrity: sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==} @@ -447,6 +436,7 @@ packages: inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -500,10 +490,6 @@ packages: lodash.flatten@4.4.0: resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==} - lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - manage-path@2.0.0: resolution: {integrity: sha512-NJhyB+PJYTpxhxZJ3lecIGgh4kwIY2RAh44XvAz9UlqthlQwtPBf62uBVR8XaD8CRuSjQ6TnZH2lNJkbLPZM2A==} @@ -511,8 +497,8 @@ packages: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} - micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + micromatch@4.0.7: + resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} engines: {node: '>=8.6'} mime-db@1.52.0: @@ -529,9 +515,6 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - on-exit-leak-free@2.1.2: resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} engines: {node: '>=14.0.0'} @@ -568,15 +551,15 @@ packages: pino-abstract-transport@1.2.0: resolution: {integrity: sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==} - pino-std-serializers@6.2.2: - resolution: {integrity: sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==} + pino-std-serializers@7.0.0: + resolution: {integrity: sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==} - pino@8.21.0: - resolution: {integrity: sha512-ip4qdzjkAyDDZklUaZkcRFb2iA118H9SgRh8yzTkSQK8HilsOJF7rSY8HoW5+I0M46AZgX/pxbprf2vvzQCE0Q==} + pino@9.1.0: + resolution: {integrity: sha512-qUcgfrlyOtjwhNLdbhoL7NR4NkHjzykAPw0V2QLFbvu/zss29h4NkRnibyFzBrNCbzCOY3WZ9hhKSwfOkNggYA==} hasBin: true - poolifier@4.0.1: - resolution: {integrity: sha512-1izVxQOC3yonTN1I51tualsPfZ0iUN+r5zaKY/+vEWIa0cUJMPgi1hN86DL4kwCTwr65JZ42ZrxnQWRmdnzRpA==} + poolifier@4.0.13: + resolution: {integrity: sha512-GPITJo3LZvZXGNDWn6eDpOJ+F5+rq4tvyoXFQJfyJ92w0qr4evjoOX9hymwMGmv8TuifFMIBmgCdcTvoxRdMgA==} engines: {node: '>=18.0.0', pnpm: '>=9.0.0'} pretty-bytes@5.6.0: @@ -643,14 +626,15 @@ packages: rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true rollup-plugin-delete@2.0.0: resolution: {integrity: sha512-/VpLMtDy+8wwRlDANuYmDa9ss/knGsAgrDhM+tEwB1npHwNu4DYNmDfUL55csse/GHs9Q+SMT/rw9uiaZ3pnzA==} engines: {node: '>=10'} - rollup@4.17.2: - resolution: {integrity: sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==} + rollup@4.18.0: + resolution: {integrity: sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -670,8 +654,8 @@ packages: secure-json-parse@2.7.0: resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} - semver@7.6.0: - resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} + semver@7.6.2: + resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} engines: {node: '>=10'} hasBin: true @@ -682,8 +666,8 @@ packages: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} - sonic-boom@3.8.1: - resolution: {integrity: sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==} + sonic-boom@4.0.1: + resolution: {integrity: sha512-hTSD/6JMLyT4r9zeof6UtuBDpjJ9sO08/nmS5djaA9eozT9oOlNdpXSnzcgj4FTqpk3nkLrs61l4gip9r1HCrQ==} split2@4.2.0: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} @@ -711,8 +695,8 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - thread-stream@2.7.0: - resolution: {integrity: sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw==} + thread-stream@3.0.2: + resolution: {integrity: sha512-cBL4xF2A3lSINV4rD5tyqnKH4z/TgWPvT+NaVhJDSwK962oo/Ye7cHSMbDzwcu7tAE1SfU6Q4XtV6Hucmi6Hlw==} timestring@6.0.0: resolution: {integrity: sha512-wMctrWD2HZZLuIlchlkE2dfXJh7J2KDI9Dwl+2abPYg0mswQHfOAyQW3jJg1pY5VfttSINZuKcXoB3FGypVklA==} @@ -750,9 +734,6 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - snapshots: '@assemblyscript/loader@0.19.23': {} @@ -762,15 +743,15 @@ snapshots: '@fastify/ajv-compiler@3.5.0': dependencies: - ajv: 8.13.0 - ajv-formats: 2.1.1(ajv@8.13.0) + ajv: 8.14.0 + ajv-formats: 2.1.1(ajv@8.14.0) fast-uri: 2.3.0 '@fastify/error@3.4.1': {} '@fastify/fast-json-stringify-compiler@4.3.0': dependencies: - fast-json-stringify: 5.15.0 + fast-json-stringify: 5.16.0 '@fastify/merge-json-schemas@0.1.1': dependencies: @@ -788,69 +769,69 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 - '@rollup/plugin-typescript@11.1.6(rollup@4.17.2)(tslib@2.6.2)(typescript@5.4.5)': + '@rollup/plugin-typescript@11.1.6(rollup@4.18.0)(tslib@2.6.2)(typescript@5.4.5)': dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.17.2) + '@rollup/pluginutils': 5.1.0(rollup@4.18.0) resolve: 1.22.8 typescript: 5.4.5 optionalDependencies: - rollup: 4.17.2 + rollup: 4.18.0 tslib: 2.6.2 - '@rollup/pluginutils@5.1.0(rollup@4.17.2)': + '@rollup/pluginutils@5.1.0(rollup@4.18.0)': dependencies: '@types/estree': 1.0.5 estree-walker: 2.0.2 picomatch: 2.3.1 optionalDependencies: - rollup: 4.17.2 + rollup: 4.18.0 - '@rollup/rollup-android-arm-eabi@4.17.2': + '@rollup/rollup-android-arm-eabi@4.18.0': optional: true - '@rollup/rollup-android-arm64@4.17.2': + '@rollup/rollup-android-arm64@4.18.0': optional: true - '@rollup/rollup-darwin-arm64@4.17.2': + '@rollup/rollup-darwin-arm64@4.18.0': optional: true - '@rollup/rollup-darwin-x64@4.17.2': + '@rollup/rollup-darwin-x64@4.18.0': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.17.2': + '@rollup/rollup-linux-arm-gnueabihf@4.18.0': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.17.2': + '@rollup/rollup-linux-arm-musleabihf@4.18.0': optional: true - '@rollup/rollup-linux-arm64-gnu@4.17.2': + '@rollup/rollup-linux-arm64-gnu@4.18.0': optional: true - '@rollup/rollup-linux-arm64-musl@4.17.2': + '@rollup/rollup-linux-arm64-musl@4.18.0': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.17.2': + '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.17.2': + '@rollup/rollup-linux-riscv64-gnu@4.18.0': optional: true - '@rollup/rollup-linux-s390x-gnu@4.17.2': + '@rollup/rollup-linux-s390x-gnu@4.18.0': optional: true - '@rollup/rollup-linux-x64-gnu@4.17.2': + '@rollup/rollup-linux-x64-gnu@4.18.0': optional: true - '@rollup/rollup-linux-x64-musl@4.17.2': + '@rollup/rollup-linux-x64-musl@4.18.0': optional: true - '@rollup/rollup-win32-arm64-msvc@4.17.2': + '@rollup/rollup-win32-arm64-msvc@4.18.0': optional: true - '@rollup/rollup-win32-ia32-msvc@4.17.2': + '@rollup/rollup-win32-ia32-msvc@4.18.0': optional: true - '@rollup/rollup-win32-x64-msvc@4.17.2': + '@rollup/rollup-win32-x64-msvc@4.18.0': optional: true '@types/estree@1.0.5': {} @@ -858,11 +839,11 @@ snapshots: '@types/glob@7.2.0': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 20.12.8 + '@types/node': 20.14.0 '@types/minimatch@5.1.2': {} - '@types/node@20.12.8': + '@types/node@20.14.0': dependencies: undici-types: 5.26.5 @@ -877,15 +858,15 @@ snapshots: clean-stack: 2.2.0 indent-string: 4.0.0 - ajv-formats@2.1.1(ajv@8.13.0): + ajv-formats@2.1.1(ajv@8.14.0): optionalDependencies: - ajv: 8.13.0 + ajv: 8.14.0 - ajv-formats@3.0.1(ajv@8.13.0): + ajv-formats@3.0.1(ajv@8.14.0): optionalDependencies: - ajv: 8.13.0 + ajv: 8.14.0 - ajv@8.13.0: + ajv@8.14.0: dependencies: fast-deep-equal: 3.1.3 json-schema-traverse: 1.0.0 @@ -898,8 +879,6 @@ snapshots: dependencies: color-convert: 2.0.1 - archy@1.0.0: {} - array-union@2.1.0: {} asynckit@0.4.0: {} @@ -910,7 +889,7 @@ snapshots: dependencies: chalk: 4.1.2 char-spinner: 1.0.1 - cli-table3: 0.6.4 + cli-table3: 0.6.5 color-support: 1.1.3 cross-argv: 2.0.0 form-data: 4.0.0 @@ -928,18 +907,14 @@ snapshots: progress: 2.0.3 reinterval: 1.1.0 retimer: 3.0.0 - semver: 7.6.0 + semver: 7.6.2 subarg: 1.0.0 timestring: 6.0.0 - avvio@8.3.0: + avvio@8.3.2: dependencies: '@fastify/error': 3.4.1 - archy: 1.0.0 - debug: 4.3.4 fastq: 1.17.1 - transitivePeerDependencies: - - supports-color balanced-match@1.0.2: {} @@ -950,9 +925,9 @@ snapshots: balanced-match: 1.0.2 concat-map: 0.0.1 - braces@3.0.2: + braces@3.0.3: dependencies: - fill-range: 7.0.1 + fill-range: 7.1.1 buffer@5.7.1: dependencies: @@ -973,7 +948,7 @@ snapshots: clean-stack@2.2.0: {} - cli-table3@0.6.4: + cli-table3@0.6.5: dependencies: string-width: 4.2.3 optionalDependencies: @@ -997,10 +972,6 @@ snapshots: cross-argv@2.0.0: {} - debug@4.3.4: - dependencies: - ms: 2.1.2 - del@5.1.0: dependencies: globby: 10.0.2 @@ -1038,13 +1009,13 @@ snapshots: '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 - micromatch: 4.0.5 + micromatch: 4.0.7 - fast-json-stringify@5.15.0: + fast-json-stringify@5.16.0: dependencies: '@fastify/merge-json-schemas': 0.1.1 - ajv: 8.13.0 - ajv-formats: 3.0.1(ajv@8.13.0) + ajv: 8.14.0 + ajv-formats: 3.0.1(ajv@8.14.0) fast-deep-equal: 3.1.3 fast-uri: 2.3.0 json-schema-ref-resolver: 1.0.1 @@ -1058,32 +1029,30 @@ snapshots: fast-uri@2.3.0: {} - fastify@4.26.2: + fastify@4.27.0: dependencies: '@fastify/ajv-compiler': 3.5.0 '@fastify/error': 3.4.1 '@fastify/fast-json-stringify-compiler': 4.3.0 abstract-logging: 2.0.1 - avvio: 8.3.0 + avvio: 8.3.2 fast-content-type-parse: 1.1.0 - fast-json-stringify: 5.15.0 + fast-json-stringify: 5.16.0 find-my-way: 8.2.0 light-my-request: 5.13.0 - pino: 8.21.0 + pino: 9.1.0 process-warning: 3.0.0 proxy-addr: 2.0.7 rfdc: 1.3.1 secure-json-parse: 2.7.0 - semver: 7.6.0 + semver: 7.6.2 toad-cache: 3.7.0 - transitivePeerDependencies: - - supports-color fastq@1.17.1: dependencies: reusify: 1.0.4 - fill-range@7.0.1: + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -1209,17 +1178,13 @@ snapshots: lodash.flatten@4.4.0: {} - lru-cache@6.0.0: - dependencies: - yallist: 4.0.0 - manage-path@2.0.0: {} merge2@1.4.1: {} - micromatch@4.0.5: + micromatch@4.0.7: dependencies: - braces: 3.0.2 + braces: 3.0.3 picomatch: 2.3.1 mime-db@1.52.0: {} @@ -1234,8 +1199,6 @@ snapshots: minimist@1.2.8: {} - ms@2.1.2: {} - on-exit-leak-free@2.1.2: {} on-net-listen@1.1.2: {} @@ -1263,23 +1226,23 @@ snapshots: readable-stream: 4.5.2 split2: 4.2.0 - pino-std-serializers@6.2.2: {} + pino-std-serializers@7.0.0: {} - pino@8.21.0: + pino@9.1.0: dependencies: atomic-sleep: 1.0.0 fast-redact: 3.5.0 on-exit-leak-free: 2.1.2 pino-abstract-transport: 1.2.0 - pino-std-serializers: 6.2.2 + pino-std-serializers: 7.0.0 process-warning: 3.0.0 quick-format-unescaped: 4.0.4 real-require: 0.2.0 safe-stable-stringify: 2.4.3 - sonic-boom: 3.8.1 - thread-stream: 2.7.0 + sonic-boom: 4.0.1 + thread-stream: 3.0.2 - poolifier@4.0.1: {} + poolifier@4.0.13: {} pretty-bytes@5.6.0: {} @@ -1336,26 +1299,26 @@ snapshots: dependencies: del: 5.1.0 - rollup@4.17.2: + rollup@4.18.0: dependencies: '@types/estree': 1.0.5 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.17.2 - '@rollup/rollup-android-arm64': 4.17.2 - '@rollup/rollup-darwin-arm64': 4.17.2 - '@rollup/rollup-darwin-x64': 4.17.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.17.2 - '@rollup/rollup-linux-arm-musleabihf': 4.17.2 - '@rollup/rollup-linux-arm64-gnu': 4.17.2 - '@rollup/rollup-linux-arm64-musl': 4.17.2 - '@rollup/rollup-linux-powerpc64le-gnu': 4.17.2 - '@rollup/rollup-linux-riscv64-gnu': 4.17.2 - '@rollup/rollup-linux-s390x-gnu': 4.17.2 - '@rollup/rollup-linux-x64-gnu': 4.17.2 - '@rollup/rollup-linux-x64-musl': 4.17.2 - '@rollup/rollup-win32-arm64-msvc': 4.17.2 - '@rollup/rollup-win32-ia32-msvc': 4.17.2 - '@rollup/rollup-win32-x64-msvc': 4.17.2 + '@rollup/rollup-android-arm-eabi': 4.18.0 + '@rollup/rollup-android-arm64': 4.18.0 + '@rollup/rollup-darwin-arm64': 4.18.0 + '@rollup/rollup-darwin-x64': 4.18.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.18.0 + '@rollup/rollup-linux-arm-musleabihf': 4.18.0 + '@rollup/rollup-linux-arm64-gnu': 4.18.0 + '@rollup/rollup-linux-arm64-musl': 4.18.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.18.0 + '@rollup/rollup-linux-riscv64-gnu': 4.18.0 + '@rollup/rollup-linux-s390x-gnu': 4.18.0 + '@rollup/rollup-linux-x64-gnu': 4.18.0 + '@rollup/rollup-linux-x64-musl': 4.18.0 + '@rollup/rollup-win32-arm64-msvc': 4.18.0 + '@rollup/rollup-win32-ia32-msvc': 4.18.0 + '@rollup/rollup-win32-x64-msvc': 4.18.0 fsevents: 2.3.3 run-parallel@1.2.0: @@ -1372,15 +1335,13 @@ snapshots: secure-json-parse@2.7.0: {} - semver@7.6.0: - dependencies: - lru-cache: 6.0.0 + semver@7.6.2: {} set-cookie-parser@2.6.0: {} slash@3.0.0: {} - sonic-boom@3.8.1: + sonic-boom@4.0.1: dependencies: atomic-sleep: 1.0.0 @@ -1410,7 +1371,7 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - thread-stream@2.7.0: + thread-stream@3.0.2: dependencies: real-require: 0.2.0 @@ -1437,5 +1398,3 @@ snapshots: uuid@8.3.2: {} wrappy@1.0.2: {} - - yallist@4.0.0: {} diff --git a/examples/typescript/http-server-pool/fastify-cluster/rollup.config.ts b/examples/typescript/http-server-pool/fastify-cluster/rollup.config.ts index 5e0a32d4..03cbd852 100644 --- a/examples/typescript/http-server-pool/fastify-cluster/rollup.config.ts +++ b/examples/typescript/http-server-pool/fastify-cluster/rollup.config.ts @@ -11,19 +11,19 @@ export default defineConfig({ dir: './dist', sourcemap: true, entryFileNames: '[name].cjs', - chunkFileNames: '[name]-[hash].cjs' + chunkFileNames: '[name]-[hash].cjs', }, { format: 'esm', dir: './dist', - sourcemap: true - } + sourcemap: true, + }, ], external: ['fastify', /^node:*/, 'poolifier'], plugins: [ typescript(), del({ - targets: ['./dist/*'] - }) - ] + targets: ['./dist/*'], + }), + ], }) diff --git a/examples/typescript/http-server-pool/fastify-cluster/src/main.ts b/examples/typescript/http-server-pool/fastify-cluster/src/main.ts index 541f0017..a548b13d 100644 --- a/examples/typescript/http-server-pool/fastify-cluster/src/main.ts +++ b/examples/typescript/http-server-pool/fastify-cluster/src/main.ts @@ -21,7 +21,8 @@ const pool = new FixedClusterPool( .then(response => { if (response.status) { console.info( - `Fastify is listening in cluster worker on port ${response.port}` + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + `Fastify is listening in cluster worker on port ${response.port?.toString()}` ) } return undefined @@ -32,6 +33,6 @@ const pool = new FixedClusterPool( }, errorHandler: (e: Error) => { console.error('Cluster worker error:', e) - } + }, } ) diff --git a/examples/typescript/http-server-pool/fastify-cluster/src/worker.ts b/examples/typescript/http-server-pool/fastify-cluster/src/worker.ts index e491fa8f..7003e265 100644 --- a/examples/typescript/http-server-pool/fastify-cluster/src/worker.ts +++ b/examples/typescript/http-server-pool/fastify-cluster/src/worker.ts @@ -24,10 +24,11 @@ class FastifyWorker extends ClusterWorker { private static readonly startFastify = async ( workerData?: WorkerData ): Promise => { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const { port } = workerData! FastifyWorker.fastify = Fastify({ - logger: true + logger: true, }) FastifyWorker.fastify.all('/api/echo', request => { @@ -44,7 +45,7 @@ class FastifyWorker extends ClusterWorker { await FastifyWorker.fastify.listen({ port }) return { status: true, - port: (FastifyWorker.fastify.server.address() as AddressInfo).port + port: (FastifyWorker.fastify.server.address() as AddressInfo).port, } } @@ -52,7 +53,7 @@ class FastifyWorker extends ClusterWorker { super(FastifyWorker.startFastify, { killHandler: async () => { await FastifyWorker.fastify.close() - } + }, }) } } diff --git a/examples/typescript/http-server-pool/fastify-hybrid/@types/fastify/index.d.ts b/examples/typescript/http-server-pool/fastify-hybrid/@types/fastify/index.d.ts index 018cac59..166bfd33 100644 --- a/examples/typescript/http-server-pool/fastify-hybrid/@types/fastify/index.d.ts +++ b/examples/typescript/http-server-pool/fastify-hybrid/@types/fastify/index.d.ts @@ -3,10 +3,7 @@ import type { TransferListItem } from 'node:worker_threads' import type * as fastify from 'fastify' import type { DynamicThreadPool } from 'poolifier' -import { - type ThreadWorkerData, - type ThreadWorkerResponse -} from '../../src/types.ts' +import type { ThreadWorkerData, ThreadWorkerResponse } from '../../src/types.ts' declare module 'fastify' { export interface FastifyInstance extends fastify.FastifyInstance { diff --git a/examples/typescript/http-server-pool/fastify-hybrid/package.json b/examples/typescript/http-server-pool/fastify-hybrid/package.json index 98e4635f..5df80bc1 100644 --- a/examples/typescript/http-server-pool/fastify-hybrid/package.json +++ b/examples/typescript/http-server-pool/fastify-hybrid/package.json @@ -6,10 +6,10 @@ "main": "dist/main.js", "type": "module", "volta": { - "node": "22.0.0", - "pnpm": "9.0.6" + "node": "22.2.0", + "pnpm": "9.1.4" }, - "packageManager": "pnpm@9.0.6", + "packageManager": "pnpm@9.1.4", "scripts": { "build": "rollup --config --configPlugin typescript", "start": "node --enable-source-maps dist/main.cjs", @@ -22,15 +22,15 @@ "author": "", "license": "ISC", "dependencies": { - "fastify": "^4.26.2", + "fastify": "^4.27.0", "fastify-plugin": "^4.5.1", - "poolifier": "^4.0.1" + "poolifier": "^4.0.13" }, "devDependencies": { "@rollup/plugin-typescript": "^11.1.6", - "@types/node": "^20.12.8", + "@types/node": "^20.14.0", "autocannon": "^7.15.0", - "rollup": "^4.17.2", + "rollup": "^4.18.0", "rollup-plugin-delete": "^2.0.0", "tslib": "^2.6.2", "typescript": "^5.4.5" diff --git a/examples/typescript/http-server-pool/fastify-hybrid/pnpm-lock.yaml b/examples/typescript/http-server-pool/fastify-hybrid/pnpm-lock.yaml index 8978fe86..bd186413 100644 --- a/examples/typescript/http-server-pool/fastify-hybrid/pnpm-lock.yaml +++ b/examples/typescript/http-server-pool/fastify-hybrid/pnpm-lock.yaml @@ -9,27 +9,27 @@ importers: .: dependencies: fastify: - specifier: ^4.26.2 - version: 4.26.2 + specifier: ^4.27.0 + version: 4.27.0 fastify-plugin: specifier: ^4.5.1 version: 4.5.1 poolifier: - specifier: ^4.0.1 - version: 4.0.1 + specifier: ^4.0.13 + version: 4.0.13 devDependencies: '@rollup/plugin-typescript': specifier: ^11.1.6 - version: 11.1.6(rollup@4.17.2)(tslib@2.6.2)(typescript@5.4.5) + version: 11.1.6(rollup@4.18.0)(tslib@2.6.2)(typescript@5.4.5) '@types/node': - specifier: ^20.12.8 - version: 20.12.8 + specifier: ^20.14.0 + version: 20.14.0 autocannon: specifier: ^7.15.0 version: 7.15.0 rollup: - specifier: ^4.17.2 - version: 4.17.2 + specifier: ^4.18.0 + version: 4.18.0 rollup-plugin-delete: specifier: ^2.0.0 version: 2.0.0 @@ -95,83 +95,83 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.17.2': - resolution: {integrity: sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==} + '@rollup/rollup-android-arm-eabi@4.18.0': + resolution: {integrity: sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.17.2': - resolution: {integrity: sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==} + '@rollup/rollup-android-arm64@4.18.0': + resolution: {integrity: sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.17.2': - resolution: {integrity: sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==} + '@rollup/rollup-darwin-arm64@4.18.0': + resolution: {integrity: sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.17.2': - resolution: {integrity: sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==} + '@rollup/rollup-darwin-x64@4.18.0': + resolution: {integrity: sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==} cpu: [x64] os: [darwin] - '@rollup/rollup-linux-arm-gnueabihf@4.17.2': - resolution: {integrity: sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==} + '@rollup/rollup-linux-arm-gnueabihf@4.18.0': + resolution: {integrity: sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.17.2': - resolution: {integrity: sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==} + '@rollup/rollup-linux-arm-musleabihf@4.18.0': + resolution: {integrity: sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.17.2': - resolution: {integrity: sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==} + '@rollup/rollup-linux-arm64-gnu@4.18.0': + resolution: {integrity: sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.17.2': - resolution: {integrity: sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==} + '@rollup/rollup-linux-arm64-musl@4.18.0': + resolution: {integrity: sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.17.2': - resolution: {integrity: sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==} + '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': + resolution: {integrity: sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.17.2': - resolution: {integrity: sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==} + '@rollup/rollup-linux-riscv64-gnu@4.18.0': + resolution: {integrity: sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.17.2': - resolution: {integrity: sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==} + '@rollup/rollup-linux-s390x-gnu@4.18.0': + resolution: {integrity: sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.17.2': - resolution: {integrity: sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==} + '@rollup/rollup-linux-x64-gnu@4.18.0': + resolution: {integrity: sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.17.2': - resolution: {integrity: sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==} + '@rollup/rollup-linux-x64-musl@4.18.0': + resolution: {integrity: sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.17.2': - resolution: {integrity: sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==} + '@rollup/rollup-win32-arm64-msvc@4.18.0': + resolution: {integrity: sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.17.2': - resolution: {integrity: sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==} + '@rollup/rollup-win32-ia32-msvc@4.18.0': + resolution: {integrity: sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.17.2': - resolution: {integrity: sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==} + '@rollup/rollup-win32-x64-msvc@4.18.0': + resolution: {integrity: sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==} cpu: [x64] os: [win32] @@ -184,8 +184,8 @@ packages: '@types/minimatch@5.1.2': resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} - '@types/node@20.12.8': - resolution: {integrity: sha512-NU0rJLJnshZWdE/097cdCBbyW1h4hEg0xpovcoAQYHl8dnEyp/NAOiE45pvc+Bd1Dt+2r94v2eGFpQJ4R7g+2w==} + '@types/node@20.14.0': + resolution: {integrity: sha512-5cHBxFGJx6L4s56Bubp4fglrEpmyJypsqI6RgzMfBHWUJQGWAAi8cWcgetEbZXHYXo9C2Fa4EEds/uSyS4cxmA==} abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} @@ -214,8 +214,8 @@ packages: ajv: optional: true - ajv@8.13.0: - resolution: {integrity: sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==} + ajv@8.14.0: + resolution: {integrity: sha512-oYs1UUtO97ZO2lJ4bwnWeQW8/zvOIQLGKcvPTsWmvc2SYgBb+upuNS5NxoLaMU4h8Ju3Nbj6Cq8mD2LQoqVKFA==} ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} @@ -225,9 +225,6 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} - archy@1.0.0: - resolution: {integrity: sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==} - array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} @@ -243,8 +240,8 @@ packages: resolution: {integrity: sha512-NaP2rQyA+tcubOJMFv2+oeW9jv2pq/t+LM6BL3cfJic0HEfscEcnWgAyU5YovE/oTHUzAgTliGdLPR+RQAWUbg==} hasBin: true - avvio@8.3.0: - resolution: {integrity: sha512-VBVH0jubFr9LdFASy/vNtm5giTrnbVquWBhT0fyizuNK2rQ7e7ONU2plZQWUNqtE1EmxFEb+kbSkFRkstiaS9Q==} + avvio@8.3.2: + resolution: {integrity: sha512-st8e519GWHa/azv8S87mcJvZs4WsgTBjOw/Ih1CP6u+8SZvcOeAYNG6JbsIrAUUJJ7JfmrnOkR8ipDS+u9SIRQ==} balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -255,8 +252,8 @@ packages: brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} buffer@5.7.1: @@ -276,8 +273,8 @@ packages: resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} engines: {node: '>=6'} - cli-table3@0.6.4: - resolution: {integrity: sha512-Lm3L0p+/npIQWNIiyF/nAn7T5dnOwR3xNTHXYEBFBFVPXzCVNZ5lqEC/1eo/EVfpDsQ1I+TX4ORPQgp+UI0CRw==} + cli-table3@0.6.5: + resolution: {integrity: sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==} engines: {node: 10.* || >= 12.*} color-convert@2.0.1: @@ -305,15 +302,6 @@ packages: cross-argv@2.0.0: resolution: {integrity: sha512-YIaY9TR5Nxeb8SMdtrU8asWVM4jqJDNDYlKV21LxtYcfNJhp1kEsgSa6qXwXgzN0WQWGODps0+TlGp2xQSHwOg==} - debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - del@5.1.0: resolution: {integrity: sha512-wH9xOVHnczo9jN2IW68BabcecVPxacIA3g/7z6vhSU/4stOKQzeCRK0yD0A24WiAAUJmmVpWqrERcTxnLo3AnA==} engines: {node: '>=8'} @@ -353,8 +341,8 @@ packages: resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} engines: {node: '>=8.6.0'} - fast-json-stringify@5.15.0: - resolution: {integrity: sha512-BUEAAyDKb64u+kmkINYfXUUiKjBKerSmVu/dzotfaWSHBxR44JFrOZgkhMO6VxDhDfiuAoi8mx4drd5nvNdA4Q==} + fast-json-stringify@5.16.0: + resolution: {integrity: sha512-A4bg6E15QrkuVO3f0SwIASgzMzR6XC4qTyTqhf3hYXy0iazbAdZKwkE+ox4WgzKyzM6ygvbdq3r134UjOaaAnA==} fast-querystring@1.1.2: resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==} @@ -369,14 +357,14 @@ packages: fastify-plugin@4.5.1: resolution: {integrity: sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ==} - fastify@4.26.2: - resolution: {integrity: sha512-90pjTuPGrfVKtdpLeLzND5nyC4woXZN5VadiNQCicj/iJU4viNHKhsAnb7jmv1vu2IzkLXyBiCzdWuzeXgQ5Ug==} + fastify@4.27.0: + resolution: {integrity: sha512-ci9IXzbigB8dyi0mSy3faa3Bsj0xWAPb9JeT4KRzubdSb6pNhcADRUaXCBml6V1Ss/a05kbtQls5LBmhHydoTA==} fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} find-my-way@8.2.0: @@ -408,6 +396,7 @@ packages: glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported globby@10.0.2: resolution: {integrity: sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==} @@ -453,6 +442,7 @@ packages: inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -506,10 +496,6 @@ packages: lodash.flatten@4.4.0: resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==} - lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - manage-path@2.0.0: resolution: {integrity: sha512-NJhyB+PJYTpxhxZJ3lecIGgh4kwIY2RAh44XvAz9UlqthlQwtPBf62uBVR8XaD8CRuSjQ6TnZH2lNJkbLPZM2A==} @@ -517,8 +503,8 @@ packages: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} - micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + micromatch@4.0.7: + resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} engines: {node: '>=8.6'} mime-db@1.52.0: @@ -535,9 +521,6 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - on-exit-leak-free@2.1.2: resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} engines: {node: '>=14.0.0'} @@ -574,15 +557,15 @@ packages: pino-abstract-transport@1.2.0: resolution: {integrity: sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==} - pino-std-serializers@6.2.2: - resolution: {integrity: sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==} + pino-std-serializers@7.0.0: + resolution: {integrity: sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==} - pino@8.21.0: - resolution: {integrity: sha512-ip4qdzjkAyDDZklUaZkcRFb2iA118H9SgRh8yzTkSQK8HilsOJF7rSY8HoW5+I0M46AZgX/pxbprf2vvzQCE0Q==} + pino@9.1.0: + resolution: {integrity: sha512-qUcgfrlyOtjwhNLdbhoL7NR4NkHjzykAPw0V2QLFbvu/zss29h4NkRnibyFzBrNCbzCOY3WZ9hhKSwfOkNggYA==} hasBin: true - poolifier@4.0.1: - resolution: {integrity: sha512-1izVxQOC3yonTN1I51tualsPfZ0iUN+r5zaKY/+vEWIa0cUJMPgi1hN86DL4kwCTwr65JZ42ZrxnQWRmdnzRpA==} + poolifier@4.0.13: + resolution: {integrity: sha512-GPITJo3LZvZXGNDWn6eDpOJ+F5+rq4tvyoXFQJfyJ92w0qr4evjoOX9hymwMGmv8TuifFMIBmgCdcTvoxRdMgA==} engines: {node: '>=18.0.0', pnpm: '>=9.0.0'} pretty-bytes@5.6.0: @@ -649,14 +632,15 @@ packages: rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true rollup-plugin-delete@2.0.0: resolution: {integrity: sha512-/VpLMtDy+8wwRlDANuYmDa9ss/knGsAgrDhM+tEwB1npHwNu4DYNmDfUL55csse/GHs9Q+SMT/rw9uiaZ3pnzA==} engines: {node: '>=10'} - rollup@4.17.2: - resolution: {integrity: sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==} + rollup@4.18.0: + resolution: {integrity: sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -676,8 +660,8 @@ packages: secure-json-parse@2.7.0: resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} - semver@7.6.0: - resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} + semver@7.6.2: + resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} engines: {node: '>=10'} hasBin: true @@ -688,8 +672,8 @@ packages: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} - sonic-boom@3.8.1: - resolution: {integrity: sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==} + sonic-boom@4.0.1: + resolution: {integrity: sha512-hTSD/6JMLyT4r9zeof6UtuBDpjJ9sO08/nmS5djaA9eozT9oOlNdpXSnzcgj4FTqpk3nkLrs61l4gip9r1HCrQ==} split2@4.2.0: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} @@ -717,8 +701,8 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - thread-stream@2.7.0: - resolution: {integrity: sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw==} + thread-stream@3.0.2: + resolution: {integrity: sha512-cBL4xF2A3lSINV4rD5tyqnKH4z/TgWPvT+NaVhJDSwK962oo/Ye7cHSMbDzwcu7tAE1SfU6Q4XtV6Hucmi6Hlw==} timestring@6.0.0: resolution: {integrity: sha512-wMctrWD2HZZLuIlchlkE2dfXJh7J2KDI9Dwl+2abPYg0mswQHfOAyQW3jJg1pY5VfttSINZuKcXoB3FGypVklA==} @@ -756,9 +740,6 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - snapshots: '@assemblyscript/loader@0.19.23': {} @@ -768,15 +749,15 @@ snapshots: '@fastify/ajv-compiler@3.5.0': dependencies: - ajv: 8.13.0 - ajv-formats: 2.1.1(ajv@8.13.0) + ajv: 8.14.0 + ajv-formats: 2.1.1(ajv@8.14.0) fast-uri: 2.3.0 '@fastify/error@3.4.1': {} '@fastify/fast-json-stringify-compiler@4.3.0': dependencies: - fast-json-stringify: 5.15.0 + fast-json-stringify: 5.16.0 '@fastify/merge-json-schemas@0.1.1': dependencies: @@ -794,69 +775,69 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 - '@rollup/plugin-typescript@11.1.6(rollup@4.17.2)(tslib@2.6.2)(typescript@5.4.5)': + '@rollup/plugin-typescript@11.1.6(rollup@4.18.0)(tslib@2.6.2)(typescript@5.4.5)': dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.17.2) + '@rollup/pluginutils': 5.1.0(rollup@4.18.0) resolve: 1.22.8 typescript: 5.4.5 optionalDependencies: - rollup: 4.17.2 + rollup: 4.18.0 tslib: 2.6.2 - '@rollup/pluginutils@5.1.0(rollup@4.17.2)': + '@rollup/pluginutils@5.1.0(rollup@4.18.0)': dependencies: '@types/estree': 1.0.5 estree-walker: 2.0.2 picomatch: 2.3.1 optionalDependencies: - rollup: 4.17.2 + rollup: 4.18.0 - '@rollup/rollup-android-arm-eabi@4.17.2': + '@rollup/rollup-android-arm-eabi@4.18.0': optional: true - '@rollup/rollup-android-arm64@4.17.2': + '@rollup/rollup-android-arm64@4.18.0': optional: true - '@rollup/rollup-darwin-arm64@4.17.2': + '@rollup/rollup-darwin-arm64@4.18.0': optional: true - '@rollup/rollup-darwin-x64@4.17.2': + '@rollup/rollup-darwin-x64@4.18.0': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.17.2': + '@rollup/rollup-linux-arm-gnueabihf@4.18.0': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.17.2': + '@rollup/rollup-linux-arm-musleabihf@4.18.0': optional: true - '@rollup/rollup-linux-arm64-gnu@4.17.2': + '@rollup/rollup-linux-arm64-gnu@4.18.0': optional: true - '@rollup/rollup-linux-arm64-musl@4.17.2': + '@rollup/rollup-linux-arm64-musl@4.18.0': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.17.2': + '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.17.2': + '@rollup/rollup-linux-riscv64-gnu@4.18.0': optional: true - '@rollup/rollup-linux-s390x-gnu@4.17.2': + '@rollup/rollup-linux-s390x-gnu@4.18.0': optional: true - '@rollup/rollup-linux-x64-gnu@4.17.2': + '@rollup/rollup-linux-x64-gnu@4.18.0': optional: true - '@rollup/rollup-linux-x64-musl@4.17.2': + '@rollup/rollup-linux-x64-musl@4.18.0': optional: true - '@rollup/rollup-win32-arm64-msvc@4.17.2': + '@rollup/rollup-win32-arm64-msvc@4.18.0': optional: true - '@rollup/rollup-win32-ia32-msvc@4.17.2': + '@rollup/rollup-win32-ia32-msvc@4.18.0': optional: true - '@rollup/rollup-win32-x64-msvc@4.17.2': + '@rollup/rollup-win32-x64-msvc@4.18.0': optional: true '@types/estree@1.0.5': {} @@ -864,11 +845,11 @@ snapshots: '@types/glob@7.2.0': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 20.12.8 + '@types/node': 20.14.0 '@types/minimatch@5.1.2': {} - '@types/node@20.12.8': + '@types/node@20.14.0': dependencies: undici-types: 5.26.5 @@ -883,15 +864,15 @@ snapshots: clean-stack: 2.2.0 indent-string: 4.0.0 - ajv-formats@2.1.1(ajv@8.13.0): + ajv-formats@2.1.1(ajv@8.14.0): optionalDependencies: - ajv: 8.13.0 + ajv: 8.14.0 - ajv-formats@3.0.1(ajv@8.13.0): + ajv-formats@3.0.1(ajv@8.14.0): optionalDependencies: - ajv: 8.13.0 + ajv: 8.14.0 - ajv@8.13.0: + ajv@8.14.0: dependencies: fast-deep-equal: 3.1.3 json-schema-traverse: 1.0.0 @@ -904,8 +885,6 @@ snapshots: dependencies: color-convert: 2.0.1 - archy@1.0.0: {} - array-union@2.1.0: {} asynckit@0.4.0: {} @@ -916,7 +895,7 @@ snapshots: dependencies: chalk: 4.1.2 char-spinner: 1.0.1 - cli-table3: 0.6.4 + cli-table3: 0.6.5 color-support: 1.1.3 cross-argv: 2.0.0 form-data: 4.0.0 @@ -934,18 +913,14 @@ snapshots: progress: 2.0.3 reinterval: 1.1.0 retimer: 3.0.0 - semver: 7.6.0 + semver: 7.6.2 subarg: 1.0.0 timestring: 6.0.0 - avvio@8.3.0: + avvio@8.3.2: dependencies: '@fastify/error': 3.4.1 - archy: 1.0.0 - debug: 4.3.4 fastq: 1.17.1 - transitivePeerDependencies: - - supports-color balanced-match@1.0.2: {} @@ -956,9 +931,9 @@ snapshots: balanced-match: 1.0.2 concat-map: 0.0.1 - braces@3.0.2: + braces@3.0.3: dependencies: - fill-range: 7.0.1 + fill-range: 7.1.1 buffer@5.7.1: dependencies: @@ -979,7 +954,7 @@ snapshots: clean-stack@2.2.0: {} - cli-table3@0.6.4: + cli-table3@0.6.5: dependencies: string-width: 4.2.3 optionalDependencies: @@ -1003,10 +978,6 @@ snapshots: cross-argv@2.0.0: {} - debug@4.3.4: - dependencies: - ms: 2.1.2 - del@5.1.0: dependencies: globby: 10.0.2 @@ -1044,13 +1015,13 @@ snapshots: '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 - micromatch: 4.0.5 + micromatch: 4.0.7 - fast-json-stringify@5.15.0: + fast-json-stringify@5.16.0: dependencies: '@fastify/merge-json-schemas': 0.1.1 - ajv: 8.13.0 - ajv-formats: 3.0.1(ajv@8.13.0) + ajv: 8.14.0 + ajv-formats: 3.0.1(ajv@8.14.0) fast-deep-equal: 3.1.3 fast-uri: 2.3.0 json-schema-ref-resolver: 1.0.1 @@ -1066,32 +1037,30 @@ snapshots: fastify-plugin@4.5.1: {} - fastify@4.26.2: + fastify@4.27.0: dependencies: '@fastify/ajv-compiler': 3.5.0 '@fastify/error': 3.4.1 '@fastify/fast-json-stringify-compiler': 4.3.0 abstract-logging: 2.0.1 - avvio: 8.3.0 + avvio: 8.3.2 fast-content-type-parse: 1.1.0 - fast-json-stringify: 5.15.0 + fast-json-stringify: 5.16.0 find-my-way: 8.2.0 light-my-request: 5.13.0 - pino: 8.21.0 + pino: 9.1.0 process-warning: 3.0.0 proxy-addr: 2.0.7 rfdc: 1.3.1 secure-json-parse: 2.7.0 - semver: 7.6.0 + semver: 7.6.2 toad-cache: 3.7.0 - transitivePeerDependencies: - - supports-color fastq@1.17.1: dependencies: reusify: 1.0.4 - fill-range@7.0.1: + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -1217,17 +1186,13 @@ snapshots: lodash.flatten@4.4.0: {} - lru-cache@6.0.0: - dependencies: - yallist: 4.0.0 - manage-path@2.0.0: {} merge2@1.4.1: {} - micromatch@4.0.5: + micromatch@4.0.7: dependencies: - braces: 3.0.2 + braces: 3.0.3 picomatch: 2.3.1 mime-db@1.52.0: {} @@ -1242,8 +1207,6 @@ snapshots: minimist@1.2.8: {} - ms@2.1.2: {} - on-exit-leak-free@2.1.2: {} on-net-listen@1.1.2: {} @@ -1271,23 +1234,23 @@ snapshots: readable-stream: 4.5.2 split2: 4.2.0 - pino-std-serializers@6.2.2: {} + pino-std-serializers@7.0.0: {} - pino@8.21.0: + pino@9.1.0: dependencies: atomic-sleep: 1.0.0 fast-redact: 3.5.0 on-exit-leak-free: 2.1.2 pino-abstract-transport: 1.2.0 - pino-std-serializers: 6.2.2 + pino-std-serializers: 7.0.0 process-warning: 3.0.0 quick-format-unescaped: 4.0.4 real-require: 0.2.0 safe-stable-stringify: 2.4.3 - sonic-boom: 3.8.1 - thread-stream: 2.7.0 + sonic-boom: 4.0.1 + thread-stream: 3.0.2 - poolifier@4.0.1: {} + poolifier@4.0.13: {} pretty-bytes@5.6.0: {} @@ -1344,26 +1307,26 @@ snapshots: dependencies: del: 5.1.0 - rollup@4.17.2: + rollup@4.18.0: dependencies: '@types/estree': 1.0.5 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.17.2 - '@rollup/rollup-android-arm64': 4.17.2 - '@rollup/rollup-darwin-arm64': 4.17.2 - '@rollup/rollup-darwin-x64': 4.17.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.17.2 - '@rollup/rollup-linux-arm-musleabihf': 4.17.2 - '@rollup/rollup-linux-arm64-gnu': 4.17.2 - '@rollup/rollup-linux-arm64-musl': 4.17.2 - '@rollup/rollup-linux-powerpc64le-gnu': 4.17.2 - '@rollup/rollup-linux-riscv64-gnu': 4.17.2 - '@rollup/rollup-linux-s390x-gnu': 4.17.2 - '@rollup/rollup-linux-x64-gnu': 4.17.2 - '@rollup/rollup-linux-x64-musl': 4.17.2 - '@rollup/rollup-win32-arm64-msvc': 4.17.2 - '@rollup/rollup-win32-ia32-msvc': 4.17.2 - '@rollup/rollup-win32-x64-msvc': 4.17.2 + '@rollup/rollup-android-arm-eabi': 4.18.0 + '@rollup/rollup-android-arm64': 4.18.0 + '@rollup/rollup-darwin-arm64': 4.18.0 + '@rollup/rollup-darwin-x64': 4.18.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.18.0 + '@rollup/rollup-linux-arm-musleabihf': 4.18.0 + '@rollup/rollup-linux-arm64-gnu': 4.18.0 + '@rollup/rollup-linux-arm64-musl': 4.18.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.18.0 + '@rollup/rollup-linux-riscv64-gnu': 4.18.0 + '@rollup/rollup-linux-s390x-gnu': 4.18.0 + '@rollup/rollup-linux-x64-gnu': 4.18.0 + '@rollup/rollup-linux-x64-musl': 4.18.0 + '@rollup/rollup-win32-arm64-msvc': 4.18.0 + '@rollup/rollup-win32-ia32-msvc': 4.18.0 + '@rollup/rollup-win32-x64-msvc': 4.18.0 fsevents: 2.3.3 run-parallel@1.2.0: @@ -1380,15 +1343,13 @@ snapshots: secure-json-parse@2.7.0: {} - semver@7.6.0: - dependencies: - lru-cache: 6.0.0 + semver@7.6.2: {} set-cookie-parser@2.6.0: {} slash@3.0.0: {} - sonic-boom@3.8.1: + sonic-boom@4.0.1: dependencies: atomic-sleep: 1.0.0 @@ -1418,7 +1379,7 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - thread-stream@2.7.0: + thread-stream@3.0.2: dependencies: real-require: 0.2.0 @@ -1445,5 +1406,3 @@ snapshots: uuid@8.3.2: {} wrappy@1.0.2: {} - - yallist@4.0.0: {} diff --git a/examples/typescript/http-server-pool/fastify-hybrid/rollup.config.ts b/examples/typescript/http-server-pool/fastify-hybrid/rollup.config.ts index 6bb949aa..ae79b9bc 100644 --- a/examples/typescript/http-server-pool/fastify-hybrid/rollup.config.ts +++ b/examples/typescript/http-server-pool/fastify-hybrid/rollup.config.ts @@ -6,7 +6,7 @@ export default defineConfig({ input: [ './src/main.ts', './src/fastify-worker.ts', - './src/request-handler-worker.ts' + './src/request-handler-worker.ts', ], strictDeprecations: true, output: [ @@ -15,19 +15,19 @@ export default defineConfig({ dir: './dist', sourcemap: true, entryFileNames: '[name].cjs', - chunkFileNames: '[name]-[hash].cjs' + chunkFileNames: '[name]-[hash].cjs', }, { format: 'esm', dir: './dist', - sourcemap: true - } + sourcemap: true, + }, ], external: ['fastify', 'fastify-plugin', /^node:*/, 'poolifier'], plugins: [ typescript(), del({ - targets: ['./dist/*'] - }) - ] + targets: ['./dist/*'], + }), + ], }) diff --git a/examples/typescript/http-server-pool/fastify-hybrid/src/fastify-poolifier.ts b/examples/typescript/http-server-pool/fastify-hybrid/src/fastify-poolifier.ts index f105d7af..753f6df1 100644 --- a/examples/typescript/http-server-pool/fastify-hybrid/src/fastify-poolifier.ts +++ b/examples/typescript/http-server-pool/fastify-hybrid/src/fastify-poolifier.ts @@ -4,10 +4,10 @@ import type { FastifyPluginCallback } from 'fastify' import fp from 'fastify-plugin' import { availableParallelism, DynamicThreadPool } from 'poolifier' -import { - type FastifyPoolifierOptions, - type ThreadWorkerData, - type ThreadWorkerResponse +import type { + FastifyPoolifierOptions, + ThreadWorkerData, + ThreadWorkerResponse, } from './types.js' const fastifyPoolifierPlugin: FastifyPluginCallback = ( @@ -18,13 +18,15 @@ const fastifyPoolifierPlugin: FastifyPluginCallback = ( options = { ...{ minWorkers: 1, - maxWorkers: availableParallelism() + maxWorkers: availableParallelism(), }, - ...options + ...options, } const { workerFile, minWorkers, maxWorkers, ...poolOptions } = options const pool = new DynamicThreadPool( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion minWorkers!, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion maxWorkers!, workerFile, poolOptions @@ -48,5 +50,5 @@ const fastifyPoolifierPlugin: FastifyPluginCallback = ( export const fastifyPoolifier = fp(fastifyPoolifierPlugin, { fastify: '4.x', - name: 'fastify-poolifier' + name: 'fastify-poolifier', }) diff --git a/examples/typescript/http-server-pool/fastify-hybrid/src/fastify-worker.ts b/examples/typescript/http-server-pool/fastify-hybrid/src/fastify-worker.ts index 8e4713cf..4a697f3e 100644 --- a/examples/typescript/http-server-pool/fastify-hybrid/src/fastify-worker.ts +++ b/examples/typescript/http-server-pool/fastify-hybrid/src/fastify-worker.ts @@ -7,18 +7,19 @@ import { fastifyPoolifier } from './fastify-poolifier.js' import type { ClusterWorkerData, ClusterWorkerResponse } from './types.js' class FastifyWorker extends ClusterWorker< -ClusterWorkerData, -ClusterWorkerResponse + ClusterWorkerData, + ClusterWorkerResponse > { private static fastify: FastifyInstance private static readonly startFastify = async ( workerData?: ClusterWorkerData ): Promise => { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const { port, ...fastifyPoolifierOptions } = workerData! FastifyWorker.fastify = Fastify({ - logger: true + logger: true, }) await FastifyWorker.fastify.register( @@ -44,7 +45,7 @@ ClusterWorkerResponse await FastifyWorker.fastify.listen({ port }) return { status: true, - port: (FastifyWorker.fastify.server.address() as AddressInfo).port + port: (FastifyWorker.fastify.server.address() as AddressInfo).port, } } @@ -53,7 +54,7 @@ ClusterWorkerResponse killHandler: async () => { await FastifyWorker.fastify.pool.destroy() await FastifyWorker.fastify.close() - } + }, }) } } diff --git a/examples/typescript/http-server-pool/fastify-hybrid/src/main.ts b/examples/typescript/http-server-pool/fastify-hybrid/src/main.ts index fea592c4..74ed1f70 100644 --- a/examples/typescript/http-server-pool/fastify-hybrid/src/main.ts +++ b/examples/typescript/http-server-pool/fastify-hybrid/src/main.ts @@ -31,16 +31,17 @@ const pool = new FixedClusterPool( : Math.round(availableParallelism() / 4), enableTasksQueue: true, tasksQueueOptions: { - concurrency: 8 + concurrency: 8, }, errorHandler: (e: Error) => { console.error('Thread worker error', e) - } + }, }) .then(response => { if (response.status) { console.info( - `Fastify is listening in cluster worker on port ${response.port}` + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + `Fastify is listening in cluster worker on port ${response.port?.toString()}` ) } return undefined @@ -51,6 +52,6 @@ const pool = new FixedClusterPool( }, errorHandler: (e: Error) => { console.error('Cluster worker error:', e) - } + }, } ) diff --git a/examples/typescript/http-server-pool/fastify-hybrid/src/request-handler-worker.ts b/examples/typescript/http-server-pool/fastify-hybrid/src/request-handler-worker.ts index b7ff8b16..5297de12 100644 --- a/examples/typescript/http-server-pool/fastify-hybrid/src/request-handler-worker.ts +++ b/examples/typescript/http-server-pool/fastify-hybrid/src/request-handler-worker.ts @@ -1,9 +1,9 @@ import { ThreadWorker } from 'poolifier' -import { - type DataPayload, - type ThreadWorkerData, - type ThreadWorkerResponse +import type { + DataPayload, + ThreadWorkerData, + ThreadWorkerResponse, } from './types.js' class RequestHandlerWorker< @@ -32,16 +32,17 @@ class RequestHandlerWorker< return { data: { number: RequestHandlerWorker.factorial( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion workerData!.data.number! - ).toString() - } + ).toString(), + }, } as unknown as Response - } + }, }) } } export const requestHandlerWorker = new RequestHandlerWorker< -ThreadWorkerData, -ThreadWorkerResponse + ThreadWorkerData, + ThreadWorkerResponse >() diff --git a/examples/typescript/http-server-pool/fastify-worker_threads/package.json b/examples/typescript/http-server-pool/fastify-worker_threads/package.json index d2b30143..bef9e6a0 100644 --- a/examples/typescript/http-server-pool/fastify-worker_threads/package.json +++ b/examples/typescript/http-server-pool/fastify-worker_threads/package.json @@ -6,10 +6,10 @@ "main": "dist/main.js", "type": "module", "volta": { - "node": "22.0.0", - "pnpm": "9.0.6" + "node": "22.2.0", + "pnpm": "9.1.4" }, - "packageManager": "pnpm@9.0.6", + "packageManager": "pnpm@9.1.4", "scripts": { "build": "pnpm build:clean && tsc", "build:clean": "tsc --build --clean", @@ -22,12 +22,12 @@ "author": "", "license": "ISC", "dependencies": { - "fastify": "^4.26.2", + "fastify": "^4.27.0", "fastify-plugin": "^4.5.1", - "poolifier": "^4.0.1" + "poolifier": "^4.0.13" }, "devDependencies": { - "@types/node": "^20.12.8", + "@types/node": "^20.14.0", "autocannon": "^7.15.0", "typescript": "^5.4.5" } diff --git a/examples/typescript/http-server-pool/fastify-worker_threads/pnpm-lock.yaml b/examples/typescript/http-server-pool/fastify-worker_threads/pnpm-lock.yaml index a52b5f81..5f6d6c2d 100644 --- a/examples/typescript/http-server-pool/fastify-worker_threads/pnpm-lock.yaml +++ b/examples/typescript/http-server-pool/fastify-worker_threads/pnpm-lock.yaml @@ -9,18 +9,18 @@ importers: .: dependencies: fastify: - specifier: ^4.26.2 - version: 4.26.2 + specifier: ^4.27.0 + version: 4.27.0 fastify-plugin: specifier: ^4.5.1 version: 4.5.1 poolifier: - specifier: ^4.0.1 - version: 4.0.1 + specifier: ^4.0.13 + version: 4.0.13 devDependencies: '@types/node': - specifier: ^20.12.8 - version: 20.12.8 + specifier: ^20.14.0 + version: 20.14.0 autocannon: specifier: ^7.15.0 version: 7.15.0 @@ -49,8 +49,8 @@ packages: '@fastify/merge-json-schemas@0.1.1': resolution: {integrity: sha512-fERDVz7topgNjtXsJTTW1JKLy0rhuLRcquYqNR9rF7OcVpCa2OVW49ZPDIhaRRCaUuvVxI+N416xUoF76HNSXA==} - '@types/node@20.12.8': - resolution: {integrity: sha512-NU0rJLJnshZWdE/097cdCBbyW1h4hEg0xpovcoAQYHl8dnEyp/NAOiE45pvc+Bd1Dt+2r94v2eGFpQJ4R7g+2w==} + '@types/node@20.14.0': + resolution: {integrity: sha512-5cHBxFGJx6L4s56Bubp4fglrEpmyJypsqI6RgzMfBHWUJQGWAAi8cWcgetEbZXHYXo9C2Fa4EEds/uSyS4cxmA==} abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} @@ -75,8 +75,8 @@ packages: ajv: optional: true - ajv@8.13.0: - resolution: {integrity: sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==} + ajv@8.14.0: + resolution: {integrity: sha512-oYs1UUtO97ZO2lJ4bwnWeQW8/zvOIQLGKcvPTsWmvc2SYgBb+upuNS5NxoLaMU4h8Ju3Nbj6Cq8mD2LQoqVKFA==} ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} @@ -86,9 +86,6 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} - archy@1.0.0: - resolution: {integrity: sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==} - asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} @@ -100,8 +97,8 @@ packages: resolution: {integrity: sha512-NaP2rQyA+tcubOJMFv2+oeW9jv2pq/t+LM6BL3cfJic0HEfscEcnWgAyU5YovE/oTHUzAgTliGdLPR+RQAWUbg==} hasBin: true - avvio@8.3.0: - resolution: {integrity: sha512-VBVH0jubFr9LdFASy/vNtm5giTrnbVquWBhT0fyizuNK2rQ7e7ONU2plZQWUNqtE1EmxFEb+kbSkFRkstiaS9Q==} + avvio@8.3.2: + resolution: {integrity: sha512-st8e519GWHa/azv8S87mcJvZs4WsgTBjOw/Ih1CP6u+8SZvcOeAYNG6JbsIrAUUJJ7JfmrnOkR8ipDS+u9SIRQ==} base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -119,8 +116,8 @@ packages: char-spinner@1.0.1: resolution: {integrity: sha512-acv43vqJ0+N0rD+Uw3pDHSxP30FHrywu2NO6/wBaHChJIizpDeBUd6NjqhNhy9LGaEAhZAXn46QzmlAvIWd16g==} - cli-table3@0.6.4: - resolution: {integrity: sha512-Lm3L0p+/npIQWNIiyF/nAn7T5dnOwR3xNTHXYEBFBFVPXzCVNZ5lqEC/1eo/EVfpDsQ1I+TX4ORPQgp+UI0CRw==} + cli-table3@0.6.5: + resolution: {integrity: sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==} engines: {node: 10.* || >= 12.*} color-convert@2.0.1: @@ -145,15 +142,6 @@ packages: cross-argv@2.0.0: resolution: {integrity: sha512-YIaY9TR5Nxeb8SMdtrU8asWVM4jqJDNDYlKV21LxtYcfNJhp1kEsgSa6qXwXgzN0WQWGODps0+TlGp2xQSHwOg==} - debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} @@ -178,8 +166,8 @@ packages: fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - fast-json-stringify@5.15.0: - resolution: {integrity: sha512-BUEAAyDKb64u+kmkINYfXUUiKjBKerSmVu/dzotfaWSHBxR44JFrOZgkhMO6VxDhDfiuAoi8mx4drd5nvNdA4Q==} + fast-json-stringify@5.16.0: + resolution: {integrity: sha512-A4bg6E15QrkuVO3f0SwIASgzMzR6XC4qTyTqhf3hYXy0iazbAdZKwkE+ox4WgzKyzM6ygvbdq3r134UjOaaAnA==} fast-querystring@1.1.2: resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==} @@ -194,8 +182,8 @@ packages: fastify-plugin@4.5.1: resolution: {integrity: sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ==} - fastify@4.26.2: - resolution: {integrity: sha512-90pjTuPGrfVKtdpLeLzND5nyC4woXZN5VadiNQCicj/iJU4viNHKhsAnb7jmv1vu2IzkLXyBiCzdWuzeXgQ5Ug==} + fastify@4.27.0: + resolution: {integrity: sha512-ci9IXzbigB8dyi0mSy3faa3Bsj0xWAPb9JeT4KRzubdSb6pNhcADRUaXCBml6V1Ss/a05kbtQls5LBmhHydoTA==} fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} @@ -261,10 +249,6 @@ packages: lodash.flatten@4.4.0: resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==} - lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - manage-path@2.0.0: resolution: {integrity: sha512-NJhyB+PJYTpxhxZJ3lecIGgh4kwIY2RAh44XvAz9UlqthlQwtPBf62uBVR8XaD8CRuSjQ6TnZH2lNJkbLPZM2A==} @@ -279,9 +263,6 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - on-exit-leak-free@2.1.2: resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} engines: {node: '>=14.0.0'} @@ -296,15 +277,15 @@ packages: pino-abstract-transport@1.2.0: resolution: {integrity: sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==} - pino-std-serializers@6.2.2: - resolution: {integrity: sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==} + pino-std-serializers@7.0.0: + resolution: {integrity: sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==} - pino@8.21.0: - resolution: {integrity: sha512-ip4qdzjkAyDDZklUaZkcRFb2iA118H9SgRh8yzTkSQK8HilsOJF7rSY8HoW5+I0M46AZgX/pxbprf2vvzQCE0Q==} + pino@9.1.0: + resolution: {integrity: sha512-qUcgfrlyOtjwhNLdbhoL7NR4NkHjzykAPw0V2QLFbvu/zss29h4NkRnibyFzBrNCbzCOY3WZ9hhKSwfOkNggYA==} hasBin: true - poolifier@4.0.1: - resolution: {integrity: sha512-1izVxQOC3yonTN1I51tualsPfZ0iUN+r5zaKY/+vEWIa0cUJMPgi1hN86DL4kwCTwr65JZ42ZrxnQWRmdnzRpA==} + poolifier@4.0.13: + resolution: {integrity: sha512-GPITJo3LZvZXGNDWn6eDpOJ+F5+rq4tvyoXFQJfyJ92w0qr4evjoOX9hymwMGmv8TuifFMIBmgCdcTvoxRdMgA==} engines: {node: '>=18.0.0', pnpm: '>=9.0.0'} pretty-bytes@5.6.0: @@ -375,16 +356,16 @@ packages: secure-json-parse@2.7.0: resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} - semver@7.6.0: - resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} + semver@7.6.2: + resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} engines: {node: '>=10'} hasBin: true set-cookie-parser@2.6.0: resolution: {integrity: sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==} - sonic-boom@3.8.1: - resolution: {integrity: sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==} + sonic-boom@4.0.1: + resolution: {integrity: sha512-hTSD/6JMLyT4r9zeof6UtuBDpjJ9sO08/nmS5djaA9eozT9oOlNdpXSnzcgj4FTqpk3nkLrs61l4gip9r1HCrQ==} split2@4.2.0: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} @@ -408,8 +389,8 @@ packages: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} - thread-stream@2.7.0: - resolution: {integrity: sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw==} + thread-stream@3.0.2: + resolution: {integrity: sha512-cBL4xF2A3lSINV4rD5tyqnKH4z/TgWPvT+NaVhJDSwK962oo/Ye7cHSMbDzwcu7tAE1SfU6Q4XtV6Hucmi6Hlw==} timestring@6.0.0: resolution: {integrity: sha512-wMctrWD2HZZLuIlchlkE2dfXJh7J2KDI9Dwl+2abPYg0mswQHfOAyQW3jJg1pY5VfttSINZuKcXoB3FGypVklA==} @@ -437,9 +418,6 @@ packages: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true - yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - snapshots: '@assemblyscript/loader@0.19.23': {} @@ -449,21 +427,21 @@ snapshots: '@fastify/ajv-compiler@3.5.0': dependencies: - ajv: 8.13.0 - ajv-formats: 2.1.1(ajv@8.13.0) + ajv: 8.14.0 + ajv-formats: 2.1.1(ajv@8.14.0) fast-uri: 2.3.0 '@fastify/error@3.4.1': {} '@fastify/fast-json-stringify-compiler@4.3.0': dependencies: - fast-json-stringify: 5.15.0 + fast-json-stringify: 5.16.0 '@fastify/merge-json-schemas@0.1.1': dependencies: fast-deep-equal: 3.1.3 - '@types/node@20.12.8': + '@types/node@20.14.0': dependencies: undici-types: 5.26.5 @@ -473,15 +451,15 @@ snapshots: abstract-logging@2.0.1: {} - ajv-formats@2.1.1(ajv@8.13.0): + ajv-formats@2.1.1(ajv@8.14.0): optionalDependencies: - ajv: 8.13.0 + ajv: 8.14.0 - ajv-formats@3.0.1(ajv@8.13.0): + ajv-formats@3.0.1(ajv@8.14.0): optionalDependencies: - ajv: 8.13.0 + ajv: 8.14.0 - ajv@8.13.0: + ajv@8.14.0: dependencies: fast-deep-equal: 3.1.3 json-schema-traverse: 1.0.0 @@ -494,8 +472,6 @@ snapshots: dependencies: color-convert: 2.0.1 - archy@1.0.0: {} - asynckit@0.4.0: {} atomic-sleep@1.0.0: {} @@ -504,7 +480,7 @@ snapshots: dependencies: chalk: 4.1.2 char-spinner: 1.0.1 - cli-table3: 0.6.4 + cli-table3: 0.6.5 color-support: 1.1.3 cross-argv: 2.0.0 form-data: 4.0.0 @@ -522,18 +498,14 @@ snapshots: progress: 2.0.3 reinterval: 1.1.0 retimer: 3.0.0 - semver: 7.6.0 + semver: 7.6.2 subarg: 1.0.0 timestring: 6.0.0 - avvio@8.3.0: + avvio@8.3.2: dependencies: '@fastify/error': 3.4.1 - archy: 1.0.0 - debug: 4.3.4 fastq: 1.17.1 - transitivePeerDependencies: - - supports-color base64-js@1.5.1: {} @@ -554,7 +526,7 @@ snapshots: char-spinner@1.0.1: {} - cli-table3@0.6.4: + cli-table3@0.6.5: dependencies: string-width: 4.2.3 optionalDependencies: @@ -576,10 +548,6 @@ snapshots: cross-argv@2.0.0: {} - debug@4.3.4: - dependencies: - ms: 2.1.2 - delayed-stream@1.0.0: {} emoji-regex@8.0.0: {} @@ -594,11 +562,11 @@ snapshots: fast-deep-equal@3.1.3: {} - fast-json-stringify@5.15.0: + fast-json-stringify@5.16.0: dependencies: '@fastify/merge-json-schemas': 0.1.1 - ajv: 8.13.0 - ajv-formats: 3.0.1(ajv@8.13.0) + ajv: 8.14.0 + ajv-formats: 3.0.1(ajv@8.14.0) fast-deep-equal: 3.1.3 fast-uri: 2.3.0 json-schema-ref-resolver: 1.0.1 @@ -614,26 +582,24 @@ snapshots: fastify-plugin@4.5.1: {} - fastify@4.26.2: + fastify@4.27.0: dependencies: '@fastify/ajv-compiler': 3.5.0 '@fastify/error': 3.4.1 '@fastify/fast-json-stringify-compiler': 4.3.0 abstract-logging: 2.0.1 - avvio: 8.3.0 + avvio: 8.3.2 fast-content-type-parse: 1.1.0 - fast-json-stringify: 5.15.0 + fast-json-stringify: 5.16.0 find-my-way: 8.2.0 light-my-request: 5.13.0 - pino: 8.21.0 + pino: 9.1.0 process-warning: 3.0.0 proxy-addr: 2.0.7 rfdc: 1.3.1 secure-json-parse: 2.7.0 - semver: 7.6.0 + semver: 7.6.2 toad-cache: 3.7.0 - transitivePeerDependencies: - - supports-color fastq@1.17.1: dependencies: @@ -697,10 +663,6 @@ snapshots: lodash.flatten@4.4.0: {} - lru-cache@6.0.0: - dependencies: - yallist: 4.0.0 - manage-path@2.0.0: {} mime-db@1.52.0: {} @@ -711,8 +673,6 @@ snapshots: minimist@1.2.8: {} - ms@2.1.2: {} - on-exit-leak-free@2.1.2: {} on-net-listen@1.1.2: {} @@ -724,23 +684,23 @@ snapshots: readable-stream: 4.5.2 split2: 4.2.0 - pino-std-serializers@6.2.2: {} + pino-std-serializers@7.0.0: {} - pino@8.21.0: + pino@9.1.0: dependencies: atomic-sleep: 1.0.0 fast-redact: 3.5.0 on-exit-leak-free: 2.1.2 pino-abstract-transport: 1.2.0 - pino-std-serializers: 6.2.2 + pino-std-serializers: 7.0.0 process-warning: 3.0.0 quick-format-unescaped: 4.0.4 real-require: 0.2.0 safe-stable-stringify: 2.4.3 - sonic-boom: 3.8.1 - thread-stream: 2.7.0 + sonic-boom: 4.0.1 + thread-stream: 3.0.2 - poolifier@4.0.1: {} + poolifier@4.0.13: {} pretty-bytes@5.6.0: {} @@ -791,13 +751,11 @@ snapshots: secure-json-parse@2.7.0: {} - semver@7.6.0: - dependencies: - lru-cache: 6.0.0 + semver@7.6.2: {} set-cookie-parser@2.6.0: {} - sonic-boom@3.8.1: + sonic-boom@4.0.1: dependencies: atomic-sleep: 1.0.0 @@ -825,7 +783,7 @@ snapshots: dependencies: has-flag: 4.0.0 - thread-stream@2.7.0: + thread-stream@3.0.2: dependencies: real-require: 0.2.0 @@ -844,5 +802,3 @@ snapshots: uuid-parse@1.1.0: {} uuid@8.3.2: {} - - yallist@4.0.0: {} diff --git a/examples/typescript/http-server-pool/fastify-worker_threads/src/fastify-poolifier.ts b/examples/typescript/http-server-pool/fastify-worker_threads/src/fastify-poolifier.ts index 450a2aea..451fcb80 100644 --- a/examples/typescript/http-server-pool/fastify-worker_threads/src/fastify-poolifier.ts +++ b/examples/typescript/http-server-pool/fastify-worker_threads/src/fastify-poolifier.ts @@ -4,10 +4,10 @@ import type { FastifyPluginCallback } from 'fastify' import fp from 'fastify-plugin' import { availableParallelism, DynamicThreadPool } from 'poolifier' -import { - type FastifyPoolifierOptions, - type WorkerData, - type WorkerResponse +import type { + FastifyPoolifierOptions, + WorkerData, + WorkerResponse, } from './types.js' const fastifyPoolifierPlugin: FastifyPluginCallback = ( @@ -18,13 +18,15 @@ const fastifyPoolifierPlugin: FastifyPluginCallback = ( options = { ...{ minWorkers: 1, - maxWorkers: availableParallelism() + maxWorkers: availableParallelism(), }, - ...options + ...options, } const { workerFile, minWorkers, maxWorkers, ...poolOptions } = options const pool = new DynamicThreadPool( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion minWorkers!, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion maxWorkers!, workerFile, poolOptions @@ -47,5 +49,5 @@ const fastifyPoolifierPlugin: FastifyPluginCallback = ( export const fastifyPoolifier = fp(fastifyPoolifierPlugin, { fastify: '4.x', - name: 'fastify-poolifier' + name: 'fastify-poolifier', }) diff --git a/examples/typescript/http-server-pool/fastify-worker_threads/src/main.ts b/examples/typescript/http-server-pool/fastify-worker_threads/src/main.ts index 5610bc1d..b9aba792 100644 --- a/examples/typescript/http-server-pool/fastify-worker_threads/src/main.ts +++ b/examples/typescript/http-server-pool/fastify-worker_threads/src/main.ts @@ -12,11 +12,12 @@ import { fastifyPoolifier } from './fastify-poolifier.js' const port = 8080 const fastify = Fastify({ - logger: true + logger: true, }) const workerFile = join( dirname(fileURLToPath(import.meta.url)), + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions `worker${extname(fileURLToPath(import.meta.url))}` ) @@ -24,11 +25,11 @@ await fastify.register(fastifyPoolifier, { workerFile, enableTasksQueue: true, tasksQueueOptions: { - concurrency: 8 + concurrency: 8, }, errorHandler: (e: Error) => { fastify.log.error('Thread worker error:', e) - } + }, }) fastify.all('/api/echo', async request => { diff --git a/examples/typescript/http-server-pool/fastify-worker_threads/src/worker.ts b/examples/typescript/http-server-pool/fastify-worker_threads/src/worker.ts index 18e5c8a3..c5819f83 100644 --- a/examples/typescript/http-server-pool/fastify-worker_threads/src/worker.ts +++ b/examples/typescript/http-server-pool/fastify-worker_threads/src/worker.ts @@ -1,10 +1,6 @@ import { ThreadWorker } from 'poolifier' -import { - type BodyPayload, - type WorkerData, - type WorkerResponse -} from './types.js' +import type { BodyPayload, WorkerData, WorkerResponse } from './types.js' class RequestHandlerWorker< Data extends WorkerData, @@ -32,16 +28,17 @@ class RequestHandlerWorker< return { body: { number: RequestHandlerWorker.factorial( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion workerData!.body.number! - ).toString() - } + ).toString(), + }, } as unknown as Response - } + }, }) } } export const requestHandlerWorker = new RequestHandlerWorker< -WorkerData, -WorkerResponse + WorkerData, + WorkerResponse >() diff --git a/examples/typescript/pool.ts b/examples/typescript/pool.ts index 3965e1f0..1be0691a 100644 --- a/examples/typescript/pool.ts +++ b/examples/typescript/pool.ts @@ -4,7 +4,7 @@ import { fileURLToPath } from 'node:url' import { availableParallelism, DynamicThreadPool, - FixedThreadPool + FixedThreadPool, } from 'poolifier' import type { MyData, MyResponse } from './worker.js' @@ -23,7 +23,7 @@ const fixedPool = new FixedThreadPool( }, errorHandler: (e: Error) => { console.error(e) - } + }, } ) @@ -39,7 +39,7 @@ const dynamicPool = new DynamicThreadPool( }, errorHandler: (e: Error) => { console.error(e) - } + }, } ) diff --git a/examples/typescript/smtp-client-pool/package.json b/examples/typescript/smtp-client-pool/package.json index 99b9ed89..e1907d0b 100644 --- a/examples/typescript/smtp-client-pool/package.json +++ b/examples/typescript/smtp-client-pool/package.json @@ -6,10 +6,10 @@ "main": "dist/main.js", "type": "module", "volta": { - "node": "22.0.0", - "pnpm": "9.0.6" + "node": "22.2.0", + "pnpm": "9.1.4" }, - "packageManager": "pnpm@9.0.6", + "packageManager": "pnpm@9.1.4", "scripts": { "build": "pnpm build:clean && tsc", "build:clean": "tsc --build --clean", @@ -21,11 +21,11 @@ "license": "ISC", "dependencies": { "nodemailer": "^6.9.13", - "poolifier": "^4.0.1" + "poolifier": "^4.0.13" }, "devDependencies": { - "@types/node": "^20.12.8", - "@types/nodemailer": "^6.4.14", + "@types/node": "^20.14.0", + "@types/nodemailer": "^6.4.15", "typescript": "^5.4.5" } } diff --git a/examples/typescript/smtp-client-pool/pnpm-lock.yaml b/examples/typescript/smtp-client-pool/pnpm-lock.yaml index af80d0a9..6186f00b 100644 --- a/examples/typescript/smtp-client-pool/pnpm-lock.yaml +++ b/examples/typescript/smtp-client-pool/pnpm-lock.yaml @@ -12,33 +12,33 @@ importers: specifier: ^6.9.13 version: 6.9.13 poolifier: - specifier: ^4.0.1 - version: 4.0.1 + specifier: ^4.0.13 + version: 4.0.13 devDependencies: '@types/node': - specifier: ^20.12.8 - version: 20.12.8 + specifier: ^20.14.0 + version: 20.14.0 '@types/nodemailer': - specifier: ^6.4.14 - version: 6.4.14 + specifier: ^6.4.15 + version: 6.4.15 typescript: specifier: ^5.4.5 version: 5.4.5 packages: - '@types/node@20.12.8': - resolution: {integrity: sha512-NU0rJLJnshZWdE/097cdCBbyW1h4hEg0xpovcoAQYHl8dnEyp/NAOiE45pvc+Bd1Dt+2r94v2eGFpQJ4R7g+2w==} + '@types/node@20.14.0': + resolution: {integrity: sha512-5cHBxFGJx6L4s56Bubp4fglrEpmyJypsqI6RgzMfBHWUJQGWAAi8cWcgetEbZXHYXo9C2Fa4EEds/uSyS4cxmA==} - '@types/nodemailer@6.4.14': - resolution: {integrity: sha512-fUWthHO9k9DSdPCSPRqcu6TWhYyxTBg382vlNIttSe9M7XfsT06y0f24KHXtbnijPGGRIcVvdKHTNikOI6qiHA==} + '@types/nodemailer@6.4.15': + resolution: {integrity: sha512-0EBJxawVNjPkng1zm2vopRctuWVCxk34JcIlRuXSf54habUWdz1FB7wHDqOqvDa8Mtpt0Q3LTXQkAs2LNyK5jQ==} nodemailer@6.9.13: resolution: {integrity: sha512-7o38Yogx6krdoBf3jCAqnIN4oSQFx+fMa0I7dK1D+me9kBxx12D+/33wSb+fhOCtIxvYJ+4x4IMEhmhCKfAiOA==} engines: {node: '>=6.0.0'} - poolifier@4.0.1: - resolution: {integrity: sha512-1izVxQOC3yonTN1I51tualsPfZ0iUN+r5zaKY/+vEWIa0cUJMPgi1hN86DL4kwCTwr65JZ42ZrxnQWRmdnzRpA==} + poolifier@4.0.13: + resolution: {integrity: sha512-GPITJo3LZvZXGNDWn6eDpOJ+F5+rq4tvyoXFQJfyJ92w0qr4evjoOX9hymwMGmv8TuifFMIBmgCdcTvoxRdMgA==} engines: {node: '>=18.0.0', pnpm: '>=9.0.0'} typescript@5.4.5: @@ -51,17 +51,17 @@ packages: snapshots: - '@types/node@20.12.8': + '@types/node@20.14.0': dependencies: undici-types: 5.26.5 - '@types/nodemailer@6.4.14': + '@types/nodemailer@6.4.15': dependencies: - '@types/node': 20.12.8 + '@types/node': 20.14.0 nodemailer@6.9.13: {} - poolifier@4.0.1: {} + poolifier@4.0.13: {} typescript@5.4.5: {} diff --git a/examples/typescript/smtp-client-pool/src/main.ts b/examples/typescript/smtp-client-pool/src/main.ts index 620bdb94..4d1f2ea8 100644 --- a/examples/typescript/smtp-client-pool/src/main.ts +++ b/examples/typescript/smtp-client-pool/src/main.ts @@ -14,16 +14,16 @@ for (const to of tos) { secure: true, auth: { user: 'REPLACE-WITH-YOUR-ALIAS@DOMAIN.TLD', - pass: 'REPLACE-WITH-YOUR-GENERATED-PASSWORD' - } + pass: 'REPLACE-WITH-YOUR-GENERATED-PASSWORD', + }, }, mail: { from: '"Foo" ', to, subject: 'Hello', text: 'Hello world?', - html: 'Hello world?' - } + html: 'Hello world?', + }, }) ) } @@ -32,9 +32,9 @@ try { await Promise.all(smtpClientPoolPromises) const elapsedTime = performance.now() - now console.info( - `Send in parallel in ${elapsedTime.toFixed(2)}ms ${ - tos.length - } mails with SMTP client pool` + `Send in parallel in ${elapsedTime.toFixed( + 2 + )}ms ${tos.length.toString()} mails with SMTP client pool` ) } catch (error) { console.error(error) diff --git a/examples/typescript/smtp-client-pool/src/pool.ts b/examples/typescript/smtp-client-pool/src/pool.ts index 315bf4ea..74783703 100644 --- a/examples/typescript/smtp-client-pool/src/pool.ts +++ b/examples/typescript/smtp-client-pool/src/pool.ts @@ -12,14 +12,14 @@ const workerFile = join( ) export const smtpClientPool = new DynamicThreadPool< -WorkerData, -SMTPTransport.SentMessageInfo + WorkerData, + SMTPTransport.SentMessageInfo >(0, availableParallelism(), workerFile, { enableTasksQueue: true, tasksQueueOptions: { - concurrency: 8 + concurrency: 8, }, errorHandler: (e: Error) => { console.error('Thread worker error:', e) - } + }, }) diff --git a/examples/typescript/smtp-client-pool/src/worker.ts b/examples/typescript/smtp-client-pool/src/worker.ts index 62288635..e2667b32 100644 --- a/examples/typescript/smtp-client-pool/src/worker.ts +++ b/examples/typescript/smtp-client-pool/src/worker.ts @@ -5,16 +5,17 @@ import { ThreadWorker } from 'poolifier' import type { WorkerData } from './types.js' class SmtpClientWorker extends ThreadWorker< -WorkerData, -SMTPTransport.SentMessageInfo + WorkerData, + SMTPTransport.SentMessageInfo > { public constructor () { super({ nodemailer: async (workerData?: WorkerData) => { return await createTransport(workerData?.smtpTransport).sendMail( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion workerData!.mail ) - } + }, }) } } diff --git a/examples/typescript/websocket-server-pool/ws-cluster/package.json b/examples/typescript/websocket-server-pool/ws-cluster/package.json index af425ef0..f333b9d7 100644 --- a/examples/typescript/websocket-server-pool/ws-cluster/package.json +++ b/examples/typescript/websocket-server-pool/ws-cluster/package.json @@ -6,10 +6,10 @@ "main": "dist/main.js", "type": "module", "volta": { - "node": "22.0.0", - "pnpm": "9.0.6" + "node": "22.2.0", + "pnpm": "9.1.4" }, - "packageManager": "pnpm@9.0.6", + "packageManager": "pnpm@9.1.4", "scripts": { "build": "rollup --config --configPlugin typescript", "start": "node --enable-source-maps dist/main.cjs", @@ -21,20 +21,20 @@ "author": "", "license": "ISC", "dependencies": { - "poolifier": "^4.0.1", + "poolifier": "^4.0.13", "ws": "^8.17.0" }, "devDependencies": { "@rollup/plugin-typescript": "^11.1.6", - "@types/node": "^20.12.8", + "@types/node": "^20.14.0", "@types/ws": "^8.5.10", - "rollup": "^4.17.2", + "rollup": "^4.18.0", "rollup-plugin-delete": "^2.0.0", "tslib": "^2.6.2", "typescript": "^5.4.5" }, "optionalDependencies": { "bufferutil": "^4.0.8", - "utf-8-validate": "^6.0.3" + "utf-8-validate": "^6.0.4" } } diff --git a/examples/typescript/websocket-server-pool/ws-cluster/pnpm-lock.yaml b/examples/typescript/websocket-server-pool/ws-cluster/pnpm-lock.yaml index cfbce80a..1b72e92b 100644 --- a/examples/typescript/websocket-server-pool/ws-cluster/pnpm-lock.yaml +++ b/examples/typescript/websocket-server-pool/ws-cluster/pnpm-lock.yaml @@ -9,31 +9,31 @@ importers: .: dependencies: poolifier: - specifier: ^4.0.1 - version: 4.0.1 + specifier: ^4.0.13 + version: 4.0.13 ws: specifier: ^8.17.0 - version: 8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.3) + version: 8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4) optionalDependencies: bufferutil: specifier: ^4.0.8 version: 4.0.8 utf-8-validate: - specifier: ^6.0.3 - version: 6.0.3 + specifier: ^6.0.4 + version: 6.0.4 devDependencies: '@rollup/plugin-typescript': specifier: ^11.1.6 - version: 11.1.6(rollup@4.17.2)(tslib@2.6.2)(typescript@5.4.5) + version: 11.1.6(rollup@4.18.0)(tslib@2.6.2)(typescript@5.4.5) '@types/node': - specifier: ^20.12.8 - version: 20.12.8 + specifier: ^20.14.0 + version: 20.14.0 '@types/ws': specifier: ^8.5.10 version: 8.5.10 rollup: - specifier: ^4.17.2 - version: 4.17.2 + specifier: ^4.18.0 + version: 4.18.0 rollup-plugin-delete: specifier: ^2.0.0 version: 2.0.0 @@ -80,83 +80,83 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.17.2': - resolution: {integrity: sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==} + '@rollup/rollup-android-arm-eabi@4.18.0': + resolution: {integrity: sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.17.2': - resolution: {integrity: sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==} + '@rollup/rollup-android-arm64@4.18.0': + resolution: {integrity: sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.17.2': - resolution: {integrity: sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==} + '@rollup/rollup-darwin-arm64@4.18.0': + resolution: {integrity: sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.17.2': - resolution: {integrity: sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==} + '@rollup/rollup-darwin-x64@4.18.0': + resolution: {integrity: sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==} cpu: [x64] os: [darwin] - '@rollup/rollup-linux-arm-gnueabihf@4.17.2': - resolution: {integrity: sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==} + '@rollup/rollup-linux-arm-gnueabihf@4.18.0': + resolution: {integrity: sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.17.2': - resolution: {integrity: sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==} + '@rollup/rollup-linux-arm-musleabihf@4.18.0': + resolution: {integrity: sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.17.2': - resolution: {integrity: sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==} + '@rollup/rollup-linux-arm64-gnu@4.18.0': + resolution: {integrity: sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.17.2': - resolution: {integrity: sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==} + '@rollup/rollup-linux-arm64-musl@4.18.0': + resolution: {integrity: sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.17.2': - resolution: {integrity: sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==} + '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': + resolution: {integrity: sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.17.2': - resolution: {integrity: sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==} + '@rollup/rollup-linux-riscv64-gnu@4.18.0': + resolution: {integrity: sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.17.2': - resolution: {integrity: sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==} + '@rollup/rollup-linux-s390x-gnu@4.18.0': + resolution: {integrity: sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.17.2': - resolution: {integrity: sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==} + '@rollup/rollup-linux-x64-gnu@4.18.0': + resolution: {integrity: sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.17.2': - resolution: {integrity: sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==} + '@rollup/rollup-linux-x64-musl@4.18.0': + resolution: {integrity: sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.17.2': - resolution: {integrity: sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==} + '@rollup/rollup-win32-arm64-msvc@4.18.0': + resolution: {integrity: sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.17.2': - resolution: {integrity: sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==} + '@rollup/rollup-win32-ia32-msvc@4.18.0': + resolution: {integrity: sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.17.2': - resolution: {integrity: sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==} + '@rollup/rollup-win32-x64-msvc@4.18.0': + resolution: {integrity: sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==} cpu: [x64] os: [win32] @@ -169,8 +169,8 @@ packages: '@types/minimatch@5.1.2': resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} - '@types/node@20.12.8': - resolution: {integrity: sha512-NU0rJLJnshZWdE/097cdCBbyW1h4hEg0xpovcoAQYHl8dnEyp/NAOiE45pvc+Bd1Dt+2r94v2eGFpQJ4R7g+2w==} + '@types/node@20.14.0': + resolution: {integrity: sha512-5cHBxFGJx6L4s56Bubp4fglrEpmyJypsqI6RgzMfBHWUJQGWAAi8cWcgetEbZXHYXo9C2Fa4EEds/uSyS4cxmA==} '@types/ws@8.5.10': resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} @@ -189,8 +189,8 @@ packages: brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} bufferutil@4.0.8: @@ -222,8 +222,8 @@ packages: fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} fs.realpath@1.0.0: @@ -243,6 +243,7 @@ packages: glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported globby@10.0.2: resolution: {integrity: sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==} @@ -265,6 +266,7 @@ packages: inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -296,15 +298,15 @@ packages: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} - micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + micromatch@4.0.7: + resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} engines: {node: '>=8.6'} minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - node-gyp-build@4.8.0: - resolution: {integrity: sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==} + node-gyp-build@4.8.1: + resolution: {integrity: sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==} hasBin: true once@1.4.0: @@ -329,8 +331,8 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} - poolifier@4.0.1: - resolution: {integrity: sha512-1izVxQOC3yonTN1I51tualsPfZ0iUN+r5zaKY/+vEWIa0cUJMPgi1hN86DL4kwCTwr65JZ42ZrxnQWRmdnzRpA==} + poolifier@4.0.13: + resolution: {integrity: sha512-GPITJo3LZvZXGNDWn6eDpOJ+F5+rq4tvyoXFQJfyJ92w0qr4evjoOX9hymwMGmv8TuifFMIBmgCdcTvoxRdMgA==} engines: {node: '>=18.0.0', pnpm: '>=9.0.0'} queue-microtask@1.2.3: @@ -346,14 +348,15 @@ packages: rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true rollup-plugin-delete@2.0.0: resolution: {integrity: sha512-/VpLMtDy+8wwRlDANuYmDa9ss/knGsAgrDhM+tEwB1npHwNu4DYNmDfUL55csse/GHs9Q+SMT/rw9uiaZ3pnzA==} engines: {node: '>=10'} - rollup@4.17.2: - resolution: {integrity: sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==} + rollup@4.18.0: + resolution: {integrity: sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -383,8 +386,8 @@ packages: undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - utf-8-validate@6.0.3: - resolution: {integrity: sha512-uIuGf9TWQ/y+0Lp+KGZCMuJWc3N9BHA+l/UmHd/oUHwJJDeysyTRxNQVkbzsIWfGFbRe3OcgML/i0mvVRPOyDA==} + utf-8-validate@6.0.4: + resolution: {integrity: sha512-xu9GQDeFp+eZ6LnCywXN/zBancWvOpUMzgjLPSjy4BRHSmTelvn2E0DG0o1sTiw5hkCKBHo8rwSKncfRfv2EEQ==} engines: {node: '>=6.14.2'} wrappy@1.0.2: @@ -416,69 +419,69 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 - '@rollup/plugin-typescript@11.1.6(rollup@4.17.2)(tslib@2.6.2)(typescript@5.4.5)': + '@rollup/plugin-typescript@11.1.6(rollup@4.18.0)(tslib@2.6.2)(typescript@5.4.5)': dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.17.2) + '@rollup/pluginutils': 5.1.0(rollup@4.18.0) resolve: 1.22.8 typescript: 5.4.5 optionalDependencies: - rollup: 4.17.2 + rollup: 4.18.0 tslib: 2.6.2 - '@rollup/pluginutils@5.1.0(rollup@4.17.2)': + '@rollup/pluginutils@5.1.0(rollup@4.18.0)': dependencies: '@types/estree': 1.0.5 estree-walker: 2.0.2 picomatch: 2.3.1 optionalDependencies: - rollup: 4.17.2 + rollup: 4.18.0 - '@rollup/rollup-android-arm-eabi@4.17.2': + '@rollup/rollup-android-arm-eabi@4.18.0': optional: true - '@rollup/rollup-android-arm64@4.17.2': + '@rollup/rollup-android-arm64@4.18.0': optional: true - '@rollup/rollup-darwin-arm64@4.17.2': + '@rollup/rollup-darwin-arm64@4.18.0': optional: true - '@rollup/rollup-darwin-x64@4.17.2': + '@rollup/rollup-darwin-x64@4.18.0': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.17.2': + '@rollup/rollup-linux-arm-gnueabihf@4.18.0': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.17.2': + '@rollup/rollup-linux-arm-musleabihf@4.18.0': optional: true - '@rollup/rollup-linux-arm64-gnu@4.17.2': + '@rollup/rollup-linux-arm64-gnu@4.18.0': optional: true - '@rollup/rollup-linux-arm64-musl@4.17.2': + '@rollup/rollup-linux-arm64-musl@4.18.0': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.17.2': + '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.17.2': + '@rollup/rollup-linux-riscv64-gnu@4.18.0': optional: true - '@rollup/rollup-linux-s390x-gnu@4.17.2': + '@rollup/rollup-linux-s390x-gnu@4.18.0': optional: true - '@rollup/rollup-linux-x64-gnu@4.17.2': + '@rollup/rollup-linux-x64-gnu@4.18.0': optional: true - '@rollup/rollup-linux-x64-musl@4.17.2': + '@rollup/rollup-linux-x64-musl@4.18.0': optional: true - '@rollup/rollup-win32-arm64-msvc@4.17.2': + '@rollup/rollup-win32-arm64-msvc@4.18.0': optional: true - '@rollup/rollup-win32-ia32-msvc@4.17.2': + '@rollup/rollup-win32-ia32-msvc@4.18.0': optional: true - '@rollup/rollup-win32-x64-msvc@4.17.2': + '@rollup/rollup-win32-x64-msvc@4.18.0': optional: true '@types/estree@1.0.5': {} @@ -486,17 +489,17 @@ snapshots: '@types/glob@7.2.0': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 20.12.8 + '@types/node': 20.14.0 '@types/minimatch@5.1.2': {} - '@types/node@20.12.8': + '@types/node@20.14.0': dependencies: undici-types: 5.26.5 '@types/ws@8.5.10': dependencies: - '@types/node': 20.12.8 + '@types/node': 20.14.0 aggregate-error@3.1.0: dependencies: @@ -512,13 +515,13 @@ snapshots: balanced-match: 1.0.2 concat-map: 0.0.1 - braces@3.0.2: + braces@3.0.3: dependencies: - fill-range: 7.0.1 + fill-range: 7.1.1 bufferutil@4.0.8: dependencies: - node-gyp-build: 4.8.0 + node-gyp-build: 4.8.1 optional: true clean-stack@2.2.0: {} @@ -548,13 +551,13 @@ snapshots: '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 - micromatch: 4.0.5 + micromatch: 4.0.7 fastq@1.17.1: dependencies: reusify: 1.0.4 - fill-range@7.0.1: + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -624,16 +627,16 @@ snapshots: merge2@1.4.1: {} - micromatch@4.0.5: + micromatch@4.0.7: dependencies: - braces: 3.0.2 + braces: 3.0.3 picomatch: 2.3.1 minimatch@3.1.2: dependencies: brace-expansion: 1.1.11 - node-gyp-build@4.8.0: + node-gyp-build@4.8.1: optional: true once@1.4.0: @@ -652,7 +655,7 @@ snapshots: picomatch@2.3.1: {} - poolifier@4.0.1: {} + poolifier@4.0.13: {} queue-microtask@1.2.3: {} @@ -672,26 +675,26 @@ snapshots: dependencies: del: 5.1.0 - rollup@4.17.2: + rollup@4.18.0: dependencies: '@types/estree': 1.0.5 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.17.2 - '@rollup/rollup-android-arm64': 4.17.2 - '@rollup/rollup-darwin-arm64': 4.17.2 - '@rollup/rollup-darwin-x64': 4.17.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.17.2 - '@rollup/rollup-linux-arm-musleabihf': 4.17.2 - '@rollup/rollup-linux-arm64-gnu': 4.17.2 - '@rollup/rollup-linux-arm64-musl': 4.17.2 - '@rollup/rollup-linux-powerpc64le-gnu': 4.17.2 - '@rollup/rollup-linux-riscv64-gnu': 4.17.2 - '@rollup/rollup-linux-s390x-gnu': 4.17.2 - '@rollup/rollup-linux-x64-gnu': 4.17.2 - '@rollup/rollup-linux-x64-musl': 4.17.2 - '@rollup/rollup-win32-arm64-msvc': 4.17.2 - '@rollup/rollup-win32-ia32-msvc': 4.17.2 - '@rollup/rollup-win32-x64-msvc': 4.17.2 + '@rollup/rollup-android-arm-eabi': 4.18.0 + '@rollup/rollup-android-arm64': 4.18.0 + '@rollup/rollup-darwin-arm64': 4.18.0 + '@rollup/rollup-darwin-x64': 4.18.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.18.0 + '@rollup/rollup-linux-arm-musleabihf': 4.18.0 + '@rollup/rollup-linux-arm64-gnu': 4.18.0 + '@rollup/rollup-linux-arm64-musl': 4.18.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.18.0 + '@rollup/rollup-linux-riscv64-gnu': 4.18.0 + '@rollup/rollup-linux-s390x-gnu': 4.18.0 + '@rollup/rollup-linux-x64-gnu': 4.18.0 + '@rollup/rollup-linux-x64-musl': 4.18.0 + '@rollup/rollup-win32-arm64-msvc': 4.18.0 + '@rollup/rollup-win32-ia32-msvc': 4.18.0 + '@rollup/rollup-win32-x64-msvc': 4.18.0 fsevents: 2.3.3 run-parallel@1.2.0: @@ -712,14 +715,14 @@ snapshots: undici-types@5.26.5: {} - utf-8-validate@6.0.3: + utf-8-validate@6.0.4: dependencies: - node-gyp-build: 4.8.0 + node-gyp-build: 4.8.1 optional: true wrappy@1.0.2: {} - ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.3): + ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4): optionalDependencies: bufferutil: 4.0.8 - utf-8-validate: 6.0.3 + utf-8-validate: 6.0.4 diff --git a/examples/typescript/websocket-server-pool/ws-cluster/requests.js b/examples/typescript/websocket-server-pool/ws-cluster/requests.js index 9beb2b78..2c73376f 100644 --- a/examples/typescript/websocket-server-pool/ws-cluster/requests.js +++ b/examples/typescript/websocket-server-pool/ws-cluster/requests.js @@ -1,4 +1,3 @@ -// eslint-disable-next-line import/no-unresolved, n/no-missing-import import { WebSocket } from 'ws' const ws = new WebSocket('ws://localhost:8080') diff --git a/examples/typescript/websocket-server-pool/ws-cluster/rollup.config.ts b/examples/typescript/websocket-server-pool/ws-cluster/rollup.config.ts index a4f72126..4080e1ac 100644 --- a/examples/typescript/websocket-server-pool/ws-cluster/rollup.config.ts +++ b/examples/typescript/websocket-server-pool/ws-cluster/rollup.config.ts @@ -11,19 +11,19 @@ export default defineConfig({ dir: './dist', sourcemap: true, entryFileNames: '[name].cjs', - chunkFileNames: '[name]-[hash].cjs' + chunkFileNames: '[name]-[hash].cjs', }, { format: 'esm', dir: './dist', - sourcemap: true - } + sourcemap: true, + }, ], external: [/^node:*/, 'poolifier', 'ws'], plugins: [ typescript(), del({ - targets: ['./dist/*'] - }) - ] + targets: ['./dist/*'], + }), + ], }) diff --git a/examples/typescript/websocket-server-pool/ws-cluster/src/main.ts b/examples/typescript/websocket-server-pool/ws-cluster/src/main.ts index 16dd38d6..6e108d6f 100644 --- a/examples/typescript/websocket-server-pool/ws-cluster/src/main.ts +++ b/examples/typescript/websocket-server-pool/ws-cluster/src/main.ts @@ -21,7 +21,8 @@ const pool = new FixedClusterPool( .then(response => { if (response.status) { console.info( - `WebSocket server is listening in cluster worker on port ${response.port}` + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + `WebSocket server is listening in cluster worker on port ${response.port?.toString()}` ) } return undefined @@ -35,6 +36,6 @@ const pool = new FixedClusterPool( }, errorHandler: (e: Error) => { console.error('Cluster worker error', e) - } + }, } ) diff --git a/examples/typescript/websocket-server-pool/ws-cluster/src/worker.ts b/examples/typescript/websocket-server-pool/ws-cluster/src/worker.ts index 232382f6..d9091e7f 100644 --- a/examples/typescript/websocket-server-pool/ws-cluster/src/worker.ts +++ b/examples/typescript/websocket-server-pool/ws-cluster/src/worker.ts @@ -6,7 +6,7 @@ import { type MessagePayload, MessageType, type WorkerData, - type WorkerResponse + type WorkerResponse, } from './types.js' class WebSocketServerWorker extends ClusterWorker { @@ -28,11 +28,12 @@ class WebSocketServerWorker extends ClusterWorker { private static readonly startWebSocketServer = ( workerData?: WorkerData ): WorkerResponse => { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const { port } = workerData! WebSocketServerWorker.wss = new WebSocketServer({ port }, () => { console.info( - `⚡️[ws server]: WebSocket server is started in cluster worker at ws://localhost:${port}/` + `⚡️[ws server]: WebSocket server is started in cluster worker at ws://localhost:${port.toString()}/` ) }) @@ -48,7 +49,7 @@ class WebSocketServerWorker extends ClusterWorker { ws.send( JSON.stringify({ type: MessageType.echo, - data + data, }) ) break @@ -58,10 +59,11 @@ class WebSocketServerWorker extends ClusterWorker { { type: MessageType.factorial, data: { - number: WebSocketServerWorker.factorial(data.number!) - } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + number: WebSocketServerWorker.factorial(data.number!), + }, }, - (_, v) => (typeof v === 'bigint' ? v.toString() : v) + (_, v: unknown) => (typeof v === 'bigint' ? v.toString() : v) ) ) break @@ -70,7 +72,7 @@ class WebSocketServerWorker extends ClusterWorker { }) return { status: true, - port: WebSocketServerWorker.wss.options.port + port: WebSocketServerWorker.wss.options.port, } } @@ -78,7 +80,7 @@ class WebSocketServerWorker extends ClusterWorker { super(WebSocketServerWorker.startWebSocketServer, { killHandler: () => { WebSocketServerWorker.wss.close() - } + }, }) } } diff --git a/examples/typescript/websocket-server-pool/ws-hybrid/package.json b/examples/typescript/websocket-server-pool/ws-hybrid/package.json index b6135dbe..cc0319c6 100644 --- a/examples/typescript/websocket-server-pool/ws-hybrid/package.json +++ b/examples/typescript/websocket-server-pool/ws-hybrid/package.json @@ -6,10 +6,10 @@ "main": "dist/main.js", "type": "module", "volta": { - "node": "22.0.0", - "pnpm": "9.0.6" + "node": "22.2.0", + "pnpm": "9.1.4" }, - "packageManager": "pnpm@9.0.6", + "packageManager": "pnpm@9.1.4", "scripts": { "build": "rollup --config --configPlugin typescript", "start": "node --enable-source-maps dist/main.cjs", @@ -21,20 +21,20 @@ "author": "", "license": "ISC", "dependencies": { - "poolifier": "^4.0.1", + "poolifier": "^4.0.13", "ws": "^8.17.0" }, "devDependencies": { "@rollup/plugin-typescript": "^11.1.6", - "@types/node": "^20.12.8", + "@types/node": "^20.14.0", "@types/ws": "^8.5.10", - "rollup": "^4.17.2", + "rollup": "^4.18.0", "rollup-plugin-delete": "^2.0.0", "tslib": "^2.6.2", "typescript": "^5.4.5" }, "optionalDependencies": { "bufferutil": "^4.0.8", - "utf-8-validate": "^6.0.3" + "utf-8-validate": "^6.0.4" } } diff --git a/examples/typescript/websocket-server-pool/ws-hybrid/pnpm-lock.yaml b/examples/typescript/websocket-server-pool/ws-hybrid/pnpm-lock.yaml index cfbce80a..1b72e92b 100644 --- a/examples/typescript/websocket-server-pool/ws-hybrid/pnpm-lock.yaml +++ b/examples/typescript/websocket-server-pool/ws-hybrid/pnpm-lock.yaml @@ -9,31 +9,31 @@ importers: .: dependencies: poolifier: - specifier: ^4.0.1 - version: 4.0.1 + specifier: ^4.0.13 + version: 4.0.13 ws: specifier: ^8.17.0 - version: 8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.3) + version: 8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4) optionalDependencies: bufferutil: specifier: ^4.0.8 version: 4.0.8 utf-8-validate: - specifier: ^6.0.3 - version: 6.0.3 + specifier: ^6.0.4 + version: 6.0.4 devDependencies: '@rollup/plugin-typescript': specifier: ^11.1.6 - version: 11.1.6(rollup@4.17.2)(tslib@2.6.2)(typescript@5.4.5) + version: 11.1.6(rollup@4.18.0)(tslib@2.6.2)(typescript@5.4.5) '@types/node': - specifier: ^20.12.8 - version: 20.12.8 + specifier: ^20.14.0 + version: 20.14.0 '@types/ws': specifier: ^8.5.10 version: 8.5.10 rollup: - specifier: ^4.17.2 - version: 4.17.2 + specifier: ^4.18.0 + version: 4.18.0 rollup-plugin-delete: specifier: ^2.0.0 version: 2.0.0 @@ -80,83 +80,83 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.17.2': - resolution: {integrity: sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==} + '@rollup/rollup-android-arm-eabi@4.18.0': + resolution: {integrity: sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.17.2': - resolution: {integrity: sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==} + '@rollup/rollup-android-arm64@4.18.0': + resolution: {integrity: sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.17.2': - resolution: {integrity: sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==} + '@rollup/rollup-darwin-arm64@4.18.0': + resolution: {integrity: sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.17.2': - resolution: {integrity: sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==} + '@rollup/rollup-darwin-x64@4.18.0': + resolution: {integrity: sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==} cpu: [x64] os: [darwin] - '@rollup/rollup-linux-arm-gnueabihf@4.17.2': - resolution: {integrity: sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==} + '@rollup/rollup-linux-arm-gnueabihf@4.18.0': + resolution: {integrity: sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.17.2': - resolution: {integrity: sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==} + '@rollup/rollup-linux-arm-musleabihf@4.18.0': + resolution: {integrity: sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.17.2': - resolution: {integrity: sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==} + '@rollup/rollup-linux-arm64-gnu@4.18.0': + resolution: {integrity: sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.17.2': - resolution: {integrity: sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==} + '@rollup/rollup-linux-arm64-musl@4.18.0': + resolution: {integrity: sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.17.2': - resolution: {integrity: sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==} + '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': + resolution: {integrity: sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.17.2': - resolution: {integrity: sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==} + '@rollup/rollup-linux-riscv64-gnu@4.18.0': + resolution: {integrity: sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.17.2': - resolution: {integrity: sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==} + '@rollup/rollup-linux-s390x-gnu@4.18.0': + resolution: {integrity: sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.17.2': - resolution: {integrity: sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==} + '@rollup/rollup-linux-x64-gnu@4.18.0': + resolution: {integrity: sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.17.2': - resolution: {integrity: sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==} + '@rollup/rollup-linux-x64-musl@4.18.0': + resolution: {integrity: sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.17.2': - resolution: {integrity: sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==} + '@rollup/rollup-win32-arm64-msvc@4.18.0': + resolution: {integrity: sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.17.2': - resolution: {integrity: sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==} + '@rollup/rollup-win32-ia32-msvc@4.18.0': + resolution: {integrity: sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.17.2': - resolution: {integrity: sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==} + '@rollup/rollup-win32-x64-msvc@4.18.0': + resolution: {integrity: sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==} cpu: [x64] os: [win32] @@ -169,8 +169,8 @@ packages: '@types/minimatch@5.1.2': resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} - '@types/node@20.12.8': - resolution: {integrity: sha512-NU0rJLJnshZWdE/097cdCBbyW1h4hEg0xpovcoAQYHl8dnEyp/NAOiE45pvc+Bd1Dt+2r94v2eGFpQJ4R7g+2w==} + '@types/node@20.14.0': + resolution: {integrity: sha512-5cHBxFGJx6L4s56Bubp4fglrEpmyJypsqI6RgzMfBHWUJQGWAAi8cWcgetEbZXHYXo9C2Fa4EEds/uSyS4cxmA==} '@types/ws@8.5.10': resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} @@ -189,8 +189,8 @@ packages: brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} bufferutil@4.0.8: @@ -222,8 +222,8 @@ packages: fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} fs.realpath@1.0.0: @@ -243,6 +243,7 @@ packages: glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported globby@10.0.2: resolution: {integrity: sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==} @@ -265,6 +266,7 @@ packages: inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -296,15 +298,15 @@ packages: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} - micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + micromatch@4.0.7: + resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} engines: {node: '>=8.6'} minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - node-gyp-build@4.8.0: - resolution: {integrity: sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==} + node-gyp-build@4.8.1: + resolution: {integrity: sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==} hasBin: true once@1.4.0: @@ -329,8 +331,8 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} - poolifier@4.0.1: - resolution: {integrity: sha512-1izVxQOC3yonTN1I51tualsPfZ0iUN+r5zaKY/+vEWIa0cUJMPgi1hN86DL4kwCTwr65JZ42ZrxnQWRmdnzRpA==} + poolifier@4.0.13: + resolution: {integrity: sha512-GPITJo3LZvZXGNDWn6eDpOJ+F5+rq4tvyoXFQJfyJ92w0qr4evjoOX9hymwMGmv8TuifFMIBmgCdcTvoxRdMgA==} engines: {node: '>=18.0.0', pnpm: '>=9.0.0'} queue-microtask@1.2.3: @@ -346,14 +348,15 @@ packages: rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true rollup-plugin-delete@2.0.0: resolution: {integrity: sha512-/VpLMtDy+8wwRlDANuYmDa9ss/knGsAgrDhM+tEwB1npHwNu4DYNmDfUL55csse/GHs9Q+SMT/rw9uiaZ3pnzA==} engines: {node: '>=10'} - rollup@4.17.2: - resolution: {integrity: sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==} + rollup@4.18.0: + resolution: {integrity: sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -383,8 +386,8 @@ packages: undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - utf-8-validate@6.0.3: - resolution: {integrity: sha512-uIuGf9TWQ/y+0Lp+KGZCMuJWc3N9BHA+l/UmHd/oUHwJJDeysyTRxNQVkbzsIWfGFbRe3OcgML/i0mvVRPOyDA==} + utf-8-validate@6.0.4: + resolution: {integrity: sha512-xu9GQDeFp+eZ6LnCywXN/zBancWvOpUMzgjLPSjy4BRHSmTelvn2E0DG0o1sTiw5hkCKBHo8rwSKncfRfv2EEQ==} engines: {node: '>=6.14.2'} wrappy@1.0.2: @@ -416,69 +419,69 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 - '@rollup/plugin-typescript@11.1.6(rollup@4.17.2)(tslib@2.6.2)(typescript@5.4.5)': + '@rollup/plugin-typescript@11.1.6(rollup@4.18.0)(tslib@2.6.2)(typescript@5.4.5)': dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.17.2) + '@rollup/pluginutils': 5.1.0(rollup@4.18.0) resolve: 1.22.8 typescript: 5.4.5 optionalDependencies: - rollup: 4.17.2 + rollup: 4.18.0 tslib: 2.6.2 - '@rollup/pluginutils@5.1.0(rollup@4.17.2)': + '@rollup/pluginutils@5.1.0(rollup@4.18.0)': dependencies: '@types/estree': 1.0.5 estree-walker: 2.0.2 picomatch: 2.3.1 optionalDependencies: - rollup: 4.17.2 + rollup: 4.18.0 - '@rollup/rollup-android-arm-eabi@4.17.2': + '@rollup/rollup-android-arm-eabi@4.18.0': optional: true - '@rollup/rollup-android-arm64@4.17.2': + '@rollup/rollup-android-arm64@4.18.0': optional: true - '@rollup/rollup-darwin-arm64@4.17.2': + '@rollup/rollup-darwin-arm64@4.18.0': optional: true - '@rollup/rollup-darwin-x64@4.17.2': + '@rollup/rollup-darwin-x64@4.18.0': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.17.2': + '@rollup/rollup-linux-arm-gnueabihf@4.18.0': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.17.2': + '@rollup/rollup-linux-arm-musleabihf@4.18.0': optional: true - '@rollup/rollup-linux-arm64-gnu@4.17.2': + '@rollup/rollup-linux-arm64-gnu@4.18.0': optional: true - '@rollup/rollup-linux-arm64-musl@4.17.2': + '@rollup/rollup-linux-arm64-musl@4.18.0': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.17.2': + '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.17.2': + '@rollup/rollup-linux-riscv64-gnu@4.18.0': optional: true - '@rollup/rollup-linux-s390x-gnu@4.17.2': + '@rollup/rollup-linux-s390x-gnu@4.18.0': optional: true - '@rollup/rollup-linux-x64-gnu@4.17.2': + '@rollup/rollup-linux-x64-gnu@4.18.0': optional: true - '@rollup/rollup-linux-x64-musl@4.17.2': + '@rollup/rollup-linux-x64-musl@4.18.0': optional: true - '@rollup/rollup-win32-arm64-msvc@4.17.2': + '@rollup/rollup-win32-arm64-msvc@4.18.0': optional: true - '@rollup/rollup-win32-ia32-msvc@4.17.2': + '@rollup/rollup-win32-ia32-msvc@4.18.0': optional: true - '@rollup/rollup-win32-x64-msvc@4.17.2': + '@rollup/rollup-win32-x64-msvc@4.18.0': optional: true '@types/estree@1.0.5': {} @@ -486,17 +489,17 @@ snapshots: '@types/glob@7.2.0': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 20.12.8 + '@types/node': 20.14.0 '@types/minimatch@5.1.2': {} - '@types/node@20.12.8': + '@types/node@20.14.0': dependencies: undici-types: 5.26.5 '@types/ws@8.5.10': dependencies: - '@types/node': 20.12.8 + '@types/node': 20.14.0 aggregate-error@3.1.0: dependencies: @@ -512,13 +515,13 @@ snapshots: balanced-match: 1.0.2 concat-map: 0.0.1 - braces@3.0.2: + braces@3.0.3: dependencies: - fill-range: 7.0.1 + fill-range: 7.1.1 bufferutil@4.0.8: dependencies: - node-gyp-build: 4.8.0 + node-gyp-build: 4.8.1 optional: true clean-stack@2.2.0: {} @@ -548,13 +551,13 @@ snapshots: '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 - micromatch: 4.0.5 + micromatch: 4.0.7 fastq@1.17.1: dependencies: reusify: 1.0.4 - fill-range@7.0.1: + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -624,16 +627,16 @@ snapshots: merge2@1.4.1: {} - micromatch@4.0.5: + micromatch@4.0.7: dependencies: - braces: 3.0.2 + braces: 3.0.3 picomatch: 2.3.1 minimatch@3.1.2: dependencies: brace-expansion: 1.1.11 - node-gyp-build@4.8.0: + node-gyp-build@4.8.1: optional: true once@1.4.0: @@ -652,7 +655,7 @@ snapshots: picomatch@2.3.1: {} - poolifier@4.0.1: {} + poolifier@4.0.13: {} queue-microtask@1.2.3: {} @@ -672,26 +675,26 @@ snapshots: dependencies: del: 5.1.0 - rollup@4.17.2: + rollup@4.18.0: dependencies: '@types/estree': 1.0.5 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.17.2 - '@rollup/rollup-android-arm64': 4.17.2 - '@rollup/rollup-darwin-arm64': 4.17.2 - '@rollup/rollup-darwin-x64': 4.17.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.17.2 - '@rollup/rollup-linux-arm-musleabihf': 4.17.2 - '@rollup/rollup-linux-arm64-gnu': 4.17.2 - '@rollup/rollup-linux-arm64-musl': 4.17.2 - '@rollup/rollup-linux-powerpc64le-gnu': 4.17.2 - '@rollup/rollup-linux-riscv64-gnu': 4.17.2 - '@rollup/rollup-linux-s390x-gnu': 4.17.2 - '@rollup/rollup-linux-x64-gnu': 4.17.2 - '@rollup/rollup-linux-x64-musl': 4.17.2 - '@rollup/rollup-win32-arm64-msvc': 4.17.2 - '@rollup/rollup-win32-ia32-msvc': 4.17.2 - '@rollup/rollup-win32-x64-msvc': 4.17.2 + '@rollup/rollup-android-arm-eabi': 4.18.0 + '@rollup/rollup-android-arm64': 4.18.0 + '@rollup/rollup-darwin-arm64': 4.18.0 + '@rollup/rollup-darwin-x64': 4.18.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.18.0 + '@rollup/rollup-linux-arm-musleabihf': 4.18.0 + '@rollup/rollup-linux-arm64-gnu': 4.18.0 + '@rollup/rollup-linux-arm64-musl': 4.18.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.18.0 + '@rollup/rollup-linux-riscv64-gnu': 4.18.0 + '@rollup/rollup-linux-s390x-gnu': 4.18.0 + '@rollup/rollup-linux-x64-gnu': 4.18.0 + '@rollup/rollup-linux-x64-musl': 4.18.0 + '@rollup/rollup-win32-arm64-msvc': 4.18.0 + '@rollup/rollup-win32-ia32-msvc': 4.18.0 + '@rollup/rollup-win32-x64-msvc': 4.18.0 fsevents: 2.3.3 run-parallel@1.2.0: @@ -712,14 +715,14 @@ snapshots: undici-types@5.26.5: {} - utf-8-validate@6.0.3: + utf-8-validate@6.0.4: dependencies: - node-gyp-build: 4.8.0 + node-gyp-build: 4.8.1 optional: true wrappy@1.0.2: {} - ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.3): + ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4): optionalDependencies: bufferutil: 4.0.8 - utf-8-validate: 6.0.3 + utf-8-validate: 6.0.4 diff --git a/examples/typescript/websocket-server-pool/ws-hybrid/requests.js b/examples/typescript/websocket-server-pool/ws-hybrid/requests.js index 9beb2b78..2c73376f 100644 --- a/examples/typescript/websocket-server-pool/ws-hybrid/requests.js +++ b/examples/typescript/websocket-server-pool/ws-hybrid/requests.js @@ -1,4 +1,3 @@ -// eslint-disable-next-line import/no-unresolved, n/no-missing-import import { WebSocket } from 'ws' const ws = new WebSocket('ws://localhost:8080') diff --git a/examples/typescript/websocket-server-pool/ws-hybrid/rollup.config.ts b/examples/typescript/websocket-server-pool/ws-hybrid/rollup.config.ts index e96f480b..fb878235 100644 --- a/examples/typescript/websocket-server-pool/ws-hybrid/rollup.config.ts +++ b/examples/typescript/websocket-server-pool/ws-hybrid/rollup.config.ts @@ -6,7 +6,7 @@ export default defineConfig({ input: [ './src/main.ts', './src/websocket-server-worker.ts', - './src/request-handler-worker.ts' + './src/request-handler-worker.ts', ], strictDeprecations: true, output: [ @@ -15,19 +15,19 @@ export default defineConfig({ dir: './dist', sourcemap: true, entryFileNames: '[name].cjs', - chunkFileNames: '[name]-[hash].cjs' + chunkFileNames: '[name]-[hash].cjs', }, { format: 'esm', dir: './dist', - sourcemap: true - } + sourcemap: true, + }, ], external: [/^node:*/, 'poolifier', 'ws'], plugins: [ typescript(), del({ - targets: ['./dist/*'] - }) - ] + targets: ['./dist/*'], + }), + ], }) diff --git a/examples/typescript/websocket-server-pool/ws-hybrid/src/main.ts b/examples/typescript/websocket-server-pool/ws-hybrid/src/main.ts index f1c75506..400f0bee 100644 --- a/examples/typescript/websocket-server-pool/ws-hybrid/src/main.ts +++ b/examples/typescript/websocket-server-pool/ws-hybrid/src/main.ts @@ -31,16 +31,17 @@ const pool = new FixedClusterPool( workerFile: requestHandlerWorkerFile, enableTasksQueue: true, tasksQueueOptions: { - concurrency: 8 + concurrency: 8, }, errorHandler: (e: Error) => { console.error('Thread worker error:', e) - } + }, }) .then(response => { if (response.status) { console.info( - `WebSocket server is listening in cluster worker on port ${response.port}` + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + `WebSocket server is listening in cluster worker on port ${response.port?.toString()}` ) } return undefined @@ -54,6 +55,6 @@ const pool = new FixedClusterPool( }, errorHandler: (e: Error) => { console.error('Cluster worker error', e) - } + }, } ) diff --git a/examples/typescript/websocket-server-pool/ws-hybrid/src/request-handler-worker.ts b/examples/typescript/websocket-server-pool/ws-hybrid/src/request-handler-worker.ts index 004dd3db..444c5179 100644 --- a/examples/typescript/websocket-server-pool/ws-hybrid/src/request-handler-worker.ts +++ b/examples/typescript/websocket-server-pool/ws-hybrid/src/request-handler-worker.ts @@ -1,9 +1,9 @@ import { ThreadWorker } from 'poolifier' -import { - type DataPayload, - type ThreadWorkerData, - type ThreadWorkerResponse +import type { + DataPayload, + ThreadWorkerData, + ThreadWorkerResponse, } from './types.js' class RequestHandlerWorker< @@ -31,15 +31,16 @@ class RequestHandlerWorker< factorial: (workerData?: Data) => { return { data: { - number: RequestHandlerWorker.factorial(workerData!.data.number!) - } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + number: RequestHandlerWorker.factorial(workerData!.data.number!), + }, } as unknown as Response - } + }, }) } } export const requestHandlerWorker = new RequestHandlerWorker< -ThreadWorkerData, -ThreadWorkerResponse + ThreadWorkerData, + ThreadWorkerResponse >() diff --git a/examples/typescript/websocket-server-pool/ws-hybrid/src/websocket-server-worker.ts b/examples/typescript/websocket-server-pool/ws-hybrid/src/websocket-server-worker.ts index e52f0c06..72ac2a1b 100644 --- a/examples/typescript/websocket-server-pool/ws-hybrid/src/websocket-server-worker.ts +++ b/examples/typescript/websocket-server-pool/ws-hybrid/src/websocket-server-worker.ts @@ -1,7 +1,7 @@ import { availableParallelism, ClusterWorker, - DynamicThreadPool + DynamicThreadPool, } from 'poolifier' import { type RawData, WebSocketServer } from 'ws' @@ -12,7 +12,7 @@ import { type MessagePayload, MessageType, type ThreadWorkerData, - type ThreadWorkerResponse + type ThreadWorkerResponse, } from './types.js' const emptyFunction = (): void => { @@ -20,24 +20,25 @@ const emptyFunction = (): void => { } class WebSocketServerWorker extends ClusterWorker< -ClusterWorkerData, -ClusterWorkerResponse + ClusterWorkerData, + ClusterWorkerResponse > { private static wss: WebSocketServer private static requestHandlerPool: DynamicThreadPool< - ThreadWorkerData, - ThreadWorkerResponse + ThreadWorkerData, + ThreadWorkerResponse > private static readonly startWebSocketServer = ( workerData?: ClusterWorkerData ): ClusterWorkerResponse => { const { port, workerFile, minWorkers, maxWorkers, ...poolOptions } = + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion workerData! WebSocketServerWorker.requestHandlerPool = new DynamicThreadPool< - ThreadWorkerData, - ThreadWorkerResponse + ThreadWorkerData, + ThreadWorkerResponse >( minWorkers ?? 1, maxWorkers ?? availableParallelism(), @@ -47,7 +48,7 @@ ClusterWorkerResponse WebSocketServerWorker.wss = new WebSocketServer({ port }, () => { console.info( - `⚡️[ws server]: WebSocket server is started in cluster worker at ws://localhost:${port}/` + `⚡️[ws server]: WebSocket server is started in cluster worker at ws://localhost:${port.toString()}/` ) }) @@ -66,7 +67,7 @@ ClusterWorkerResponse ws.send( JSON.stringify({ type: MessageType.echo, - data: response.data + data: response.data, }) ) return undefined @@ -81,9 +82,10 @@ ClusterWorkerResponse JSON.stringify( { type: MessageType.factorial, - data: response.data + data: response.data, }, - (_, v) => (typeof v === 'bigint' ? v.toString() : v) + (_, v: unknown) => + typeof v === 'bigint' ? v.toString() : v ) ) return undefined @@ -95,7 +97,7 @@ ClusterWorkerResponse }) return { status: true, - port: WebSocketServerWorker.wss.options.port + port: WebSocketServerWorker.wss.options.port, } } @@ -104,7 +106,7 @@ ClusterWorkerResponse killHandler: async () => { await WebSocketServerWorker.requestHandlerPool.destroy() WebSocketServerWorker.wss.close() - } + }, }) } } diff --git a/examples/typescript/websocket-server-pool/ws-worker_threads/package.json b/examples/typescript/websocket-server-pool/ws-worker_threads/package.json index c6899481..1e551898 100644 --- a/examples/typescript/websocket-server-pool/ws-worker_threads/package.json +++ b/examples/typescript/websocket-server-pool/ws-worker_threads/package.json @@ -6,10 +6,10 @@ "main": "dist/main.js", "type": "module", "volta": { - "node": "22.0.0", - "pnpm": "9.0.6" + "node": "22.2.0", + "pnpm": "9.1.4" }, - "packageManager": "pnpm@9.0.6", + "packageManager": "pnpm@9.1.4", "scripts": { "build": "pnpm build:clean && tsc", "build:clean": "tsc --build --clean", @@ -21,16 +21,16 @@ "author": "", "license": "ISC", "dependencies": { - "poolifier": "^4.0.1", + "poolifier": "^4.0.13", "ws": "^8.17.0" }, "devDependencies": { - "@types/node": "^20.12.8", + "@types/node": "^20.14.0", "@types/ws": "^8.5.10", "typescript": "^5.4.5" }, "optionalDependencies": { "bufferutil": "^4.0.8", - "utf-8-validate": "^6.0.3" + "utf-8-validate": "^6.0.4" } } diff --git a/examples/typescript/websocket-server-pool/ws-worker_threads/pnpm-lock.yaml b/examples/typescript/websocket-server-pool/ws-worker_threads/pnpm-lock.yaml index fbf4eac1..28df8d74 100644 --- a/examples/typescript/websocket-server-pool/ws-worker_threads/pnpm-lock.yaml +++ b/examples/typescript/websocket-server-pool/ws-worker_threads/pnpm-lock.yaml @@ -9,22 +9,22 @@ importers: .: dependencies: poolifier: - specifier: ^4.0.1 - version: 4.0.1 + specifier: ^4.0.13 + version: 4.0.13 ws: specifier: ^8.17.0 - version: 8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.3) + version: 8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4) optionalDependencies: bufferutil: specifier: ^4.0.8 version: 4.0.8 utf-8-validate: - specifier: ^6.0.3 - version: 6.0.3 + specifier: ^6.0.4 + version: 6.0.4 devDependencies: '@types/node': - specifier: ^20.12.8 - version: 20.12.8 + specifier: ^20.14.0 + version: 20.14.0 '@types/ws': specifier: ^8.5.10 version: 8.5.10 @@ -34,8 +34,8 @@ importers: packages: - '@types/node@20.12.8': - resolution: {integrity: sha512-NU0rJLJnshZWdE/097cdCBbyW1h4hEg0xpovcoAQYHl8dnEyp/NAOiE45pvc+Bd1Dt+2r94v2eGFpQJ4R7g+2w==} + '@types/node@20.14.0': + resolution: {integrity: sha512-5cHBxFGJx6L4s56Bubp4fglrEpmyJypsqI6RgzMfBHWUJQGWAAi8cWcgetEbZXHYXo9C2Fa4EEds/uSyS4cxmA==} '@types/ws@8.5.10': resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} @@ -44,12 +44,12 @@ packages: resolution: {integrity: sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==} engines: {node: '>=6.14.2'} - node-gyp-build@4.8.0: - resolution: {integrity: sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==} + node-gyp-build@4.8.1: + resolution: {integrity: sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==} hasBin: true - poolifier@4.0.1: - resolution: {integrity: sha512-1izVxQOC3yonTN1I51tualsPfZ0iUN+r5zaKY/+vEWIa0cUJMPgi1hN86DL4kwCTwr65JZ42ZrxnQWRmdnzRpA==} + poolifier@4.0.13: + resolution: {integrity: sha512-GPITJo3LZvZXGNDWn6eDpOJ+F5+rq4tvyoXFQJfyJ92w0qr4evjoOX9hymwMGmv8TuifFMIBmgCdcTvoxRdMgA==} engines: {node: '>=18.0.0', pnpm: '>=9.0.0'} typescript@5.4.5: @@ -60,8 +60,8 @@ packages: undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - utf-8-validate@6.0.3: - resolution: {integrity: sha512-uIuGf9TWQ/y+0Lp+KGZCMuJWc3N9BHA+l/UmHd/oUHwJJDeysyTRxNQVkbzsIWfGFbRe3OcgML/i0mvVRPOyDA==} + utf-8-validate@6.0.4: + resolution: {integrity: sha512-xu9GQDeFp+eZ6LnCywXN/zBancWvOpUMzgjLPSjy4BRHSmTelvn2E0DG0o1sTiw5hkCKBHo8rwSKncfRfv2EEQ==} engines: {node: '>=6.14.2'} ws@8.17.0: @@ -78,34 +78,34 @@ packages: snapshots: - '@types/node@20.12.8': + '@types/node@20.14.0': dependencies: undici-types: 5.26.5 '@types/ws@8.5.10': dependencies: - '@types/node': 20.12.8 + '@types/node': 20.14.0 bufferutil@4.0.8: dependencies: - node-gyp-build: 4.8.0 + node-gyp-build: 4.8.1 optional: true - node-gyp-build@4.8.0: + node-gyp-build@4.8.1: optional: true - poolifier@4.0.1: {} + poolifier@4.0.13: {} typescript@5.4.5: {} undici-types@5.26.5: {} - utf-8-validate@6.0.3: + utf-8-validate@6.0.4: dependencies: - node-gyp-build: 4.8.0 + node-gyp-build: 4.8.1 optional: true - ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.3): + ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4): optionalDependencies: bufferutil: 4.0.8 - utf-8-validate: 6.0.3 + utf-8-validate: 6.0.4 diff --git a/examples/typescript/websocket-server-pool/ws-worker_threads/requests.js b/examples/typescript/websocket-server-pool/ws-worker_threads/requests.js index 9beb2b78..2c73376f 100644 --- a/examples/typescript/websocket-server-pool/ws-worker_threads/requests.js +++ b/examples/typescript/websocket-server-pool/ws-worker_threads/requests.js @@ -1,4 +1,3 @@ -// eslint-disable-next-line import/no-unresolved, n/no-missing-import import { WebSocket } from 'ws' const ws = new WebSocket('ws://localhost:8080') diff --git a/examples/typescript/websocket-server-pool/ws-worker_threads/src/main.ts b/examples/typescript/websocket-server-pool/ws-worker_threads/src/main.ts index 7a162499..cb28beeb 100644 --- a/examples/typescript/websocket-server-pool/ws-worker_threads/src/main.ts +++ b/examples/typescript/websocket-server-pool/ws-worker_threads/src/main.ts @@ -6,7 +6,7 @@ import { type DataPayload, type MessagePayload, MessageType } from './types.js' const port = 8080 const wss = new WebSocketServer({ port }, () => { console.info( - `⚡️[ws server]: WebSocket server is started at ws://localhost:${port}/` + `⚡️[ws server]: WebSocket server is started at ws://localhost:${port.toString()}/` ) }) @@ -29,7 +29,7 @@ wss.on('connection', ws => { ws.send( JSON.stringify({ type: MessageType.echo, - data: response.data + data: response.data, }) ) return undefined @@ -44,9 +44,9 @@ wss.on('connection', ws => { JSON.stringify( { type: MessageType.factorial, - data: response.data + data: response.data, }, - (_, v) => (typeof v === 'bigint' ? v.toString() : v) + (_, v: unknown) => (typeof v === 'bigint' ? v.toString() : v) ) ) return undefined diff --git a/examples/typescript/websocket-server-pool/ws-worker_threads/src/pool.ts b/examples/typescript/websocket-server-pool/ws-worker_threads/src/pool.ts index 45d458d5..1cefa60c 100644 --- a/examples/typescript/websocket-server-pool/ws-worker_threads/src/pool.ts +++ b/examples/typescript/websocket-server-pool/ws-worker_threads/src/pool.ts @@ -3,11 +3,7 @@ import { fileURLToPath } from 'node:url' import { availableParallelism, DynamicThreadPool } from 'poolifier' -import { - type DataPayload, - type WorkerData, - type WorkerResponse -} from './types.js' +import type { DataPayload, WorkerData, WorkerResponse } from './types.js' const workerFile = join( dirname(fileURLToPath(import.meta.url)), @@ -15,14 +11,14 @@ const workerFile = join( ) export const requestHandlerPool = new DynamicThreadPool< -WorkerData, -WorkerResponse + WorkerData, + WorkerResponse >(1, availableParallelism(), workerFile, { enableTasksQueue: true, tasksQueueOptions: { - concurrency: 8 + concurrency: 8, }, errorHandler: (e: Error) => { console.error('Thread worker error:', e) - } + }, }) diff --git a/examples/typescript/websocket-server-pool/ws-worker_threads/src/worker.ts b/examples/typescript/websocket-server-pool/ws-worker_threads/src/worker.ts index e1b67193..2c4de3e2 100644 --- a/examples/typescript/websocket-server-pool/ws-worker_threads/src/worker.ts +++ b/examples/typescript/websocket-server-pool/ws-worker_threads/src/worker.ts @@ -1,10 +1,6 @@ import { ThreadWorker } from 'poolifier' -import { - type DataPayload, - type WorkerData, - type WorkerResponse -} from './types.js' +import type { DataPayload, WorkerData, WorkerResponse } from './types.js' class RequestHandlerWorker< Data extends WorkerData, @@ -31,15 +27,16 @@ class RequestHandlerWorker< factorial: (workerData?: Data) => { return { data: { - number: RequestHandlerWorker.factorial(workerData!.data.number!) - } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + number: RequestHandlerWorker.factorial(workerData!.data.number!), + }, } as unknown as Response - } + }, }) } } export const requestHandlerWorker = new RequestHandlerWorker< -WorkerData, -WorkerResponse + WorkerData, + WorkerResponse >() diff --git a/examples/typescript/worker.ts b/examples/typescript/worker.ts index 1d8af8d9..7ab1fc56 100644 --- a/examples/typescript/worker.ts +++ b/examples/typescript/worker.ts @@ -12,7 +12,7 @@ export interface MyResponse { class MyThreadWorker extends ThreadWorker { constructor () { super(async (data?: MyData) => await this.process(data), { - maxInactiveTime: 60000 + maxInactiveTime: 60000, }) } diff --git a/jsr.json b/jsr.json index 1b2cce8c..060ceee5 100644 --- a/jsr.json +++ b/jsr.json @@ -1,7 +1,7 @@ { "$schema": "https://jsr.io/schema/config-file.v1.json", "name": "@poolifier/poolifier", - "version": "4.0.1", + "version": "4.0.13", "exports": "./src/index.ts", "publish": { "include": ["LICENSE", "README.md", "jsr.json", "src/**/*.ts"] diff --git a/package.json b/package.json index 880bd768..59debe23 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package", "name": "poolifier", - "version": "4.0.1", + "version": "4.0.13", "description": "Fast and small Node.js Worker_Threads and Cluster Worker Pool", "license": "MIT", "type": "module", @@ -21,9 +21,6 @@ "build:prod": "rollup --config", "build:typedoc": "rollup --config --environment DOCUMENTATION,BUILD:development", "build:analyze": "rollup --config --environment ANALYZE,BUILD:development", - "benchmark:benchmark.js": "pnpm build && node --max-old-space-size=8192 --enable-source-maps benchmarks/internal/bench.mjs -t benchmark.js", - "benchmark:benchmark.js:prod": "pnpm build:prod && node --max-old-space-size=8192 --enable-source-maps benchmarks/internal/bench.mjs -t benchmark.js", - "benchmark:benchmark.js:debug": "pnpm build && node --max-old-space-size=8192 --enable-source-maps --inspect benchmarks/internal/bench.mjs -t benchmark.js", "benchmark:tatami-ng": "pnpm build && node --enable-source-maps benchmarks/internal/bench.mjs -t tatami-ng", "benchmark:tatami-ng:prod": "pnpm build:prod && node --enable-source-maps benchmarks/internal/bench.mjs -t tatami-ng", "benchmark:tatami-ng:debug": "pnpm build && node --enable-source-maps --inspect benchmarks/internal/bench.mjs -t tatami-ng", @@ -44,10 +41,10 @@ "pnpm": ">=9.0.0" }, "volta": { - "node": "22.0.0", - "pnpm": "9.0.6" + "node": "22.2.0", + "pnpm": "9.1.4" }, - "packageManager": "pnpm@9.0.6", + "packageManager": "pnpm@9.1.4", "repository": { "type": "git", "url": "https://github.com/poolifier/poolifier.git" @@ -104,46 +101,39 @@ } }, "devDependencies": { - "@biomejs/biome": "^1.7.2", + "@biomejs/biome": "^1.7.3", "@commitlint/cli": "^19.3.0", "@commitlint/config-conventional": "^19.2.2", + "@cspell/eslint-plugin": "^8.8.3", + "@eslint/js": "^9.4.0", "@release-it/bumper": "^6.0.1", "@release-it/keep-a-changelog": "^5.0.0", "@rollup/plugin-terser": "^0.4.4", "@rollup/plugin-typescript": "^11.1.6", - "@types/node": "^20.12.8", - "@typescript-eslint/eslint-plugin": "^7.8.0", - "@typescript-eslint/parser": "^7.8.0", - "benchmark": "^2.1.4", + "@types/node": "^20.14.0", "c8": "^9.1.0", "cross-env": "^7.0.3", - "eslint": "^8.57.0", - "eslint-config-love": "^47.0.0", - "eslint-config-standard": "^17.1.0", + "eslint": "^9.4.0", "eslint-define-config": "^2.1.0", - "eslint-import-resolver-typescript": "^3.6.1", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jsdoc": "^48.2.3", - "eslint-plugin-n": "^17.4.0", - "eslint-plugin-promise": "^6.1.1", + "eslint-plugin-jsdoc": "^48.2.7", + "eslint-plugin-n": "^17.7.0", "eslint-plugin-simple-import-sort": "^12.1.0", - "eslint-plugin-spellcheck": "^0.0.20", - "eslint-plugin-tsdoc": "^0.2.17", "expect": "^29.7.0", + "globals": "^15.3.0", "husky": "^9.0.11", - "lint-staged": "^15.2.2", - "microtime": "^3.1.1", + "lint-staged": "^15.2.5", "mocha": "^10.4.0", "mochawesome": "^7.1.3", - "prettier": "^3.2.5", - "release-it": "^17.2.1", - "rollup": "^4.17.2", + "neostandard": "^0.5.1", + "prettier": "^3.3.0", + "release-it": "^17.3.0", + "rollup": "^4.18.0", "rollup-plugin-analyzer": "^4.0.0", "rollup-plugin-command": "^1.1.3", "rollup-plugin-delete": "^2.0.0", - "rollup-plugin-dts": "^6.1.0", - "sinon": "^17.0.1", - "tatami-ng": "^0.4.4", + "rollup-plugin-dts": "^6.1.1", + "sinon": "^18.0.0", + "tatami-ng": "^0.4.13", "typedoc": "^0.25.13", "typescript": "~5.4.5" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 720ebb1d..4ab91107 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,38 +12,35 @@ importers: .: devDependencies: '@biomejs/biome': - specifier: ^1.7.2 - version: 1.7.2 + specifier: ^1.7.3 + version: 1.7.3 '@commitlint/cli': specifier: ^19.3.0 - version: 19.3.0(@types/node@20.12.8)(typescript@5.4.5) + version: 19.3.0(@types/node@20.14.0)(typescript@5.4.5) '@commitlint/config-conventional': specifier: ^19.2.2 version: 19.2.2 + '@cspell/eslint-plugin': + specifier: ^8.8.3 + version: 8.8.3(eslint@9.4.0) + '@eslint/js': + specifier: ^9.4.0 + version: 9.4.0 '@release-it/bumper': specifier: ^6.0.1 - version: 6.0.1(release-it@17.2.1(typescript@5.4.5)) + version: 6.0.1(release-it@17.3.0(typescript@5.4.5)) '@release-it/keep-a-changelog': specifier: ^5.0.0 - version: 5.0.0(release-it@17.2.1(typescript@5.4.5)) + version: 5.0.0(release-it@17.3.0(typescript@5.4.5)) '@rollup/plugin-terser': specifier: ^0.4.4 - version: 0.4.4(rollup@4.17.2) + version: 0.4.4(rollup@4.18.0) '@rollup/plugin-typescript': specifier: ^11.1.6 - version: 11.1.6(rollup@4.17.2)(tslib@2.6.2)(typescript@5.4.5) + version: 11.1.6(rollup@4.18.0)(tslib@2.6.2)(typescript@5.4.5) '@types/node': - specifier: ^20.12.8 - version: 20.12.8 - '@typescript-eslint/eslint-plugin': - specifier: ^7.8.0 - version: 7.8.0(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/parser': - specifier: ^7.8.0 - version: 7.8.0(eslint@8.57.0)(typescript@5.4.5) - benchmark: - specifier: ^2.1.4 - version: 2.1.4 + specifier: ^20.14.0 + version: 20.14.0 c8: specifier: ^9.1.0 version: 9.1.0 @@ -51,68 +48,50 @@ importers: specifier: ^7.0.3 version: 7.0.3 eslint: - specifier: ^8.57.0 - version: 8.57.0 - eslint-config-love: - specifier: ^47.0.0 - version: 47.0.0(@typescript-eslint/eslint-plugin@7.8.0(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0))(eslint-plugin-n@17.4.0(eslint@8.57.0))(eslint-plugin-promise@6.1.1(eslint@8.57.0))(eslint@8.57.0)(typescript@5.4.5) - eslint-config-standard: - specifier: ^17.1.0 - version: 17.1.0(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0))(eslint-plugin-n@17.4.0(eslint@8.57.0))(eslint-plugin-promise@6.1.1(eslint@8.57.0))(eslint@8.57.0) + specifier: ^9.4.0 + version: 9.4.0 eslint-define-config: specifier: ^2.1.0 version: 2.1.0 - eslint-import-resolver-typescript: - specifier: ^3.6.1 - version: 3.6.1(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.29.1)(eslint@8.57.0) - eslint-plugin-import: - specifier: ^2.29.1 - version: 2.29.1(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) eslint-plugin-jsdoc: - specifier: ^48.2.3 - version: 48.2.3(eslint@8.57.0) + specifier: ^48.2.7 + version: 48.2.7(eslint@9.4.0) eslint-plugin-n: - specifier: ^17.4.0 - version: 17.4.0(eslint@8.57.0) - eslint-plugin-promise: - specifier: ^6.1.1 - version: 6.1.1(eslint@8.57.0) + specifier: ^17.7.0 + version: 17.7.0(eslint@9.4.0) eslint-plugin-simple-import-sort: specifier: ^12.1.0 - version: 12.1.0(eslint@8.57.0) - eslint-plugin-spellcheck: - specifier: ^0.0.20 - version: 0.0.20(eslint@8.57.0) - eslint-plugin-tsdoc: - specifier: ^0.2.17 - version: 0.2.17 + version: 12.1.0(eslint@9.4.0) expect: specifier: ^29.7.0 version: 29.7.0 + globals: + specifier: ^15.3.0 + version: 15.3.0 husky: specifier: ^9.0.11 version: 9.0.11 lint-staged: - specifier: ^15.2.2 - version: 15.2.2 - microtime: - specifier: ^3.1.1 - version: 3.1.1 + specifier: ^15.2.5 + version: 15.2.5 mocha: specifier: ^10.4.0 version: 10.4.0 mochawesome: specifier: ^7.1.3 version: 7.1.3(mocha@10.4.0) + neostandard: + specifier: ^0.5.1 + version: 0.5.1(@typescript-eslint/parser@8.0.0-alpha.25(eslint@9.4.0)(typescript@5.4.5))(eslint@9.4.0)(typescript@5.4.5) prettier: - specifier: ^3.2.5 - version: 3.2.5 + specifier: ^3.3.0 + version: 3.3.0 release-it: - specifier: ^17.2.1 - version: 17.2.1(typescript@5.4.5) + specifier: ^17.3.0 + version: 17.3.0(typescript@5.4.5) rollup: - specifier: ^4.17.2 - version: 4.17.2 + specifier: ^4.18.0 + version: 4.18.0 rollup-plugin-analyzer: specifier: ^4.0.0 version: 4.0.0 @@ -123,14 +102,14 @@ importers: specifier: ^2.0.0 version: 2.0.0 rollup-plugin-dts: - specifier: ^6.1.0 - version: 6.1.0(rollup@4.17.2)(typescript@5.4.5) + specifier: ^6.1.1 + version: 6.1.1(rollup@4.18.0)(typescript@5.4.5) sinon: - specifier: ^17.0.1 - version: 17.0.1 + specifier: ^18.0.0 + version: 18.0.0 tatami-ng: - specifier: ^0.4.4 - version: 0.4.4(typescript@5.4.5) + specifier: ^0.4.13 + version: 0.4.13(typescript@5.4.5) typedoc: specifier: ^0.25.13 version: 0.25.13(typescript@5.4.5) @@ -140,70 +119,70 @@ importers: packages: - '@babel/code-frame@7.24.2': - resolution: {integrity: sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==} + '@babel/code-frame@7.24.6': + resolution: {integrity: sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.24.5': - resolution: {integrity: sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==} + '@babel/helper-validator-identifier@7.24.6': + resolution: {integrity: sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw==} engines: {node: '>=6.9.0'} - '@babel/highlight@7.24.5': - resolution: {integrity: sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==} + '@babel/highlight@7.24.6': + resolution: {integrity: sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ==} engines: {node: '>=6.9.0'} '@bcoe/v8-coverage@0.2.3': resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} - '@biomejs/biome@1.7.2': - resolution: {integrity: sha512-6Skx9N47inLQzYi9RKgJ7PBnUnaHnMe/imqX43cOcJjZtfMnQLxEvfM2Eyo7gChkwrZlwc+VbA4huFRjw2fsYA==} + '@biomejs/biome@1.7.3': + resolution: {integrity: sha512-ogFQI+fpXftr+tiahA6bIXwZ7CSikygASdqMtH07J2cUzrpjyTMVc9Y97v23c7/tL1xCZhM+W9k4hYIBm7Q6cQ==} engines: {node: '>=14.21.3'} hasBin: true - '@biomejs/cli-darwin-arm64@1.7.2': - resolution: {integrity: sha512-CrldIueHivWEWmeTkK8bTXajeX53F8i2Rrkkt8cPZyMtzkrwxf8Riq4a/jz3SQBHkxHFT4TqGbSTNMXe3X1ogA==} + '@biomejs/cli-darwin-arm64@1.7.3': + resolution: {integrity: sha512-eDvLQWmGRqrPIRY7AIrkPHkQ3visEItJKkPYSHCscSDdGvKzYjmBJwG1Gu8+QC5ed6R7eiU63LEC0APFBobmfQ==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [darwin] - '@biomejs/cli-darwin-x64@1.7.2': - resolution: {integrity: sha512-UELnLJuJOsTL9meArvn8BtiXDURyPil2Ej9me2uVpEvee8UQdqd/bssP5we400OWShlL1AAML4fn6d2WX5332g==} + '@biomejs/cli-darwin-x64@1.7.3': + resolution: {integrity: sha512-JXCaIseKRER7dIURsVlAJacnm8SG5I0RpxZ4ya3dudASYUc68WGl4+FEN03ABY3KMIq7hcK1tzsJiWlmXyosZg==} engines: {node: '>=14.21.3'} cpu: [x64] os: [darwin] - '@biomejs/cli-linux-arm64-musl@1.7.2': - resolution: {integrity: sha512-kKYZiem7Sj7wI0dpVxJlK7C+TFQwzO/ctufIGXGJAyEmUe9vEKSzV8CXpv+JIRiTWyqaZJ4K+eHz4SPdPCv05w==} + '@biomejs/cli-linux-arm64-musl@1.7.3': + resolution: {integrity: sha512-c8AlO45PNFZ1BYcwaKzdt46kYbuP6xPGuGQ6h4j3XiEDpyseRRUy/h+6gxj07XovmyxKnSX9GSZ6nVbZvcVUAw==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - '@biomejs/cli-linux-arm64@1.7.2': - resolution: {integrity: sha512-Z1CSGQE6fHz55gkiFHv9E8wEAaSUd7dHSRaxSCBa7utonHqpIeMbvj3Evm1w0WfGLFDtRXLV1fTfEdM0FMTOhA==} + '@biomejs/cli-linux-arm64@1.7.3': + resolution: {integrity: sha512-phNTBpo7joDFastnmZsFjYcDYobLTx4qR4oPvc9tJ486Bd1SfEVPHEvJdNJrMwUQK56T+TRClOQd/8X1nnjA9w==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - '@biomejs/cli-linux-x64-musl@1.7.2': - resolution: {integrity: sha512-x10LpGMepDrLS+h2TZ6/T7egpHjGKtiI4GuShNylmBQJWfTotbFf9eseHggrqJ4WZf9yrGoVYrtbxXftuB95sQ==} + '@biomejs/cli-linux-x64-musl@1.7.3': + resolution: {integrity: sha512-UdEHKtYGWEX3eDmVWvQeT+z05T9/Sdt2+F/7zmMOFQ7boANeX8pcO6EkJPK3wxMudrApsNEKT26rzqK6sZRTRA==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - '@biomejs/cli-linux-x64@1.7.2': - resolution: {integrity: sha512-vXXyox8/CQijBxAu0+r8FfSO7JlC4tob3PbaFda8gPJFRz2uFJw39HtxVUwbTV1EcU6wSPh4SiRu5sZfP1VHrQ==} + '@biomejs/cli-linux-x64@1.7.3': + resolution: {integrity: sha512-vnedYcd5p4keT3iD48oSKjOIRPYcjSNNbd8MO1bKo9ajg3GwQXZLAH+0Cvlr+eMsO67/HddWmscSQwTFrC/uPA==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - '@biomejs/cli-win32-arm64@1.7.2': - resolution: {integrity: sha512-kRXdlKzcU7INf6/ldu0nVmkOgt7bKqmyXRRCUqqaJfA32+9InTbkD8tGrHZEVYIWr+eTuKcg16qZVDsPSDFZ8g==} + '@biomejs/cli-win32-arm64@1.7.3': + resolution: {integrity: sha512-unNCDqUKjujYkkSxs7gFIfdasttbDC4+z0kYmcqzRk6yWVoQBL4dNLcCbdnJS+qvVDNdI9rHp2NwpQ0WAdla4Q==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [win32] - '@biomejs/cli-win32-x64@1.7.2': - resolution: {integrity: sha512-qHTtpAs+CNglAAuaTy09htoqUhrQyd3nd0aGTuLNqD10h1llMVi8WFZfoa+e5MuDSfYtMK6nW2Tbf6WgzzR1Qw==} + '@biomejs/cli-win32-x64@1.7.3': + resolution: {integrity: sha512-ZmByhbrnmz/UUFYB622CECwhKIPjJLLPr5zr3edhu04LzbfcOrz16VYeNq5dpO1ADG70FORhAJkaIGdaVBG00w==} engines: {node: '>=14.21.3'} cpu: [x64] os: [win32] @@ -277,8 +256,201 @@ packages: resolution: {integrity: sha512-tpyc+7i6bPG9mvaBbtKUeghfyZSDgWquIDfMgqYtTbmZ9Y9VzEm2je9EYcQ0aoz5o7NvGS+rcDec93yO08MHYA==} engines: {node: '>=v18'} - '@es-joy/jsdoccomment@0.42.0': - resolution: {integrity: sha512-R1w57YlVA6+YE01wch3GPYn6bCsrOV3YW/5oGGE2tmX6JcL9Nr+b5IikrjMPF+v9CV3ay+obImEdsDhovhJrzw==} + '@cspell/cspell-bundled-dicts@8.8.3': + resolution: {integrity: sha512-nRa30TQwE4R5xcM6CBibM2l7D359ympexjm7OrykzYmStIiiudDIsuNOIXGBrDouxRFgKGAa/ETo1g+Pxz7kNA==} + engines: {node: '>=18'} + + '@cspell/cspell-pipe@8.8.3': + resolution: {integrity: sha512-tzngpFKXeUsdTZEErffTlwUnPIKYgyRKy0YTrD77EkhyDSbUnaS8JWqtGZbKV7iQ+R4CL7tiaubPjUzkbWj+kQ==} + engines: {node: '>=18'} + + '@cspell/cspell-resolver@8.8.3': + resolution: {integrity: sha512-pMOB2MJYeria0DeW1dsehRPIHLzoOXCm1Cdjp1kRZ931PbqNCYaE/GM6laWpUTAbS9Ly2tv4g0jK3PUH8ZTtJA==} + engines: {node: '>=18'} + + '@cspell/cspell-service-bus@8.8.3': + resolution: {integrity: sha512-QVKe/JZvoTaaBAMXG40HjZib1g6rGgxk03e070GmdfCiMRUCWFtK+9DKVYJfSqjQhzj/eDCrq8aWplHWy66umg==} + engines: {node: '>=18'} + + '@cspell/cspell-types@8.8.3': + resolution: {integrity: sha512-31wYSBPinhqKi9TSzPg50fWHJmMQwD1d5p26yM/NAfNQvjAfBQlrg4pqix8pxOJkAK5W/TnoaVXjzJ5XCg6arQ==} + engines: {node: '>=18'} + + '@cspell/dict-ada@4.0.2': + resolution: {integrity: sha512-0kENOWQeHjUlfyId/aCM/mKXtkEgV0Zu2RhUXCBr4hHo9F9vph+Uu8Ww2b0i5a4ZixoIkudGA+eJvyxrG1jUpA==} + + '@cspell/dict-aws@4.0.2': + resolution: {integrity: sha512-aNGHWSV7dRLTIn8WJemzLoMF62qOaiUQlgnsCwH5fRCD/00gsWCwg106pnbkmK4AyabyxzneOV4dfecDJWkSxw==} + + '@cspell/dict-bash@4.1.3': + resolution: {integrity: sha512-tOdI3QVJDbQSwPjUkOiQFhYcu2eedmX/PtEpVWg0aFps/r6AyjUQINtTgpqMYnYuq8O1QUIQqnpx21aovcgZCw==} + + '@cspell/dict-companies@3.1.2': + resolution: {integrity: sha512-OwR5i1xbYuJX7FtHQySmTy3iJtPV1rZQ3jFCxFGwrA1xRQ4rtRcDQ+sTXBCIAoJHkXa84f9J3zsngOKmMGyS/w==} + + '@cspell/dict-cpp@5.1.8': + resolution: {integrity: sha512-X5uq0uRqN6cyOZOZV1YKi6g8sBtd0+VoF5NbDWURahGR8TRsiztH0sNqs0IB3X0dW4GakU+n9SXcuEmxynkSsw==} + + '@cspell/dict-cryptocurrencies@5.0.0': + resolution: {integrity: sha512-Z4ARIw5+bvmShL+4ZrhDzGhnc9znaAGHOEMaB/GURdS/jdoreEDY34wdN0NtdLHDO5KO7GduZnZyqGdRoiSmYA==} + + '@cspell/dict-csharp@4.0.2': + resolution: {integrity: sha512-1JMofhLK+4p4KairF75D3A924m5ERMgd1GvzhwK2geuYgd2ZKuGW72gvXpIV7aGf52E3Uu1kDXxxGAiZ5uVG7g==} + + '@cspell/dict-css@4.0.12': + resolution: {integrity: sha512-vGBgPM92MkHQF5/2jsWcnaahOZ+C6OE/fPvd5ScBP72oFY9tn5GLuomcyO0z8vWCr2e0nUSX1OGimPtcQAlvSw==} + + '@cspell/dict-dart@2.0.3': + resolution: {integrity: sha512-cLkwo1KT5CJY5N5RJVHks2genFkNCl/WLfj+0fFjqNR+tk3tBI1LY7ldr9piCtSFSm4x9pO1x6IV3kRUY1lLiw==} + + '@cspell/dict-data-science@1.0.11': + resolution: {integrity: sha512-TaHAZRVe0Zlcc3C23StZqqbzC0NrodRwoSAc8dis+5qLeLLnOCtagYQeROQvDlcDg3X/VVEO9Whh4W/z4PAmYQ==} + + '@cspell/dict-django@4.1.0': + resolution: {integrity: sha512-bKJ4gPyrf+1c78Z0Oc4trEB9MuhcB+Yg+uTTWsvhY6O2ncFYbB/LbEZfqhfmmuK/XJJixXfI1laF2zicyf+l0w==} + + '@cspell/dict-docker@1.1.7': + resolution: {integrity: sha512-XlXHAr822euV36GGsl2J1CkBIVg3fZ6879ZOg5dxTIssuhUOCiV2BuzKZmt6aIFmcdPmR14+9i9Xq+3zuxeX0A==} + + '@cspell/dict-dotnet@5.0.2': + resolution: {integrity: sha512-UD/pO2A2zia/YZJ8Kck/F6YyDSpCMq0YvItpd4YbtDVzPREfTZ48FjZsbYi4Jhzwfvc6o8R56JusAE58P+4sNQ==} + + '@cspell/dict-elixir@4.0.3': + resolution: {integrity: sha512-g+uKLWvOp9IEZvrIvBPTr/oaO6619uH/wyqypqvwpmnmpjcfi8+/hqZH8YNKt15oviK8k4CkINIqNhyndG9d9Q==} + + '@cspell/dict-en-common-misspellings@2.0.1': + resolution: {integrity: sha512-uWaP8UG4uvcPyqaG0FzPKCm5kfmhsiiQ45Fs6b3/AEAqfq7Fj1JW0+S3qRt85FQA9SoU6gUJCz9wkK/Ylh7m5A==} + + '@cspell/dict-en-gb@1.1.33': + resolution: {integrity: sha512-tKSSUf9BJEV+GJQAYGw5e+ouhEe2ZXE620S7BLKe3ZmpnjlNG9JqlnaBhkIMxKnNFkLY2BP/EARzw31AZnOv4g==} + + '@cspell/dict-en_us@4.3.21': + resolution: {integrity: sha512-Bzoo2aS4Pej/MGIFlATpp0wMt9IzVHrhDjdV7FgkAIXbjrOn67ojbTxCgWs8AuCNVfK8lBYGEvs5+ElH1msF8w==} + + '@cspell/dict-filetypes@3.0.4': + resolution: {integrity: sha512-IBi8eIVdykoGgIv5wQhOURi5lmCNJq0we6DvqKoPQJHthXbgsuO1qrHSiUVydMiQl/XvcnUWTMeAlVUlUClnVg==} + + '@cspell/dict-fonts@4.0.0': + resolution: {integrity: sha512-t9V4GeN/m517UZn63kZPUYP3OQg5f0OBLSd3Md5CU3eH1IFogSvTzHHnz4Wqqbv8NNRiBZ3HfdY/pqREZ6br3Q==} + + '@cspell/dict-fsharp@1.0.1': + resolution: {integrity: sha512-23xyPcD+j+NnqOjRHgW3IU7Li912SX9wmeefcY0QxukbAxJ/vAN4rBpjSwwYZeQPAn3fxdfdNZs03fg+UM+4yQ==} + + '@cspell/dict-fullstack@3.1.8': + resolution: {integrity: sha512-YRlZupL7uqMCtEBK0bDP9BrcPnjDhz7m4GBqCc1EYqfXauHbLmDT8ELha7T/E7wsFKniHSjzwDZzhNXo2lusRQ==} + + '@cspell/dict-gaming-terms@1.0.5': + resolution: {integrity: sha512-C3riccZDD3d9caJQQs1+MPfrUrQ+0KHdlj9iUR1QD92FgTOF6UxoBpvHUUZ9YSezslcmpFQK4xQQ5FUGS7uWfw==} + + '@cspell/dict-git@3.0.0': + resolution: {integrity: sha512-simGS/lIiXbEaqJu9E2VPoYW1OTC2xrwPPXNXFMa2uo/50av56qOuaxDrZ5eH1LidFXwoc8HROCHYeKoNrDLSw==} + + '@cspell/dict-golang@6.0.9': + resolution: {integrity: sha512-etDt2WQauyEQDA+qPS5QtkYTb2I9l5IfQftAllVoB1aOrT6bxxpHvMEpJ0Hsn/vezxrCqa/BmtUbRxllIxIuSg==} + + '@cspell/dict-google@1.0.1': + resolution: {integrity: sha512-dQr4M3n95uOhtloNSgB9tYYGXGGEGEykkFyRtfcp5pFuEecYUa0BSgtlGKx9RXVtJtKgR+yFT/a5uQSlt8WjqQ==} + + '@cspell/dict-haskell@4.0.1': + resolution: {integrity: sha512-uRrl65mGrOmwT7NxspB4xKXFUenNC7IikmpRZW8Uzqbqcu7ZRCUfstuVH7T1rmjRgRkjcIjE4PC11luDou4wEQ==} + + '@cspell/dict-html-symbol-entities@4.0.0': + resolution: {integrity: sha512-HGRu+48ErJjoweR5IbcixxETRewrBb0uxQBd6xFGcxbEYCX8CnQFTAmKI5xNaIt2PKaZiJH3ijodGSqbKdsxhw==} + + '@cspell/dict-html@4.0.5': + resolution: {integrity: sha512-p0brEnRybzSSWi8sGbuVEf7jSTDmXPx7XhQUb5bgG6b54uj+Z0Qf0V2n8b/LWwIPJNd1GygaO9l8k3HTCy1h4w==} + + '@cspell/dict-java@5.0.6': + resolution: {integrity: sha512-kdE4AHHHrixyZ5p6zyms1SLoYpaJarPxrz8Tveo6gddszBVVwIUZ+JkQE1bWNLK740GWzIXdkznpUfw1hP9nXw==} + + '@cspell/dict-julia@1.0.1': + resolution: {integrity: sha512-4JsCLCRhhLMLiaHpmR7zHFjj1qOauzDI5ZzCNQS31TUMfsOo26jAKDfo0jljFAKgw5M2fEG7sKr8IlPpQAYrmQ==} + + '@cspell/dict-k8s@1.0.5': + resolution: {integrity: sha512-Cj+/ZV4S+MKlwfocSJZqe/2UAd/sY8YtlZjbK25VN1nCnrsKrBjfkX29vclwSj1U9aJg4Z9jw/uMjoaKu9ZrpQ==} + + '@cspell/dict-latex@4.0.0': + resolution: {integrity: sha512-LPY4y6D5oI7D3d+5JMJHK/wxYTQa2lJMSNxps2JtuF8hbAnBQb3igoWEjEbIbRRH1XBM0X8dQqemnjQNCiAtxQ==} + + '@cspell/dict-lorem-ipsum@4.0.0': + resolution: {integrity: sha512-1l3yjfNvMzZPibW8A7mQU4kTozwVZVw0AvFEdy+NcqtbxH+TvbSkNMqROOFWrkD2PjnKG0+Ea0tHI2Pi6Gchnw==} + + '@cspell/dict-lua@4.0.3': + resolution: {integrity: sha512-lDHKjsrrbqPaea13+G9s0rtXjMO06gPXPYRjRYawbNmo4E/e3XFfVzeci3OQDQNDmf2cPOwt9Ef5lu2lDmwfJg==} + + '@cspell/dict-makefile@1.0.0': + resolution: {integrity: sha512-3W9tHPcSbJa6s0bcqWo6VisEDTSN5zOtDbnPabF7rbyjRpNo0uHXHRJQF8gAbFzoTzBBhgkTmrfSiuyQm7vBUQ==} + + '@cspell/dict-monkeyc@1.0.6': + resolution: {integrity: sha512-oO8ZDu/FtZ55aq9Mb67HtaCnsLn59xvhO/t2mLLTHAp667hJFxpp7bCtr2zOrR1NELzFXmKln/2lw/PvxMSvrA==} + + '@cspell/dict-node@5.0.1': + resolution: {integrity: sha512-lax/jGz9h3Dv83v8LHa5G0bf6wm8YVRMzbjJPG/9rp7cAGPtdrga+XANFq+B7bY5+jiSA3zvj10LUFCFjnnCCg==} + + '@cspell/dict-npm@5.0.16': + resolution: {integrity: sha512-ZWPnLAziEcSCvV0c8k9Qj88pfMu+wZwM5Qks87ShsfBgI8uLZ9tGHravA7gmjH1Gd7Bgxy2ulvXtSqIWPh1lew==} + + '@cspell/dict-php@4.0.7': + resolution: {integrity: sha512-SUCOBfRDDFz1E2jnAZIIuy8BNbCc8i+VkiL9g4HH9tTN6Nlww5Uz2pMqYS6rZQkXuubqsbkbPlsRiuseEnTmYA==} + + '@cspell/dict-powershell@5.0.4': + resolution: {integrity: sha512-eosDShapDgBWN9ULF7+sRNdUtzRnUdsfEdBSchDm8FZA4HOqxUSZy3b/cX/Rdw0Fnw0AKgk0kzgXw7tS6vwJMQ==} + + '@cspell/dict-public-licenses@2.0.7': + resolution: {integrity: sha512-KlBXuGcN3LE7tQi/GEqKiDewWGGuopiAD0zRK1QilOx5Co8XAvs044gk4MNIQftc8r0nHeUI+irJKLGcR36DIQ==} + + '@cspell/dict-python@4.1.11': + resolution: {integrity: sha512-XG+v3PumfzUW38huSbfT15Vqt3ihNb462ulfXifpQllPok5OWynhszCLCRQjQReV+dgz784ST4ggRxW452/kVg==} + + '@cspell/dict-r@2.0.1': + resolution: {integrity: sha512-KCmKaeYMLm2Ip79mlYPc8p+B2uzwBp4KMkzeLd5E6jUlCL93Y5Nvq68wV5fRLDRTf7N1LvofkVFWfDcednFOgA==} + + '@cspell/dict-ruby@5.0.2': + resolution: {integrity: sha512-cIh8KTjpldzFzKGgrqUX4bFyav5lC52hXDKo4LbRuMVncs3zg4hcSf4HtURY+f2AfEZzN6ZKzXafQpThq3dl2g==} + + '@cspell/dict-rust@4.0.3': + resolution: {integrity: sha512-8DFCzkFQ+2k3fDaezWc/D+0AyiBBiOGYfSDUfrTNU7wpvUvJ6cRcAUshMI/cn2QW/mmxTspRgVlXsE6GUMz00Q==} + + '@cspell/dict-scala@5.0.2': + resolution: {integrity: sha512-v97ClgidZt99JUm7OjhQugDHmhx4U8fcgunHvD/BsXWjXNj4cTr0m0YjofyZoL44WpICsNuFV9F/sv9OM5HUEw==} + + '@cspell/dict-software-terms@3.4.0': + resolution: {integrity: sha512-RfrSrvKBaUZ1q3R6eksWe+SMUDNFzAthqXGJuZeylZBO3LdaYdhRDcqFzeMwksfCYjvBYeJ1Ady6NSpdXzESjQ==} + + '@cspell/dict-sql@2.1.3': + resolution: {integrity: sha512-SEyTNKJrjqD6PAzZ9WpdSu6P7wgdNtGV2RV8Kpuw1x6bV+YsSptuClYG+JSdRExBTE6LwIe1bTklejUp3ZP8TQ==} + + '@cspell/dict-svelte@1.0.2': + resolution: {integrity: sha512-rPJmnn/GsDs0btNvrRBciOhngKV98yZ9SHmg8qI6HLS8hZKvcXc0LMsf9LLuMK1TmS2+WQFAan6qeqg6bBxL2Q==} + + '@cspell/dict-swift@2.0.1': + resolution: {integrity: sha512-gxrCMUOndOk7xZFmXNtkCEeroZRnS2VbeaIPiymGRHj5H+qfTAzAKxtv7jJbVA3YYvEzWcVE2oKDP4wcbhIERw==} + + '@cspell/dict-terraform@1.0.0': + resolution: {integrity: sha512-Ak+vy4HP/bOgzf06BAMC30+ZvL9mzv21xLM2XtfnBLTDJGdxlk/nK0U6QT8VfFLqJ0ZZSpyOxGsUebWDCTr/zQ==} + + '@cspell/dict-typescript@3.1.5': + resolution: {integrity: sha512-EkIwwNV/xqEoBPJml2S16RXj65h1kvly8dfDLgXerrKw6puybZdvAHerAph6/uPTYdtLcsPyJYkPt5ISOJYrtw==} + + '@cspell/dict-vue@3.0.0': + resolution: {integrity: sha512-niiEMPWPV9IeRBRzZ0TBZmNnkK3olkOPYxC1Ny2AX4TGlYRajcW0WUtoSHmvvjZNfWLSg2L6ruiBeuPSbjnG6A==} + + '@cspell/dynamic-import@8.8.3': + resolution: {integrity: sha512-qpxGC2hGVfbSaLJkaEu//rqbgAOjYnMlbxD75Fk9ny96sr+ZI1YC0nmUErWlgXSbtjVY/DHCOu26Usweo5iRgA==} + engines: {node: '>=18.0'} + + '@cspell/eslint-plugin@8.8.3': + resolution: {integrity: sha512-N32SkoOa9DoUkfhsaGHg2mZHYUx8Tt0M4d34UAnbbqYEFwYP6wfrAzMhX35vicX1kh1KHeoSUsr5PukUhx8GzQ==} + engines: {node: '>=18'} + peerDependencies: + eslint: ^7 || ^8 || ^9 + + '@cspell/strong-weak-map@8.8.3': + resolution: {integrity: sha512-y/pL7Zex8iHQ54qDYvg9oCiCgfZ9DAUTOI/VtPFVC+42JqLx6YufYxJS2uAsFlfAXIPiRV8qnnG6BHImD1Ix6g==} + engines: {node: '>=18'} + + '@es-joy/jsdoccomment@0.43.1': + resolution: {integrity: sha512-I238eDtOolvCuvtxrnqtlBaw0BwdQuYqK7eA6XIonicMdOOOb75mqdIzkGDUbS04+1Di007rgm9snFRNeVrOog==} engines: {node: '>=16'} '@eslint-community/eslint-utils@4.4.0': @@ -291,30 +463,35 @@ packages: resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/eslintrc@2.1.4': - resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@eslint/config-array@0.15.1': + resolution: {integrity: sha512-K4gzNq+yymn/EVsXYmf+SBcBro8MTf+aXJZUphM96CdzUEr+ClGDvAbpmaEK+cGVigVXIgs9gNmvHAlrzzY5JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@8.57.0': - resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@eslint/eslintrc@3.1.0': + resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@humanwhocodes/config-array@0.11.14': - resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} - engines: {node: '>=10.10.0'} + '@eslint/js@9.4.0': + resolution: {integrity: sha512-fdI7VJjP3Rvc70lC4xkFXHB0fiPeojiL1PxVG6t1ZvXQrarj893PweuBTujxDUFk0Fxj4R7PIIAZ/aiiyZPZcg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.3': + resolution: {integrity: sha512-HAbhAYKfsAC2EkTqve00ibWIZlaU74Z1EHwAjYr4PXF0YU2VEA1zSIKSSpKszRLRWwHzzRZXvK632u+uXzvsvw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@humanwhocodes/module-importer@1.0.1': resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} - '@humanwhocodes/object-schema@2.0.3': - resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} + '@humanwhocodes/retry@0.3.0': + resolution: {integrity: sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==} + engines: {node: '>=18.18'} '@iarna/toml@2.2.5': resolution: {integrity: sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==} - '@inquirer/figures@1.0.1': - resolution: {integrity: sha512-mtup3wVKia3ZwULPHcbs4Mor8Voi+iIXEWD7wCNbIO6lYR62oPCTQyrddi5OMYVXHzeCSoneZwJuS8sBvlEwDw==} + '@inquirer/figures@1.0.3': + resolution: {integrity: sha512-ErXXzENMH5pJt5/ssXV0DfWUZqly8nGzf0UcBV9xTnP+KyffE2mqyxIMBrZ8ijQck2nU0TQm40EQB53YreyWHw==} engines: {node: '>=18'} '@istanbuljs/schema@0.1.3': @@ -358,12 +535,6 @@ packages: resolution: {integrity: sha512-/gKJun8NNiWGZJkGzI/Ragc53cOdcLNdzjLaIa+GEjguQs0ulsurx8WN0jijdK9yPqDvziX995sMRLyLt1uZMQ==} engines: {node: '>= 0.4'} - '@microsoft/tsdoc-config@0.16.2': - resolution: {integrity: sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==} - - '@microsoft/tsdoc@0.14.2': - resolution: {integrity: sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==} - '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -392,14 +563,11 @@ packages: resolution: {integrity: sha512-r+oZUH7aMFui1ypZnAvZmn0KSqAUgE1/tUXIWaqUCa1758ts/Jio84GZuzsvUkme98kv0WFY8//n0J1Z+vsIsQ==} engines: {node: '>= 18'} - '@octokit/openapi-types@20.0.0': - resolution: {integrity: sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==} - '@octokit/openapi-types@22.2.0': resolution: {integrity: sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==} - '@octokit/plugin-paginate-rest@9.2.1': - resolution: {integrity: sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw==} + '@octokit/plugin-paginate-rest@11.3.1': + resolution: {integrity: sha512-ryqobs26cLtM1kQxqeZui4v8FeznirUsksiA+RYemMPJ7Micju0WSkv50dBksTuZks9O5cg4wp+t8fZ/cLY56g==} engines: {node: '>= 18'} peerDependencies: '@octokit/core': '5' @@ -410,11 +578,11 @@ packages: peerDependencies: '@octokit/core': '5' - '@octokit/plugin-rest-endpoint-methods@10.4.1': - resolution: {integrity: sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==} + '@octokit/plugin-rest-endpoint-methods@13.2.2': + resolution: {integrity: sha512-EI7kXWidkt3Xlok5uN43suK99VWqc8OaIMktY9d9+RNKl69juoTyxmLoWPIZgJYzi41qj/9zU7G/ljnNOJ5AFA==} engines: {node: '>= 18'} peerDependencies: - '@octokit/core': '5' + '@octokit/core': ^5 '@octokit/request-error@5.1.0': resolution: {integrity: sha512-GETXfE05J0+7H2STzekpKObFe765O5dlAKUTLNGeH+x47z7JjXHfsHKo5z21D/o/IOZTUEI6nyWyR+bZVP/n5Q==} @@ -424,16 +592,17 @@ packages: resolution: {integrity: sha512-9Bb014e+m2TgBeEJGEbdplMVWwPmL1FPtggHQRkV+WVsMggPtEkLKPlcVYm/o8xKLkpJ7B+6N8WfQMtDLX2Dpw==} engines: {node: '>= 18'} - '@octokit/rest@20.1.0': - resolution: {integrity: sha512-STVO3itHQLrp80lvcYB2UIKoeil5Ctsgd2s1AM+du3HqZIR35ZH7WE9HLwUOLXH0myA0y3AGNPo8gZtcgIbw0g==} + '@octokit/rest@20.1.1': + resolution: {integrity: sha512-MB4AYDsM5jhIHro/dq4ix1iWTLGToIGk6cWF5L6vanFaMble5jTX/UBQyiv05HsWnwUtY8JrfHy2LWfKwihqMw==} engines: {node: '>= 18'} - '@octokit/types@12.6.0': - resolution: {integrity: sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==} - '@octokit/types@13.5.0': resolution: {integrity: sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ==} + '@pkgr/core@0.1.1': + resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + '@pnpm/config.env-replace@1.1.0': resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==} engines: {node: '>=12.22.0'} @@ -489,83 +658,83 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.17.2': - resolution: {integrity: sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==} + '@rollup/rollup-android-arm-eabi@4.18.0': + resolution: {integrity: sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.17.2': - resolution: {integrity: sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==} + '@rollup/rollup-android-arm64@4.18.0': + resolution: {integrity: sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.17.2': - resolution: {integrity: sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==} + '@rollup/rollup-darwin-arm64@4.18.0': + resolution: {integrity: sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.17.2': - resolution: {integrity: sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==} + '@rollup/rollup-darwin-x64@4.18.0': + resolution: {integrity: sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==} cpu: [x64] os: [darwin] - '@rollup/rollup-linux-arm-gnueabihf@4.17.2': - resolution: {integrity: sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==} + '@rollup/rollup-linux-arm-gnueabihf@4.18.0': + resolution: {integrity: sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.17.2': - resolution: {integrity: sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==} + '@rollup/rollup-linux-arm-musleabihf@4.18.0': + resolution: {integrity: sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.17.2': - resolution: {integrity: sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==} + '@rollup/rollup-linux-arm64-gnu@4.18.0': + resolution: {integrity: sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.17.2': - resolution: {integrity: sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==} + '@rollup/rollup-linux-arm64-musl@4.18.0': + resolution: {integrity: sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.17.2': - resolution: {integrity: sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==} + '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': + resolution: {integrity: sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.17.2': - resolution: {integrity: sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==} + '@rollup/rollup-linux-riscv64-gnu@4.18.0': + resolution: {integrity: sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.17.2': - resolution: {integrity: sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==} + '@rollup/rollup-linux-s390x-gnu@4.18.0': + resolution: {integrity: sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.17.2': - resolution: {integrity: sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==} + '@rollup/rollup-linux-x64-gnu@4.18.0': + resolution: {integrity: sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.17.2': - resolution: {integrity: sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==} + '@rollup/rollup-linux-x64-musl@4.18.0': + resolution: {integrity: sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.17.2': - resolution: {integrity: sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==} + '@rollup/rollup-win32-arm64-msvc@4.18.0': + resolution: {integrity: sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.17.2': - resolution: {integrity: sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==} + '@rollup/rollup-win32-ia32-msvc@4.18.0': + resolution: {integrity: sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.17.2': - resolution: {integrity: sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==} + '@rollup/rollup-win32-x64-msvc@4.18.0': + resolution: {integrity: sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==} cpu: [x64] os: [win32] @@ -595,6 +764,35 @@ packages: '@sinonjs/text-encoding@0.7.2': resolution: {integrity: sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==} + '@stylistic/eslint-plugin-js@1.8.1': + resolution: {integrity: sha512-c5c2C8Mos5tTQd+NWpqwEu7VT6SSRooAguFPMj1cp2RkTYl1ynKoXo8MWy3k4rkbzoeYHrqC2UlUzsroAN7wtQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: '>=8.40.0' + + '@stylistic/eslint-plugin-jsx@1.8.1': + resolution: {integrity: sha512-k1Eb6rcjMP+mmjvj+vd9y5KUdWn1OBkkPLHXhsrHt5lCDFZxJEs0aVQzE5lpYrtVZVkpc5esTtss/cPJux0lfA==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: '>=8.40.0' + + '@stylistic/eslint-plugin-plus@1.8.1': + resolution: {integrity: sha512-4+40H3lHYTN8OWz+US8CamVkO+2hxNLp9+CAjorI7top/lHqemhpJvKA1LD9Uh+WMY9DYWiWpL2+SZ2wAXY9fQ==} + peerDependencies: + eslint: '*' + + '@stylistic/eslint-plugin-ts@1.8.1': + resolution: {integrity: sha512-/q1m+ZuO1JHfiSF16EATFzv7XSJkc5W6DocfvH5o9oB6WWYFMF77fVoBWnKT3wGptPOc2hkRupRKhmeFROdfWA==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: '>=8.40.0' + + '@stylistic/eslint-plugin@1.8.1': + resolution: {integrity: sha512-64My6I7uCcmSQ//427Pfg2vjSf9SDzfsGIWohNFgISMLYdC5BzJqDo647iDDJzSxINh3WTC0Ql46ifiKuOoTyA==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: '>=8.40.0' + '@szmarczak/http-timer@5.0.1': resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} engines: {node: '>=14.16'} @@ -605,6 +803,9 @@ packages: '@types/conventional-commits-parser@5.0.0': resolution: {integrity: sha512-loB369iXNmAZglwWATL+WRe+CRMmmBPtpolYzIebFaX4YA3x+BEfLqhUAV9WanycKI3TG1IMr5bMJDajDKLlUQ==} + '@types/eslint@8.56.10': + resolution: {integrity: sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==} + '@types/estree@1.0.5': resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} @@ -626,14 +827,11 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/json5@0.0.29': - resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - '@types/minimatch@5.1.2': resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} - '@types/node@20.12.8': - resolution: {integrity: sha512-NU0rJLJnshZWdE/097cdCBbyW1h4hEg0xpovcoAQYHl8dnEyp/NAOiE45pvc+Bd1Dt+2r94v2eGFpQJ4R7g+2w==} + '@types/node@20.14.0': + resolution: {integrity: sha512-5cHBxFGJx6L4s56Bubp4fglrEpmyJypsqI6RgzMfBHWUJQGWAAi8cWcgetEbZXHYXo9C2Fa4EEds/uSyS4cxmA==} '@types/semver@7.5.8': resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} @@ -647,66 +845,93 @@ packages: '@types/yargs@17.0.32': resolution: {integrity: sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==} - '@typescript-eslint/eslint-plugin@7.8.0': - resolution: {integrity: sha512-gFTT+ezJmkwutUPmB0skOj3GZJtlEGnlssems4AjkVweUPGj7jRwwqg0Hhg7++kPGJqKtTYx+R05Ftww372aIg==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/eslint-plugin@8.0.0-alpha.25': + resolution: {integrity: sha512-IixQVZhrJ6rVd5Rx/WFGoIKLSXcMsueWa4bmnGlGTKSb4l+E+ORtEEY7RiXXeWK4mPgVpHHWZEElSdfflznpxA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^7.0.0 - eslint: ^8.56.0 + '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 + eslint: ^8.57.0 || ^9.0.0 typescript: '*' peerDependenciesMeta: typescript: optional: true - '@typescript-eslint/parser@7.8.0': - resolution: {integrity: sha512-KgKQly1pv0l4ltcftP59uQZCi4HUYswCLbTqVZEJu7uLX8CTLyswqMLqLN+2QFz4jCptqWVV4SB7vdxcH2+0kQ==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/parser@8.0.0-alpha.25': + resolution: {integrity: sha512-7CU44JP/FlZL/2dXwmU3BJ5tY1755FD190yCiiRYs41ds+CXdLlwkFD5PYVYPu+SFDT6trBnPo6d35ttHiDNnQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.56.0 + eslint: ^8.57.0 || ^9.0.0 typescript: '*' peerDependenciesMeta: typescript: optional: true - '@typescript-eslint/scope-manager@7.8.0': - resolution: {integrity: sha512-viEmZ1LmwsGcnr85gIq+FCYI7nO90DVbE37/ll51hjv9aG+YZMb4WDE2fyWpUR4O/UrhGRpYXK/XajcGTk2B8g==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/scope-manager@6.21.0': + resolution: {integrity: sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==} + engines: {node: ^16.0.0 || >=18.0.0} - '@typescript-eslint/type-utils@7.8.0': - resolution: {integrity: sha512-H70R3AefQDQpz9mGv13Uhi121FNMh+WEaRqcXTX09YEDky21km4dV1ZXJIp8QjXc4ZaVkXVdohvWDzbnbHDS+A==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/scope-manager@8.0.0-alpha.25': + resolution: {integrity: sha512-QPaOIVNwL7rl8QDK/GszySHARQ++QCBYooIRb3UnqaIzZrQPPx0ZqkiYdvi6NZOMxqOKo02jEelGYiqbdEAPDg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/type-utils@8.0.0-alpha.25': + resolution: {integrity: sha512-s5Y32/BL8qIfGMTyN0IQ5ZvYu8nVBzqjjUQncWKOHcqXrjQxgRteBScNgLXsJ20cjTgaEmPjMRvnR0k3Zcslvg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.56.0 typescript: '*' peerDependenciesMeta: typescript: optional: true - '@typescript-eslint/types@7.8.0': - resolution: {integrity: sha512-wf0peJ+ZGlcH+2ZS23aJbOv+ztjeeP8uQ9GgwMJGVLx/Nj9CJt17GWgWWoSmoRVKAX2X+7fzEnAjxdvK2gqCLw==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/types@6.21.0': + resolution: {integrity: sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==} + engines: {node: ^16.0.0 || >=18.0.0} - '@typescript-eslint/typescript-estree@7.8.0': - resolution: {integrity: sha512-5pfUCOwK5yjPaJQNy44prjCwtr981dO8Qo9J9PwYXZ0MosgAbfEMB008dJ5sNo3+/BN6ytBPuSvXUg9SAqB0dg==} + '@typescript-eslint/types@7.11.0': + resolution: {integrity: sha512-MPEsDRZTyCiXkD4vd3zywDCifi7tatc4K37KqTprCvaXptP7Xlpdw0NR2hRJTetG5TxbWDB79Ys4kLmHliEo/w==} engines: {node: ^18.18.0 || >=20.0.0} + + '@typescript-eslint/types@8.0.0-alpha.25': + resolution: {integrity: sha512-9C5VuCWi75jcgr/hQ/+9HVHjXv/7IyKHM5DMPZDWXrfvXS39UGYyDUx77PMHl+rre6Iz9kR/8TQUJdBX33iwzQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@6.21.0': + resolution: {integrity: sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==} + engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: typescript: '*' peerDependenciesMeta: typescript: optional: true - '@typescript-eslint/utils@7.8.0': - resolution: {integrity: sha512-L0yFqOCflVqXxiZyXrDr80lnahQfSOfc9ELAAZ75sqicqp2i36kEZZGuUymHNFoYOqxRT05up760b4iGsl02nQ==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/typescript-estree@8.0.0-alpha.25': + resolution: {integrity: sha512-+gThr9Q6t8aoiRn0PKGo79Vj/fvfFaCi31ugsoSzzccs0lO1f/zKSOXQAuqBiAVF/TuiuTA2FNAn1mO+UhnQqg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true - '@typescript-eslint/visitor-keys@7.8.0': - resolution: {integrity: sha512-q4/gibTNBQNA0lGyYQCmWRS5D15n8rXh4QjK3KV+MBPlTYHpfBUT3D3PaPR/HeNiI9W6R7FvlkcGhNyAoP+caA==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/utils@6.21.0': + resolution: {integrity: sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 - '@ungap/structured-clone@1.2.0': - resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + '@typescript-eslint/utils@8.0.0-alpha.25': + resolution: {integrity: sha512-L129Op2k+Rx9SIY03yAXu5unfvQDLZIHDZnRiKBYSEI8HTPhhe36v0EQebZxvbkfkoAU8+M5T7SKc1cP4L2yJw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + + '@typescript-eslint/visitor-keys@6.21.0': + resolution: {integrity: sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==} + engines: {node: ^16.0.0 || >=18.0.0} + + '@typescript-eslint/visitor-keys@8.0.0-alpha.25': + resolution: {integrity: sha512-9vnWmeuzFWpPhHsY+eBZQl1TA9MXAXwSTp84X4fcff2cqytaXw1hyK2+M/qrza5FSTdyl41c4hv2XSYkRC9HVQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} JSONStream@1.3.5: resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} @@ -733,8 +958,8 @@ packages: ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - ajv@8.13.0: - resolution: {integrity: sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==} + ajv@8.14.0: + resolution: {integrity: sha512-oYs1UUtO97ZO2lJ4bwnWeQW8/zvOIQLGKcvPTsWmvc2SYgBb+upuNS5NxoLaMU4h8Ju3Nbj6Cq8mD2LQoqVKFA==} ansi-align@3.0.1: resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} @@ -796,26 +1021,13 @@ packages: array-ify@1.0.0: resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} - array-includes@3.1.8: - resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} - engines: {node: '>= 0.4'} + array-timsort@1.0.3: + resolution: {integrity: sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==} array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} - array.prototype.findlastindex@1.2.5: - resolution: {integrity: sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==} - engines: {node: '>= 0.4'} - - array.prototype.flat@1.3.2: - resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} - engines: {node: '>= 0.4'} - - array.prototype.flatmap@1.3.2: - resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} - engines: {node: '>= 0.4'} - array.prototype.map@1.0.7: resolution: {integrity: sha512-XpcFfLoBEAhezrrNw1V+yLXkE7M6uR7xJEsxbG6c/V9v043qurwVJB9r9UTnoSioFDoz1i1VOydpWGmJpfVZbg==} engines: {node: '>= 0.4'} @@ -848,9 +1060,6 @@ packages: before-after-hook@2.2.3: resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==} - benchmark@2.1.4: - resolution: {integrity: sha512-l9MlfN4M1K/H2fbhfMy3B7vJd6AGKJVQn2h6Sg/Yx+KckoUA7ewS5Vv6TjSq18ooE1kS9hhAlQRH3AkXIh/aOQ==} - binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} @@ -868,8 +1077,8 @@ packages: brace-expansion@2.0.1: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} browser-stdout@1.3.1: @@ -881,10 +1090,6 @@ packages: buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - builtin-modules@3.3.0: - resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} - engines: {node: '>=6'} - bundle-name@4.1.0: resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} engines: {node: '>=18'} @@ -945,6 +1150,10 @@ packages: resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} engines: {node: '>=6'} + clear-module@4.1.2: + resolution: {integrity: sha512-LWAxzHqdHsAZlPlEyJ2Poz6AIs384mPeqLVCru2p0BrP9G/kVGuhNyZYClLO6cXlnuJjzC8xtsJIuMjKqLXoAw==} + engines: {node: '>=8'} + cli-boxes@3.0.0: resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} engines: {node: '>=10'} @@ -996,13 +1205,17 @@ packages: colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} - commander@11.1.0: - resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} - engines: {node: '>=16'} + commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + comment-json@4.2.3: + resolution: {integrity: sha512-SsxdiOf064DWoZLH799Ata6u7iV658A11PlWtZATDlXPpKGJnbJZ5Z24ybixAi+LUUqJ/GKowAejtC5GFUG7Tw==} + engines: {node: '>= 6'} + comment-parser@1.4.1: resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==} engines: {node: '>= 12.0.0'} @@ -1036,6 +1249,9 @@ packages: convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + cosmiconfig-typescript-loader@5.0.0: resolution: {integrity: sha512-+8cK7jRAReYkMwMiG+bxhcNKiHJDM6bR9FD/nGBXOWdMLuYawjF5cGrtLilJ+LGd3ZjCXnJjR5DkfWPoIVlqJA==} engines: {node: '>=v16'} @@ -1066,6 +1282,35 @@ packages: resolution: {integrity: sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==} engines: {node: '>=12'} + cspell-config-lib@8.8.3: + resolution: {integrity: sha512-61NKZrzTi9OLEEiZBggLQy9nswgR0gd6bKH06xXFQyRfNpAjaPOzOUFhSSfX1MQX+lQF3KtSYcHpppwbpPsL8w==} + engines: {node: '>=18'} + + cspell-dictionary@8.8.3: + resolution: {integrity: sha512-g2G3uh8JbuJKAYFdFQENcbTIrK9SJRXBiQ/t+ch+9I/t5HmuGOVe+wxKEM/0c9M2CRLpzJShBvttH9rnw4Yqfg==} + engines: {node: '>=18'} + + cspell-glob@8.8.3: + resolution: {integrity: sha512-9c4Nw/bIsjKSuBuRrLa1sWtIzbXXvja+FVbUOE9c2IiZfh6K1I+UssiXTbRTMg6qgTdkfT4o3KOcFN0ZcbmCUQ==} + engines: {node: '>=18'} + + cspell-grammar@8.8.3: + resolution: {integrity: sha512-3RP7xQ/6IiIjbWQDuE+4b0ERKkSWGMY75bd0oEsh5HcFhhOYphmcpxLxRRM/yxYQaYgdvq0QIcwrpanx86KJ7A==} + engines: {node: '>=18'} + hasBin: true + + cspell-io@8.8.3: + resolution: {integrity: sha512-vO7BUa6i7tjmQr+9dw/Ic7tm4ECnSUlbuMv0zJs/SIrO9AcID2pCWPeZNZEGAmeutrEOi2iThZ/uS33aCuv7Jw==} + engines: {node: '>=18'} + + cspell-lib@8.8.3: + resolution: {integrity: sha512-IqtTKBPug5Jzt9T8f/b6qGAbARRR5tpQkLjzsrfLzxM68ery23wEPDtmWToEyc9EslulZGLe0T78XuEU9AMF+g==} + engines: {node: '>=18'} + + cspell-trie-lib@8.8.3: + resolution: {integrity: sha512-0zrkrhrFLVajwo6++XD9a+r0Olml7UjPgbztjPKbXIJrZCradBF5rvt3wq5mPpsjq2+Dz0z6K5muZpbO+gqapQ==} + engines: {node: '>=18'} + dargs@8.1.0: resolution: {integrity: sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==} engines: {node: '>=12'} @@ -1093,16 +1338,17 @@ packages: dateformat@4.6.3: resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==} - debug@3.2.7: - resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} peerDependencies: supports-color: '*' peerDependenciesMeta: supports-color: optional: true - debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + debug@4.3.5: + resolution: {integrity: sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -1187,14 +1433,6 @@ packages: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} - doctrine@2.1.0: - resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} - engines: {node: '>=0.10.0'} - - doctrine@3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} - dot-prop@5.3.0: resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} engines: {node: '>=8'} @@ -1215,14 +1453,18 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - enhanced-resolve@5.16.0: - resolution: {integrity: sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==} + enhanced-resolve@5.16.1: + resolution: {integrity: sha512-4U5pNsuDl0EhuZpq46M5xPslstkviJuhrdobaRDBk2Jy2KO37FDAJl4lb2KlNabxT0m4MTK2UHNrsAcphE8nyw==} engines: {node: '>=10.13.0'} env-paths@2.2.1: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} + env-paths@3.0.0: + resolution: {integrity: sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} @@ -1252,9 +1494,6 @@ packages: resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} engines: {node: '>= 0.4'} - es-shim-unscopables@1.0.2: - resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} - es-to-primitive@1.2.1: resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} engines: {node: '>= 0.4'} @@ -1287,126 +1526,60 @@ packages: engines: {node: '>=6.0'} hasBin: true - eslint-compat-utils@0.5.0: - resolution: {integrity: sha512-dc6Y8tzEcSYZMHa+CMPLi/hyo1FzNeonbhJL7Ol0ccuKQkwopJcJBA9YL/xmMTLU1eKigXo9vj9nALElWYSowg==} + eslint-compat-utils@0.5.1: + resolution: {integrity: sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==} engines: {node: '>=12'} peerDependencies: eslint: '>=6.0.0' - eslint-config-love@47.0.0: - resolution: {integrity: sha512-wIeJhb4/NF7nE5Ltppg1e9dp1Auxx0+ZPRysrXQ3uBKlW4Nj/UiTZu4r3sKWCxo6HGcRcI4MC1Q5421y3fny2w==} - peerDependencies: - '@typescript-eslint/eslint-plugin': ^7.0.1 - eslint: ^8.0.1 - eslint-plugin-import: ^2.25.2 - eslint-plugin-n: '^15.0.0 || ^16.0.0 ' - eslint-plugin-promise: ^6.0.0 - typescript: '*' - - eslint-config-standard@17.1.0: - resolution: {integrity: sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==} - engines: {node: '>=12.0.0'} - peerDependencies: - eslint: ^8.0.1 - eslint-plugin-import: ^2.25.2 - eslint-plugin-n: '^15.0.0 || ^16.0.0 ' - eslint-plugin-promise: ^6.0.0 - eslint-define-config@2.1.0: resolution: {integrity: sha512-QUp6pM9pjKEVannNAbSJNeRuYwW3LshejfyBBpjeMGaJjaDUpVps4C6KVR8R7dWZnD3i0synmrE36znjTkJvdQ==} engines: {node: '>=18.0.0', npm: '>=9.0.0', pnpm: '>=8.6.0'} - eslint-import-resolver-node@0.3.9: - resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} - - eslint-import-resolver-typescript@3.6.1: - resolution: {integrity: sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - eslint: '*' - eslint-plugin-import: '*' - - eslint-module-utils@2.8.1: - resolution: {integrity: sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - eslint: - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true - eslint-plugin-es-x@7.6.0: resolution: {integrity: sha512-I0AmeNgevgaTR7y2lrVCJmGYF0rjoznpDvqV/kIkZSZbZ8Rw3eu4cGlvBBULScfkSOCzqKbff5LR4CNrV7mZHA==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: eslint: '>=8' - eslint-plugin-import@2.29.1: - resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - - eslint-plugin-jsdoc@48.2.3: - resolution: {integrity: sha512-r9DMAmFs66VNvNqRLLjHejdnJtILrt3xGi+Qx0op0oRfFGVpOR1Hb3BC++MacseHx93d8SKYPhyrC9BS7Os2QA==} + eslint-plugin-jsdoc@48.2.7: + resolution: {integrity: sha512-fYj3roTnkFL9OFFTB129rico8lerC5G8Vp2ZW9SjO9RNWG0exVvI+i/Y8Bpm1ufjR0uvT38xtoab/U0Hp8Ybog==} engines: {node: '>=18'} peerDependencies: eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 - eslint-plugin-n@17.4.0: - resolution: {integrity: sha512-RtgGgNpYxECwE9dFr+D66RtbN0B8r/fY6ZF8EVsmK2YnZxE8/n9LNQhgnkL9z37UFZjYVmvMuC32qu7fQBsLVQ==} + eslint-plugin-n@17.7.0: + resolution: {integrity: sha512-4Jg4ZKVE4VjHig2caBqPHYNW5na84RVufUuipFLJbgM/G57O6FdpUKJbHakCDJb/yjQuyqVzYWRtU3HNYaZUwg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: '>=8.23.0' - eslint-plugin-promise@6.1.1: - resolution: {integrity: sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - eslint-plugin-simple-import-sort@12.1.0: resolution: {integrity: sha512-Y2fqAfC11TcG/WP3TrI1Gi3p3nc8XJyEOJYHyEPEGI/UAgNx6akxxlX74p7SbAQdLcgASKhj8M0GKvH3vq/+ig==} peerDependencies: eslint: '>=5.0.0' - eslint-plugin-spellcheck@0.0.20: - resolution: {integrity: sha512-GJa6vgzWAYqe0elKADAsiBRrhvqBnKyt7tpFSqlCZJsK2W9+K80oMyHhKolA7vJ13H5RCGs5/KCN+mKUyKoAiA==} - peerDependencies: - eslint: '>=0.8.0' - - eslint-plugin-tsdoc@0.2.17: - resolution: {integrity: sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA==} - - eslint-scope@7.2.2: - resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + eslint-scope@8.0.1: + resolution: {integrity: sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} eslint-visitor-keys@3.4.3: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - eslint@8.57.0: - resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + eslint-visitor-keys@4.0.0: + resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint@9.4.0: + resolution: {integrity: sha512-sjc7Y8cUD1IlwYcTS9qPSvGjAC8Ne9LctpxKKu3x/1IC9bnOg98Zy6GxEJUfr1NojMgVPlyANXYns8oE2c1TAA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true + espree@10.0.1: + resolution: {integrity: sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + espree@9.6.1: resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1431,6 +1604,9 @@ packages: estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} @@ -1457,6 +1633,10 @@ packages: fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + fast-equals@5.0.1: + resolution: {integrity: sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ==} + engines: {node: '>=6.0.0'} + fast-glob@3.3.2: resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} engines: {node: '>=8.6.0'} @@ -1474,12 +1654,12 @@ packages: resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} engines: {node: ^12.20 || >= 14.13} - file-entry-cache@6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} - fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} find-up@5.0.0: @@ -1490,9 +1670,9 @@ packages: resolution: {integrity: sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==} engines: {node: '>=18'} - flat-cache@3.2.0: - resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} - engines: {node: ^10.12.0 || >=12.0.0} + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} flat@5.0.2: resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} @@ -1545,6 +1725,10 @@ packages: functions-have-names@1.2.3: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + gensequence@7.0.0: + resolution: {integrity: sha512-47Frx13aZh01afHJTB3zTtKIlFI6vWY+MYCN9Qpew6i52rfKjnhCF/l1YlC8UmEMvvntZZ6z4PiCcmyuedR2aQ==} + engines: {node: '>=18'} + get-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} @@ -1569,8 +1753,8 @@ packages: resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} engines: {node: '>= 0.4'} - get-tsconfig@4.7.3: - resolution: {integrity: sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==} + get-tsconfig@4.7.5: + resolution: {integrity: sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==} get-uri@6.0.3: resolution: {integrity: sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==} @@ -1597,10 +1781,12 @@ packages: glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported glob@8.1.0: resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} engines: {node: '>=12'} + deprecated: Glob versions prior to v9 are no longer supported global-directory@4.0.1: resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} @@ -1610,12 +1796,12 @@ packages: resolution: {integrity: sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==} engines: {node: '>=10'} - globals@13.24.0: - resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} - engines: {node: '>=8'} + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} - globals@15.1.0: - resolution: {integrity: sha512-926gJqg+4mkxwYKiFvoomM4J0kWESfk3qfTvRL2/oc/tK/eTDBbrfcKnSa2KtfdxB5onoL7D3A3qIHQFpd4+UA==} + globals@15.3.0: + resolution: {integrity: sha512-cCdyVjIUVTtX8ZsPkq1oCsOsLmGIswqnjZYMJJTGaNApj1yHtLSymKhwH51ttirREn75z3p4k051clwg7rvNKA==} engines: {node: '>=18'} globalthis@1.0.4: @@ -1665,6 +1851,10 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} + has-own-prop@2.0.0: + resolution: {integrity: sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==} + engines: {node: '>=8'} + has-property-descriptors@1.0.2: resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} @@ -1714,10 +1904,6 @@ packages: resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} engines: {node: '>=16.17.0'} - hunspell-spellchecker@1.0.2: - resolution: {integrity: sha512-4DwmFAvlz+ChsqLDsZT2cwBsYNXh+oWboemxXtafwKIyItq52xfR4e4kr017sLAoPaSYVofSOvPUfmOAhXyYvw==} - hasBin: true - husky@9.0.11: resolution: {integrity: sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==} engines: {node: '>=18'} @@ -1755,6 +1941,7 @@ packages: inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -1770,12 +1957,12 @@ packages: resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - ini@4.1.2: - resolution: {integrity: sha512-AMB1mvwR1pyBFY/nSevUX6y8nJWS63/SzUKD3JyQn97s4xgIdgQPT75IRouIiBAN4yLQBUShNYVW0+UG25daCw==} + ini@4.1.3: + resolution: {integrity: sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - inquirer@9.2.19: - resolution: {integrity: sha512-WpxOT71HGsFya6/mj5PUue0sWwbpbiPfAR+332zLj/siB0QA1PZM8v3GepegFV1Op189UxHUCF6y8AySdtOMVA==} + inquirer@9.2.22: + resolution: {integrity: sha512-SqLLa/Oe5rZUagTR9z+Zd6izyatHglbmbvVofo1KzuVB54YHleWzeHNLoR7FOICGOeQSqeLh1cordb3MzhGcEw==} engines: {node: '>=18'} internal-slot@1.0.7: @@ -1812,10 +1999,6 @@ packages: resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} engines: {node: '>= 0.4'} - is-builtin-module@3.2.1: - resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} - engines: {node: '>=6'} - is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} @@ -2031,9 +2214,6 @@ packages: resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} hasBin: true - jju@1.4.0: - resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} - js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -2066,10 +2246,6 @@ packages: json-stringify-safe@5.0.1: resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} - json5@1.0.2: - resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} - hasBin: true - jsonc-parser@3.2.1: resolution: {integrity: sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==} @@ -2094,20 +2270,20 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - lilconfig@3.0.0: - resolution: {integrity: sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==} + lilconfig@3.1.1: + resolution: {integrity: sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==} engines: {node: '>=14'} lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - lint-staged@15.2.2: - resolution: {integrity: sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==} + lint-staged@15.2.5: + resolution: {integrity: sha512-j+DfX7W9YUvdzEZl3Rk47FhDF6xwDBV5wwsCPw6BwWZVPYJemusQmvb9bRsW23Sqsaa+vRloAWogbK4BUuU2zA==} engines: {node: '>=18.12.0'} hasBin: true - listr2@8.0.1: - resolution: {integrity: sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==} + listr2@8.2.1: + resolution: {integrity: sha512-irTfvpib/rNiD637xeevjO2l3Z5loZmuaRi0L0YE5LfijwVY96oyVn0DFD3o/teAok7nfobMG1THvvcHh/BP6g==} engines: {node: '>=18.0.0'} locate-path@6.0.0: @@ -2195,10 +2371,6 @@ packages: resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - lru-cache@7.18.3: resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} engines: {node: '>=12'} @@ -2233,14 +2405,10 @@ packages: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} - micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + micromatch@4.0.7: + resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} engines: {node: '>=8.6'} - microtime@3.1.1: - resolution: {integrity: sha512-to1r7o24cDsud9IhN6/8wGmMx5R2kT0w2Xwm5okbYI3d1dk6Xv0m+Z+jg2vS9pt+ocgQHTCtgs/YuyJhySzxNg==} - engines: {node: '>= 14.13.0'} - mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} @@ -2272,6 +2440,10 @@ packages: resolution: {integrity: sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==} engines: {node: '>=10'} + minimatch@9.0.3: + resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} + engines: {node: '>=16 || 14 >=14.17'} + minimatch@9.0.4: resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} engines: {node: '>=16 || 14 >=14.17'} @@ -2306,6 +2478,13 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + neostandard@0.5.1: + resolution: {integrity: sha512-PaeGRlEyc0EQ0a5ORPZurasGhjfdgFB2TLGyTAnl7Vj1xerZ3vgT5NFdbaVAb1PtoT/HOFtOajYAUguNl9hDew==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + eslint: ^9.0.0 + netmask@2.0.2: resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} engines: {node: '>= 0.4.0'} @@ -2314,11 +2493,8 @@ packages: resolution: {integrity: sha512-NHDDGYudnvRutt/VhKFlX26IotXe1w0cmkDm6JGquh5bz/bDTw0LufSmH/GxTjEdpHEO+bVKFTwdrcGa/9XlKQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - nise@5.1.9: - resolution: {integrity: sha512-qOnoujW4SV6e40dYxJOb3uvuoPHtmLzIk4TFo+j0jPJoC+5Z9xja5qH5JZobEPsa8+YYphMrOSwnrshEhG2qww==} - - node-addon-api@5.1.0: - resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==} + nise@6.0.0: + resolution: {integrity: sha512-K8ePqo9BFvN31HXwEtTNGzgrPpmvgciDsFz8aztFjt4LqKO/JeFD8tBOeuDiCMXrIl/m1YvfH8auSpxfaD09wg==} node-domexception@1.0.0: resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} @@ -2328,10 +2504,6 @@ packages: resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - node-gyp-build@4.8.0: - resolution: {integrity: sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==} - hasBin: true - normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -2363,18 +2535,6 @@ packages: resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} engines: {node: '>= 0.4'} - object.fromentries@2.0.8: - resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} - engines: {node: '>= 0.4'} - - object.groupby@1.0.3: - resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} - engines: {node: '>= 0.4'} - - object.values@1.2.0: - resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==} - engines: {node: '>= 0.4'} - once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} @@ -2454,6 +2614,10 @@ packages: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} + parent-module@2.0.0: + resolution: {integrity: sha512-uo0Z9JJeWzv8BG+tRcapBKNJ0dro9cLyczGzulS6EfeyAdeC9sbojtW6XwvYxJkEne9En+J2XEl4zyglVeIwFg==} + engines: {node: '>=8'} + parse-json@5.2.0: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} @@ -2498,21 +2662,26 @@ packages: resolution: {integrity: sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==} engines: {node: '>=12'} - picocolors@1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + peowly@1.3.0: + resolution: {integrity: sha512-Tvj2QMNEuvL3WmaG4agZ6IGjOLGcvQSQO9TBJFkh9op+tNX3/J3UZtxPQWUA+d+Lki4u8WaNJ0OUwNt1G3GnWg==} + engines: {node: '>=18.6.0'} + + picocolors@1.0.1: + resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + pidtree@0.6.0: resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} engines: {node: '>=0.10'} hasBin: true - platform@1.3.6: - resolution: {integrity: sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==} - possible-typed-array-names@1.0.0: resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} engines: {node: '>= 0.4'} @@ -2521,8 +2690,8 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - prettier@3.2.5: - resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} + prettier@3.3.0: + resolution: {integrity: sha512-J9odKxERhCQ10OC2yb93583f6UnYutOeiV5i0zEDS7UGTdUt0u+y8erxl3lBKvwo/JHyyoEdXjwp4dke9oyZ/g==} engines: {node: '>=14'} hasBin: true @@ -2602,11 +2771,15 @@ packages: resolution: {integrity: sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==} engines: {node: '>=12'} - release-it@17.2.1: - resolution: {integrity: sha512-zBOpaHyjrXC3g/9rHyQlvuDw9yCn9AGphrlL+t3gWNEhbZKEQ62WNY45JxllcJMNx9orQUxBZ3o7pVCqkeuTbg==} - engines: {node: ^18.18.0 || ^20.8.0 || ^21.0.0} + release-it@17.3.0: + resolution: {integrity: sha512-7t9a2WEwqQKCdteshZUrO/3RX60plS5CzYAFr5+4Zj8qvRx1pFOFVglJSz4BeFAEd2yejpPxfI60+qRUzLEDZw==} + engines: {node: ^18.18.0 || ^20.8.0 || ^22.0.0} hasBin: true + repeat-string@1.6.1: + resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} + engines: {node: '>=0.10'} + require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -2629,9 +2802,6 @@ packages: resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - resolve@1.19.0: - resolution: {integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==} - resolve@1.22.8: resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} hasBin: true @@ -2661,6 +2831,7 @@ packages: rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true rollup-plugin-analyzer@4.0.0: @@ -2674,15 +2845,15 @@ packages: resolution: {integrity: sha512-/VpLMtDy+8wwRlDANuYmDa9ss/knGsAgrDhM+tEwB1npHwNu4DYNmDfUL55csse/GHs9Q+SMT/rw9uiaZ3pnzA==} engines: {node: '>=10'} - rollup-plugin-dts@6.1.0: - resolution: {integrity: sha512-ijSCPICkRMDKDLBK9torss07+8dl9UpY9z1N/zTeA1cIqdzMlpkV3MOOC7zukyvQfDyxa1s3Dl2+DeiP/G6DOw==} + rollup-plugin-dts@6.1.1: + resolution: {integrity: sha512-aSHRcJ6KG2IHIioYlvAOcEq6U99sVtqDDKVhnwt70rW6tsz3tv5OSjEiWcgzfsHdLyGXZ/3b/7b/+Za3Y6r1XA==} engines: {node: '>=16'} peerDependencies: rollup: ^3.29.4 || ^4 typescript: ^4.5 || ^5.0 - rollup@4.17.2: - resolution: {integrity: sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==} + rollup@4.18.0: + resolution: {integrity: sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -2718,8 +2889,8 @@ packages: resolution: {integrity: sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==} engines: {node: '>=12'} - semver@7.6.0: - resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} + semver@7.6.2: + resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} engines: {node: '>=10'} hasBin: true @@ -2764,8 +2935,8 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} - sinon@17.0.1: - resolution: {integrity: sha512-wmwE19Lie0MLT+ZYNpDymasPHUKTaZHUH/pKEubRXIzySv9Atnlw+BUMGCzWgV7b7wO+Hw6f1TEOr0IUnmU8/g==} + sinon@18.0.0: + resolution: {integrity: sha512-+dXDXzD1sBO6HlmZDd7mXZCR/y5ECiEiGCBSGuFD/kZ0bDTofPYc6JaeGmPSF+1j1MejGUWkORbYOLDyvqCWpA==} slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} @@ -2811,8 +2982,8 @@ packages: spdx-expression-parse@4.0.0: resolution: {integrity: sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==} - spdx-license-ids@3.0.17: - resolution: {integrity: sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==} + spdx-license-ids@3.0.18: + resolution: {integrity: sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==} split2@4.2.0: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} @@ -2874,10 +3045,6 @@ packages: resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} engines: {node: '>=12'} - strip-bom@3.0.0: - resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} - engines: {node: '>=4'} - strip-final-newline@2.0.0: resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} engines: {node: '>=6'} @@ -2910,12 +3077,16 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + synckit@0.9.0: + resolution: {integrity: sha512-7RnqIMq572L8PeEzKeBINYEJDDxpcH8JEgLwUqBd3TkofhFRbkq4QLR0u+36avGAhCRbk2nnmjcW9SE531hPDg==} + engines: {node: ^14.18.0 || >=16.0.0} + tapable@2.2.1: resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} engines: {node: '>=6'} - tatami-ng@0.4.4: - resolution: {integrity: sha512-/YSab/Z35+RcEBSxOn6tbQqdk00Yfr0l0Wlnp+TGyr7vGzuGV4Pod1oZARZ8iG7fOI9CASNlzifV0FELii7NAg==} + tatami-ng@0.4.13: + resolution: {integrity: sha512-55myS02pVzECcyRgq7Rio0mPQyKO5f6f3L4aO/2engizicFOvhWxboJqwjULjhlQInjnN2Th6YH4s+YTahJX7w==} peerDependencies: typescript: ^5.0.0 @@ -2958,9 +3129,6 @@ packages: peerDependencies: typescript: '>=4.2.0' - tsconfig-paths@3.15.0: - resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} - tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} @@ -2972,10 +3140,6 @@ packages: resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} engines: {node: '>=4'} - type-fest@0.20.2: - resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} - engines: {node: '>=10'} - type-fest@0.21.3: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} @@ -3014,6 +3178,15 @@ packages: peerDependencies: typescript: 4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x + typescript-eslint@8.0.0-alpha.25: + resolution: {integrity: sha512-gQsFB1mdtxduwOCXpgKTIDyyZ38iaam443/Kf8LYbKbt8rMCgz3HRYVR8sp8QF9H26MgTrYE7jGqfWXWYowTcQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + typescript@5.4.5: resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} engines: {node: '>=14.17'} @@ -3062,16 +3235,22 @@ packages: resolution: {integrity: sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==} engines: {node: '>=10.12.0'} - validator@13.11.0: - resolution: {integrity: sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==} + validator@13.12.0: + resolution: {integrity: sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==} engines: {node: '>= 0.10'} + vscode-languageserver-textdocument@1.0.11: + resolution: {integrity: sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==} + vscode-oniguruma@1.7.0: resolution: {integrity: sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==} vscode-textmate@8.0.0: resolution: {integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==} + vscode-uri@3.0.8: + resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==} + wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} @@ -3139,12 +3318,10 @@ packages: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} - yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - - yaml@2.3.4: - resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==} + yaml@2.4.3: + resolution: {integrity: sha512-sntgmxj8o7DE7g/Qi60cqpLBA3HG3STcDA0kO+WfB05jEKhZMbY7umNm2rBpQvsmZ16/lPXCJGW2672dgOUkrg==} engines: {node: '>= 14'} + hasBin: true yargs-parser@20.2.4: resolution: {integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==} @@ -3176,62 +3353,62 @@ packages: snapshots: - '@babel/code-frame@7.24.2': + '@babel/code-frame@7.24.6': dependencies: - '@babel/highlight': 7.24.5 - picocolors: 1.0.0 + '@babel/highlight': 7.24.6 + picocolors: 1.0.1 - '@babel/helper-validator-identifier@7.24.5': {} + '@babel/helper-validator-identifier@7.24.6': {} - '@babel/highlight@7.24.5': + '@babel/highlight@7.24.6': dependencies: - '@babel/helper-validator-identifier': 7.24.5 + '@babel/helper-validator-identifier': 7.24.6 chalk: 2.4.2 js-tokens: 4.0.0 - picocolors: 1.0.0 + picocolors: 1.0.1 '@bcoe/v8-coverage@0.2.3': {} - '@biomejs/biome@1.7.2': + '@biomejs/biome@1.7.3': optionalDependencies: - '@biomejs/cli-darwin-arm64': 1.7.2 - '@biomejs/cli-darwin-x64': 1.7.2 - '@biomejs/cli-linux-arm64': 1.7.2 - '@biomejs/cli-linux-arm64-musl': 1.7.2 - '@biomejs/cli-linux-x64': 1.7.2 - '@biomejs/cli-linux-x64-musl': 1.7.2 - '@biomejs/cli-win32-arm64': 1.7.2 - '@biomejs/cli-win32-x64': 1.7.2 - - '@biomejs/cli-darwin-arm64@1.7.2': + '@biomejs/cli-darwin-arm64': 1.7.3 + '@biomejs/cli-darwin-x64': 1.7.3 + '@biomejs/cli-linux-arm64': 1.7.3 + '@biomejs/cli-linux-arm64-musl': 1.7.3 + '@biomejs/cli-linux-x64': 1.7.3 + '@biomejs/cli-linux-x64-musl': 1.7.3 + '@biomejs/cli-win32-arm64': 1.7.3 + '@biomejs/cli-win32-x64': 1.7.3 + + '@biomejs/cli-darwin-arm64@1.7.3': optional: true - '@biomejs/cli-darwin-x64@1.7.2': + '@biomejs/cli-darwin-x64@1.7.3': optional: true - '@biomejs/cli-linux-arm64-musl@1.7.2': + '@biomejs/cli-linux-arm64-musl@1.7.3': optional: true - '@biomejs/cli-linux-arm64@1.7.2': + '@biomejs/cli-linux-arm64@1.7.3': optional: true - '@biomejs/cli-linux-x64-musl@1.7.2': + '@biomejs/cli-linux-x64-musl@1.7.3': optional: true - '@biomejs/cli-linux-x64@1.7.2': + '@biomejs/cli-linux-x64@1.7.3': optional: true - '@biomejs/cli-win32-arm64@1.7.2': + '@biomejs/cli-win32-arm64@1.7.3': optional: true - '@biomejs/cli-win32-x64@1.7.2': + '@biomejs/cli-win32-x64@1.7.3': optional: true - '@commitlint/cli@19.3.0(@types/node@20.12.8)(typescript@5.4.5)': + '@commitlint/cli@19.3.0(@types/node@20.14.0)(typescript@5.4.5)': dependencies: '@commitlint/format': 19.3.0 '@commitlint/lint': 19.2.2 - '@commitlint/load': 19.2.0(@types/node@20.12.8)(typescript@5.4.5) + '@commitlint/load': 19.2.0(@types/node@20.14.0)(typescript@5.4.5) '@commitlint/read': 19.2.1 '@commitlint/types': 19.0.3 execa: 8.0.1 @@ -3248,7 +3425,7 @@ snapshots: '@commitlint/config-validator@19.0.3': dependencies: '@commitlint/types': 19.0.3 - ajv: 8.13.0 + ajv: 8.14.0 '@commitlint/ensure@19.0.3': dependencies: @@ -3269,7 +3446,7 @@ snapshots: '@commitlint/is-ignored@19.2.2': dependencies: '@commitlint/types': 19.0.3 - semver: 7.6.0 + semver: 7.6.2 '@commitlint/lint@19.2.2': dependencies: @@ -3278,7 +3455,7 @@ snapshots: '@commitlint/rules': 19.0.3 '@commitlint/types': 19.0.3 - '@commitlint/load@19.2.0(@types/node@20.12.8)(typescript@5.4.5)': + '@commitlint/load@19.2.0(@types/node@20.14.0)(typescript@5.4.5)': dependencies: '@commitlint/config-validator': 19.0.3 '@commitlint/execute-rule': 19.0.0 @@ -3286,7 +3463,7 @@ snapshots: '@commitlint/types': 19.0.3 chalk: 5.3.0 cosmiconfig: 9.0.0(typescript@5.4.5) - cosmiconfig-typescript-loader: 5.0.0(@types/node@20.12.8)(cosmiconfig@9.0.0(typescript@5.4.5))(typescript@5.4.5) + cosmiconfig-typescript-loader: 5.0.0(@types/node@20.14.0)(cosmiconfig@9.0.0(typescript@5.4.5))(typescript@5.4.5) lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 lodash.uniq: 4.5.0 @@ -3338,25 +3515,223 @@ snapshots: '@types/conventional-commits-parser': 5.0.0 chalk: 5.3.0 - '@es-joy/jsdoccomment@0.42.0': + '@cspell/cspell-bundled-dicts@8.8.3': + dependencies: + '@cspell/dict-ada': 4.0.2 + '@cspell/dict-aws': 4.0.2 + '@cspell/dict-bash': 4.1.3 + '@cspell/dict-companies': 3.1.2 + '@cspell/dict-cpp': 5.1.8 + '@cspell/dict-cryptocurrencies': 5.0.0 + '@cspell/dict-csharp': 4.0.2 + '@cspell/dict-css': 4.0.12 + '@cspell/dict-dart': 2.0.3 + '@cspell/dict-django': 4.1.0 + '@cspell/dict-docker': 1.1.7 + '@cspell/dict-dotnet': 5.0.2 + '@cspell/dict-elixir': 4.0.3 + '@cspell/dict-en-common-misspellings': 2.0.1 + '@cspell/dict-en-gb': 1.1.33 + '@cspell/dict-en_us': 4.3.21 + '@cspell/dict-filetypes': 3.0.4 + '@cspell/dict-fonts': 4.0.0 + '@cspell/dict-fsharp': 1.0.1 + '@cspell/dict-fullstack': 3.1.8 + '@cspell/dict-gaming-terms': 1.0.5 + '@cspell/dict-git': 3.0.0 + '@cspell/dict-golang': 6.0.9 + '@cspell/dict-google': 1.0.1 + '@cspell/dict-haskell': 4.0.1 + '@cspell/dict-html': 4.0.5 + '@cspell/dict-html-symbol-entities': 4.0.0 + '@cspell/dict-java': 5.0.6 + '@cspell/dict-julia': 1.0.1 + '@cspell/dict-k8s': 1.0.5 + '@cspell/dict-latex': 4.0.0 + '@cspell/dict-lorem-ipsum': 4.0.0 + '@cspell/dict-lua': 4.0.3 + '@cspell/dict-makefile': 1.0.0 + '@cspell/dict-monkeyc': 1.0.6 + '@cspell/dict-node': 5.0.1 + '@cspell/dict-npm': 5.0.16 + '@cspell/dict-php': 4.0.7 + '@cspell/dict-powershell': 5.0.4 + '@cspell/dict-public-licenses': 2.0.7 + '@cspell/dict-python': 4.1.11 + '@cspell/dict-r': 2.0.1 + '@cspell/dict-ruby': 5.0.2 + '@cspell/dict-rust': 4.0.3 + '@cspell/dict-scala': 5.0.2 + '@cspell/dict-software-terms': 3.4.0 + '@cspell/dict-sql': 2.1.3 + '@cspell/dict-svelte': 1.0.2 + '@cspell/dict-swift': 2.0.1 + '@cspell/dict-terraform': 1.0.0 + '@cspell/dict-typescript': 3.1.5 + '@cspell/dict-vue': 3.0.0 + + '@cspell/cspell-pipe@8.8.3': {} + + '@cspell/cspell-resolver@8.8.3': + dependencies: + global-directory: 4.0.1 + + '@cspell/cspell-service-bus@8.8.3': {} + + '@cspell/cspell-types@8.8.3': {} + + '@cspell/dict-ada@4.0.2': {} + + '@cspell/dict-aws@4.0.2': {} + + '@cspell/dict-bash@4.1.3': {} + + '@cspell/dict-companies@3.1.2': {} + + '@cspell/dict-cpp@5.1.8': {} + + '@cspell/dict-cryptocurrencies@5.0.0': {} + + '@cspell/dict-csharp@4.0.2': {} + + '@cspell/dict-css@4.0.12': {} + + '@cspell/dict-dart@2.0.3': {} + + '@cspell/dict-data-science@1.0.11': {} + + '@cspell/dict-django@4.1.0': {} + + '@cspell/dict-docker@1.1.7': {} + + '@cspell/dict-dotnet@5.0.2': {} + + '@cspell/dict-elixir@4.0.3': {} + + '@cspell/dict-en-common-misspellings@2.0.1': {} + + '@cspell/dict-en-gb@1.1.33': {} + + '@cspell/dict-en_us@4.3.21': {} + + '@cspell/dict-filetypes@3.0.4': {} + + '@cspell/dict-fonts@4.0.0': {} + + '@cspell/dict-fsharp@1.0.1': {} + + '@cspell/dict-fullstack@3.1.8': {} + + '@cspell/dict-gaming-terms@1.0.5': {} + + '@cspell/dict-git@3.0.0': {} + + '@cspell/dict-golang@6.0.9': {} + + '@cspell/dict-google@1.0.1': {} + + '@cspell/dict-haskell@4.0.1': {} + + '@cspell/dict-html-symbol-entities@4.0.0': {} + + '@cspell/dict-html@4.0.5': {} + + '@cspell/dict-java@5.0.6': {} + + '@cspell/dict-julia@1.0.1': {} + + '@cspell/dict-k8s@1.0.5': {} + + '@cspell/dict-latex@4.0.0': {} + + '@cspell/dict-lorem-ipsum@4.0.0': {} + + '@cspell/dict-lua@4.0.3': {} + + '@cspell/dict-makefile@1.0.0': {} + + '@cspell/dict-monkeyc@1.0.6': {} + + '@cspell/dict-node@5.0.1': {} + + '@cspell/dict-npm@5.0.16': {} + + '@cspell/dict-php@4.0.7': {} + + '@cspell/dict-powershell@5.0.4': {} + + '@cspell/dict-public-licenses@2.0.7': {} + + '@cspell/dict-python@4.1.11': dependencies: + '@cspell/dict-data-science': 1.0.11 + + '@cspell/dict-r@2.0.1': {} + + '@cspell/dict-ruby@5.0.2': {} + + '@cspell/dict-rust@4.0.3': {} + + '@cspell/dict-scala@5.0.2': {} + + '@cspell/dict-software-terms@3.4.0': {} + + '@cspell/dict-sql@2.1.3': {} + + '@cspell/dict-svelte@1.0.2': {} + + '@cspell/dict-swift@2.0.1': {} + + '@cspell/dict-terraform@1.0.0': {} + + '@cspell/dict-typescript@3.1.5': {} + + '@cspell/dict-vue@3.0.0': {} + + '@cspell/dynamic-import@8.8.3': + dependencies: + import-meta-resolve: 4.1.0 + + '@cspell/eslint-plugin@8.8.3(eslint@9.4.0)': + dependencies: + '@cspell/cspell-types': 8.8.3 + cspell-lib: 8.8.3 + eslint: 9.4.0 + estree-walker: 3.0.3 + synckit: 0.9.0 + + '@cspell/strong-weak-map@8.8.3': {} + + '@es-joy/jsdoccomment@0.43.1': + dependencies: + '@types/eslint': 8.56.10 + '@types/estree': 1.0.5 + '@typescript-eslint/types': 7.11.0 comment-parser: 1.4.1 esquery: 1.5.0 jsdoc-type-pratt-parser: 4.0.0 - '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)': + '@eslint-community/eslint-utils@4.4.0(eslint@9.4.0)': dependencies: - eslint: 8.57.0 + eslint: 9.4.0 eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.10.0': {} - '@eslint/eslintrc@2.1.4': + '@eslint/config-array@0.15.1': + dependencies: + '@eslint/object-schema': 2.1.3 + debug: 4.3.5 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/eslintrc@3.1.0': dependencies: ajv: 6.12.6 - debug: 4.3.4(supports-color@8.1.1) - espree: 9.6.1 - globals: 13.24.0 + debug: 4.3.5 + espree: 10.0.1 + globals: 14.0.0 ignore: 5.3.1 import-fresh: 3.3.0 js-yaml: 4.1.0 @@ -3365,23 +3740,17 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@8.57.0': {} + '@eslint/js@9.4.0': {} - '@humanwhocodes/config-array@0.11.14': - dependencies: - '@humanwhocodes/object-schema': 2.0.3 - debug: 4.3.4(supports-color@8.1.1) - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color + '@eslint/object-schema@2.1.3': {} '@humanwhocodes/module-importer@1.0.1': {} - '@humanwhocodes/object-schema@2.0.3': {} + '@humanwhocodes/retry@0.3.0': {} '@iarna/toml@2.2.5': {} - '@inquirer/figures@1.0.1': {} + '@inquirer/figures@1.0.3': {} '@istanbuljs/schema@0.1.3': {} @@ -3398,7 +3767,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.12.8 + '@types/node': 20.14.0 '@types/yargs': 17.0.32 chalk: 4.1.2 @@ -3428,15 +3797,6 @@ snapshots: dependencies: call-bind: 1.0.7 - '@microsoft/tsdoc-config@0.16.2': - dependencies: - '@microsoft/tsdoc': 0.14.2 - ajv: 6.12.6 - jju: 1.4.0 - resolve: 1.19.0 - - '@microsoft/tsdoc@0.14.2': {} - '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -3472,23 +3832,21 @@ snapshots: '@octokit/types': 13.5.0 universal-user-agent: 6.0.1 - '@octokit/openapi-types@20.0.0': {} - '@octokit/openapi-types@22.2.0': {} - '@octokit/plugin-paginate-rest@9.2.1(@octokit/core@5.2.0)': + '@octokit/plugin-paginate-rest@11.3.1(@octokit/core@5.2.0)': dependencies: '@octokit/core': 5.2.0 - '@octokit/types': 12.6.0 + '@octokit/types': 13.5.0 '@octokit/plugin-request-log@4.0.1(@octokit/core@5.2.0)': dependencies: '@octokit/core': 5.2.0 - '@octokit/plugin-rest-endpoint-methods@10.4.1(@octokit/core@5.2.0)': + '@octokit/plugin-rest-endpoint-methods@13.2.2(@octokit/core@5.2.0)': dependencies: '@octokit/core': 5.2.0 - '@octokit/types': 12.6.0 + '@octokit/types': 13.5.0 '@octokit/request-error@5.1.0': dependencies: @@ -3503,21 +3861,19 @@ snapshots: '@octokit/types': 13.5.0 universal-user-agent: 6.0.1 - '@octokit/rest@20.1.0': + '@octokit/rest@20.1.1': dependencies: '@octokit/core': 5.2.0 - '@octokit/plugin-paginate-rest': 9.2.1(@octokit/core@5.2.0) + '@octokit/plugin-paginate-rest': 11.3.1(@octokit/core@5.2.0) '@octokit/plugin-request-log': 4.0.1(@octokit/core@5.2.0) - '@octokit/plugin-rest-endpoint-methods': 10.4.1(@octokit/core@5.2.0) - - '@octokit/types@12.6.0': - dependencies: - '@octokit/openapi-types': 20.0.0 + '@octokit/plugin-rest-endpoint-methods': 13.2.2(@octokit/core@5.2.0) '@octokit/types@13.5.0': dependencies: '@octokit/openapi-types': 22.2.0 + '@pkgr/core@0.1.1': {} + '@pnpm/config.env-replace@1.1.0': {} '@pnpm/network.ca-file@1.0.2': @@ -3530,94 +3886,94 @@ snapshots: '@pnpm/network.ca-file': 1.0.2 config-chain: 1.1.13 - '@release-it/bumper@6.0.1(release-it@17.2.1(typescript@5.4.5))': + '@release-it/bumper@6.0.1(release-it@17.3.0(typescript@5.4.5))': dependencies: '@iarna/toml': 2.2.5 detect-indent: 7.0.1 fast-glob: 3.3.2 - ini: 4.1.2 + ini: 4.1.3 js-yaml: 4.1.0 lodash-es: 4.17.21 - release-it: 17.2.1(typescript@5.4.5) - semver: 7.6.0 + release-it: 17.3.0(typescript@5.4.5) + semver: 7.6.2 - '@release-it/keep-a-changelog@5.0.0(release-it@17.2.1(typescript@5.4.5))': + '@release-it/keep-a-changelog@5.0.0(release-it@17.3.0(typescript@5.4.5))': dependencies: detect-newline: 4.0.1 - release-it: 17.2.1(typescript@5.4.5) + release-it: 17.3.0(typescript@5.4.5) string-template: 1.0.0 - '@rollup/plugin-terser@0.4.4(rollup@4.17.2)': + '@rollup/plugin-terser@0.4.4(rollup@4.18.0)': dependencies: serialize-javascript: 6.0.2 smob: 1.5.0 terser: 5.31.0 optionalDependencies: - rollup: 4.17.2 + rollup: 4.18.0 - '@rollup/plugin-typescript@11.1.6(rollup@4.17.2)(tslib@2.6.2)(typescript@5.4.5)': + '@rollup/plugin-typescript@11.1.6(rollup@4.18.0)(tslib@2.6.2)(typescript@5.4.5)': dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.17.2) + '@rollup/pluginutils': 5.1.0(rollup@4.18.0) resolve: 1.22.8 typescript: 5.4.5 optionalDependencies: - rollup: 4.17.2 + rollup: 4.18.0 tslib: 2.6.2 - '@rollup/pluginutils@5.1.0(rollup@4.17.2)': + '@rollup/pluginutils@5.1.0(rollup@4.18.0)': dependencies: '@types/estree': 1.0.5 estree-walker: 2.0.2 picomatch: 2.3.1 optionalDependencies: - rollup: 4.17.2 + rollup: 4.18.0 - '@rollup/rollup-android-arm-eabi@4.17.2': + '@rollup/rollup-android-arm-eabi@4.18.0': optional: true - '@rollup/rollup-android-arm64@4.17.2': + '@rollup/rollup-android-arm64@4.18.0': optional: true - '@rollup/rollup-darwin-arm64@4.17.2': + '@rollup/rollup-darwin-arm64@4.18.0': optional: true - '@rollup/rollup-darwin-x64@4.17.2': + '@rollup/rollup-darwin-x64@4.18.0': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.17.2': + '@rollup/rollup-linux-arm-gnueabihf@4.18.0': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.17.2': + '@rollup/rollup-linux-arm-musleabihf@4.18.0': optional: true - '@rollup/rollup-linux-arm64-gnu@4.17.2': + '@rollup/rollup-linux-arm64-gnu@4.18.0': optional: true - '@rollup/rollup-linux-arm64-musl@4.17.2': + '@rollup/rollup-linux-arm64-musl@4.18.0': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.17.2': + '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.17.2': + '@rollup/rollup-linux-riscv64-gnu@4.18.0': optional: true - '@rollup/rollup-linux-s390x-gnu@4.17.2': + '@rollup/rollup-linux-s390x-gnu@4.18.0': optional: true - '@rollup/rollup-linux-x64-gnu@4.17.2': + '@rollup/rollup-linux-x64-gnu@4.18.0': optional: true - '@rollup/rollup-linux-x64-musl@4.17.2': + '@rollup/rollup-linux-x64-musl@4.18.0': optional: true - '@rollup/rollup-win32-arm64-msvc@4.17.2': + '@rollup/rollup-win32-arm64-msvc@4.18.0': optional: true - '@rollup/rollup-win32-ia32-msvc@4.17.2': + '@rollup/rollup-win32-ia32-msvc@4.18.0': optional: true - '@rollup/rollup-win32-x64-msvc@4.17.2': + '@rollup/rollup-win32-x64-msvc@4.18.0': optional: true '@sinclair/typebox@0.27.8': {} @@ -3646,6 +4002,54 @@ snapshots: '@sinonjs/text-encoding@0.7.2': {} + '@stylistic/eslint-plugin-js@1.8.1(eslint@9.4.0)': + dependencies: + '@types/eslint': 8.56.10 + acorn: 8.11.3 + escape-string-regexp: 4.0.0 + eslint: 9.4.0 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + + '@stylistic/eslint-plugin-jsx@1.8.1(eslint@9.4.0)': + dependencies: + '@stylistic/eslint-plugin-js': 1.8.1(eslint@9.4.0) + '@types/eslint': 8.56.10 + eslint: 9.4.0 + estraverse: 5.3.0 + picomatch: 4.0.2 + + '@stylistic/eslint-plugin-plus@1.8.1(eslint@9.4.0)(typescript@5.4.5)': + dependencies: + '@types/eslint': 8.56.10 + '@typescript-eslint/utils': 6.21.0(eslint@9.4.0)(typescript@5.4.5) + eslint: 9.4.0 + transitivePeerDependencies: + - supports-color + - typescript + + '@stylistic/eslint-plugin-ts@1.8.1(eslint@9.4.0)(typescript@5.4.5)': + dependencies: + '@stylistic/eslint-plugin-js': 1.8.1(eslint@9.4.0) + '@types/eslint': 8.56.10 + '@typescript-eslint/utils': 6.21.0(eslint@9.4.0)(typescript@5.4.5) + eslint: 9.4.0 + transitivePeerDependencies: + - supports-color + - typescript + + '@stylistic/eslint-plugin@1.8.1(eslint@9.4.0)(typescript@5.4.5)': + dependencies: + '@stylistic/eslint-plugin-js': 1.8.1(eslint@9.4.0) + '@stylistic/eslint-plugin-jsx': 1.8.1(eslint@9.4.0) + '@stylistic/eslint-plugin-plus': 1.8.1(eslint@9.4.0)(typescript@5.4.5) + '@stylistic/eslint-plugin-ts': 1.8.1(eslint@9.4.0)(typescript@5.4.5) + '@types/eslint': 8.56.10 + eslint: 9.4.0 + transitivePeerDependencies: + - supports-color + - typescript + '@szmarczak/http-timer@5.0.1': dependencies: defer-to-connect: 2.0.1 @@ -3654,14 +4058,19 @@ snapshots: '@types/conventional-commits-parser@5.0.0': dependencies: - '@types/node': 20.12.8 + '@types/node': 20.14.0 + + '@types/eslint@8.56.10': + dependencies: + '@types/estree': 1.0.5 + '@types/json-schema': 7.0.15 '@types/estree@1.0.5': {} '@types/glob@7.2.0': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 20.12.8 + '@types/node': 20.14.0 '@types/http-cache-semantics@4.0.4': {} @@ -3677,11 +4086,9 @@ snapshots: '@types/json-schema@7.0.15': {} - '@types/json5@0.0.29': {} - '@types/minimatch@5.1.2': {} - '@types/node@20.12.8': + '@types/node@20.14.0': dependencies: undici-types: 5.26.5 @@ -3695,93 +4102,129 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@7.8.0(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/eslint-plugin@8.0.0-alpha.25(@typescript-eslint/parser@8.0.0-alpha.25(eslint@9.4.0)(typescript@5.4.5))(eslint@9.4.0)(typescript@5.4.5)': dependencies: '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 7.8.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/scope-manager': 7.8.0 - '@typescript-eslint/type-utils': 7.8.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/utils': 7.8.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.8.0 - debug: 4.3.4(supports-color@8.1.1) - eslint: 8.57.0 + '@typescript-eslint/parser': 8.0.0-alpha.25(eslint@9.4.0)(typescript@5.4.5) + '@typescript-eslint/scope-manager': 8.0.0-alpha.25 + '@typescript-eslint/type-utils': 8.0.0-alpha.25(eslint@9.4.0)(typescript@5.4.5) + '@typescript-eslint/utils': 8.0.0-alpha.25(eslint@9.4.0)(typescript@5.4.5) + '@typescript-eslint/visitor-keys': 8.0.0-alpha.25 + eslint: 9.4.0 graphemer: 1.4.0 ignore: 5.3.1 natural-compare: 1.4.0 - semver: 7.6.0 ts-api-utils: 1.3.0(typescript@5.4.5) optionalDependencies: typescript: 5.4.5 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/parser@8.0.0-alpha.25(eslint@9.4.0)(typescript@5.4.5)': dependencies: - '@typescript-eslint/scope-manager': 7.8.0 - '@typescript-eslint/types': 7.8.0 - '@typescript-eslint/typescript-estree': 7.8.0(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.8.0 - debug: 4.3.4(supports-color@8.1.1) - eslint: 8.57.0 + '@typescript-eslint/scope-manager': 8.0.0-alpha.25 + '@typescript-eslint/types': 8.0.0-alpha.25 + '@typescript-eslint/typescript-estree': 8.0.0-alpha.25(typescript@5.4.5) + '@typescript-eslint/visitor-keys': 8.0.0-alpha.25 + debug: 4.3.5 + eslint: 9.4.0 optionalDependencies: typescript: 5.4.5 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@7.8.0': + '@typescript-eslint/scope-manager@6.21.0': dependencies: - '@typescript-eslint/types': 7.8.0 - '@typescript-eslint/visitor-keys': 7.8.0 + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/visitor-keys': 6.21.0 - '@typescript-eslint/type-utils@7.8.0(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/scope-manager@8.0.0-alpha.25': dependencies: - '@typescript-eslint/typescript-estree': 7.8.0(typescript@5.4.5) - '@typescript-eslint/utils': 7.8.0(eslint@8.57.0)(typescript@5.4.5) - debug: 4.3.4(supports-color@8.1.1) - eslint: 8.57.0 + '@typescript-eslint/types': 8.0.0-alpha.25 + '@typescript-eslint/visitor-keys': 8.0.0-alpha.25 + + '@typescript-eslint/type-utils@8.0.0-alpha.25(eslint@9.4.0)(typescript@5.4.5)': + dependencies: + '@typescript-eslint/typescript-estree': 8.0.0-alpha.25(typescript@5.4.5) + '@typescript-eslint/utils': 8.0.0-alpha.25(eslint@9.4.0)(typescript@5.4.5) + debug: 4.3.5 ts-api-utils: 1.3.0(typescript@5.4.5) optionalDependencies: typescript: 5.4.5 transitivePeerDependencies: + - eslint - supports-color - '@typescript-eslint/types@7.8.0': {} + '@typescript-eslint/types@6.21.0': {} + + '@typescript-eslint/types@7.11.0': {} + + '@typescript-eslint/types@8.0.0-alpha.25': {} - '@typescript-eslint/typescript-estree@7.8.0(typescript@5.4.5)': + '@typescript-eslint/typescript-estree@6.21.0(typescript@5.4.5)': dependencies: - '@typescript-eslint/types': 7.8.0 - '@typescript-eslint/visitor-keys': 7.8.0 - debug: 4.3.4(supports-color@8.1.1) + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/visitor-keys': 6.21.0 + debug: 4.3.5 + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.3 + semver: 7.6.2 + ts-api-utils: 1.3.0(typescript@5.4.5) + optionalDependencies: + typescript: 5.4.5 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/typescript-estree@8.0.0-alpha.25(typescript@5.4.5)': + dependencies: + '@typescript-eslint/types': 8.0.0-alpha.25 + '@typescript-eslint/visitor-keys': 8.0.0-alpha.25 + debug: 4.3.5 globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.4 - semver: 7.6.0 + semver: 7.6.2 ts-api-utils: 1.3.0(typescript@5.4.5) optionalDependencies: typescript: 5.4.5 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@7.8.0(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/utils@6.21.0(eslint@9.4.0)(typescript@5.4.5)': dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.4.0) '@types/json-schema': 7.0.15 '@types/semver': 7.5.8 - '@typescript-eslint/scope-manager': 7.8.0 - '@typescript-eslint/types': 7.8.0 - '@typescript-eslint/typescript-estree': 7.8.0(typescript@5.4.5) - eslint: 8.57.0 - semver: 7.6.0 + '@typescript-eslint/scope-manager': 6.21.0 + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.4.5) + eslint: 9.4.0 + semver: 7.6.2 + transitivePeerDependencies: + - supports-color + - typescript + + '@typescript-eslint/utils@8.0.0-alpha.25(eslint@9.4.0)(typescript@5.4.5)': + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@9.4.0) + '@typescript-eslint/scope-manager': 8.0.0-alpha.25 + '@typescript-eslint/types': 8.0.0-alpha.25 + '@typescript-eslint/typescript-estree': 8.0.0-alpha.25(typescript@5.4.5) + eslint: 9.4.0 transitivePeerDependencies: - supports-color - typescript - '@typescript-eslint/visitor-keys@7.8.0': + '@typescript-eslint/visitor-keys@6.21.0': dependencies: - '@typescript-eslint/types': 7.8.0 + '@typescript-eslint/types': 6.21.0 eslint-visitor-keys: 3.4.3 - '@ungap/structured-clone@1.2.0': {} + '@typescript-eslint/visitor-keys@8.0.0-alpha.25': + dependencies: + '@typescript-eslint/types': 8.0.0-alpha.25 + eslint-visitor-keys: 3.4.3 JSONStream@1.3.5: dependencies: @@ -3796,7 +4239,7 @@ snapshots: agent-base@7.1.1: dependencies: - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5 transitivePeerDependencies: - supports-color @@ -3812,7 +4255,7 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 - ajv@8.13.0: + ajv@8.14.0: dependencies: fast-deep-equal: 3.1.3 json-schema-traverse: 1.0.0 @@ -3865,40 +4308,10 @@ snapshots: array-ify@1.0.0: {} - array-includes@3.1.8: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-object-atoms: 1.0.0 - get-intrinsic: 1.2.4 - is-string: 1.0.7 + array-timsort@1.0.3: {} array-union@2.1.0: {} - array.prototype.findlastindex@1.2.5: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - es-object-atoms: 1.0.0 - es-shim-unscopables: 1.0.2 - - array.prototype.flat@1.3.2: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-shim-unscopables: 1.0.2 - - array.prototype.flatmap@1.3.2: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-shim-unscopables: 1.0.2 - array.prototype.map@1.0.7: dependencies: call-bind: 1.0.7 @@ -3939,11 +4352,6 @@ snapshots: before-after-hook@2.2.3: {} - benchmark@2.1.4: - dependencies: - lodash: 4.17.21 - platform: 1.3.6 - binary-extensions@2.3.0: {} bl@4.1.0: @@ -3972,9 +4380,9 @@ snapshots: dependencies: balanced-match: 1.0.2 - braces@3.0.2: + braces@3.0.3: dependencies: - fill-range: 7.0.1 + fill-range: 7.1.1 browser-stdout@1.3.1: {} @@ -3985,8 +4393,6 @@ snapshots: base64-js: 1.5.1 ieee754: 1.2.1 - builtin-modules@3.3.0: {} - bundle-name@4.1.0: dependencies: run-applescript: 7.0.0 @@ -4049,7 +4455,7 @@ snapshots: chokidar@3.5.3: dependencies: anymatch: 3.1.3 - braces: 3.0.2 + braces: 3.0.3 glob-parent: 5.1.2 is-binary-path: 2.1.0 is-glob: 4.0.3 @@ -4062,6 +4468,11 @@ snapshots: clean-stack@2.2.0: {} + clear-module@4.1.2: + dependencies: + parent-module: 2.0.0 + resolve-from: 5.0.0 + cli-boxes@3.0.0: {} cli-cursor@3.1.0: @@ -4109,10 +4520,18 @@ snapshots: colorette@2.0.20: {} - commander@11.1.0: {} + commander@12.1.0: {} commander@2.20.3: {} + comment-json@4.2.3: + dependencies: + array-timsort: 1.0.3 + core-util-is: 1.0.3 + esprima: 4.0.1 + has-own-prop: 2.0.0 + repeat-string: 1.6.1 + comment-parser@1.4.1: {} compare-func@2.0.0: @@ -4152,9 +4571,11 @@ snapshots: convert-source-map@2.0.0: {} - cosmiconfig-typescript-loader@5.0.0(@types/node@20.12.8)(cosmiconfig@9.0.0(typescript@5.4.5))(typescript@5.4.5): + core-util-is@1.0.3: {} + + cosmiconfig-typescript-loader@5.0.0(@types/node@20.14.0)(cosmiconfig@9.0.0(typescript@5.4.5))(typescript@5.4.5): dependencies: - '@types/node': 20.12.8 + '@types/node': 20.14.0 cosmiconfig: 9.0.0(typescript@5.4.5) jiti: 1.21.0 typescript: 5.4.5 @@ -4182,6 +4603,64 @@ snapshots: dependencies: type-fest: 1.4.0 + cspell-config-lib@8.8.3: + dependencies: + '@cspell/cspell-types': 8.8.3 + comment-json: 4.2.3 + yaml: 2.4.3 + + cspell-dictionary@8.8.3: + dependencies: + '@cspell/cspell-pipe': 8.8.3 + '@cspell/cspell-types': 8.8.3 + cspell-trie-lib: 8.8.3 + fast-equals: 5.0.1 + gensequence: 7.0.0 + + cspell-glob@8.8.3: + dependencies: + micromatch: 4.0.7 + + cspell-grammar@8.8.3: + dependencies: + '@cspell/cspell-pipe': 8.8.3 + '@cspell/cspell-types': 8.8.3 + + cspell-io@8.8.3: + dependencies: + '@cspell/cspell-service-bus': 8.8.3 + + cspell-lib@8.8.3: + dependencies: + '@cspell/cspell-bundled-dicts': 8.8.3 + '@cspell/cspell-pipe': 8.8.3 + '@cspell/cspell-resolver': 8.8.3 + '@cspell/cspell-types': 8.8.3 + '@cspell/dynamic-import': 8.8.3 + '@cspell/strong-weak-map': 8.8.3 + clear-module: 4.1.2 + comment-json: 4.2.3 + cspell-config-lib: 8.8.3 + cspell-dictionary: 8.8.3 + cspell-glob: 8.8.3 + cspell-grammar: 8.8.3 + cspell-io: 8.8.3 + cspell-trie-lib: 8.8.3 + env-paths: 3.0.0 + fast-equals: 5.0.1 + gensequence: 7.0.0 + import-fresh: 3.3.0 + resolve-from: 5.0.0 + vscode-languageserver-textdocument: 1.0.11 + vscode-uri: 3.0.8 + xdg-basedir: 5.1.0 + + cspell-trie-lib@8.8.3: + dependencies: + '@cspell/cspell-pipe': 8.8.3 + '@cspell/cspell-types': 8.8.3 + gensequence: 7.0.0 + dargs@8.1.0: {} data-uri-to-buffer@4.0.1: {} @@ -4208,16 +4687,16 @@ snapshots: dateformat@4.6.3: {} - debug@3.2.7: - dependencies: - ms: 2.1.3 - debug@4.3.4(supports-color@8.1.1): dependencies: ms: 2.1.2 optionalDependencies: supports-color: 8.1.1 + debug@4.3.5: + dependencies: + ms: 2.1.2 + decamelize@4.0.0: {} decompress-response@6.0.0: @@ -4288,14 +4767,6 @@ snapshots: dependencies: path-type: 4.0.0 - doctrine@2.1.0: - dependencies: - esutils: 2.0.3 - - doctrine@3.0.0: - dependencies: - esutils: 2.0.3 - dot-prop@5.3.0: dependencies: is-obj: 2.0.0 @@ -4312,13 +4783,15 @@ snapshots: emoji-regex@9.2.2: {} - enhanced-resolve@5.16.0: + enhanced-resolve@5.16.1: dependencies: graceful-fs: 4.2.11 tapable: 2.2.1 env-paths@2.2.1: {} + env-paths@3.0.0: {} + error-ex@1.3.2: dependencies: is-arrayish: 0.2.1 @@ -4402,10 +4875,6 @@ snapshots: has-tostringtag: 1.0.2 hasown: 2.0.2 - es-shim-unscopables@1.0.2: - dependencies: - hasown: 2.0.2 - es-to-primitive@1.2.1: dependencies: is-callable: 1.2.7 @@ -4432,188 +4901,87 @@ snapshots: optionalDependencies: source-map: 0.6.1 - eslint-compat-utils@0.5.0(eslint@8.57.0): - dependencies: - eslint: 8.57.0 - semver: 7.6.0 - - eslint-config-love@47.0.0(@typescript-eslint/eslint-plugin@7.8.0(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0))(eslint-plugin-n@17.4.0(eslint@8.57.0))(eslint-plugin-promise@6.1.1(eslint@8.57.0))(eslint@8.57.0)(typescript@5.4.5): - dependencies: - '@typescript-eslint/eslint-plugin': 7.8.0(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/parser': 7.8.0(eslint@8.57.0)(typescript@5.4.5) - eslint: 8.57.0 - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) - eslint-plugin-n: 17.4.0(eslint@8.57.0) - eslint-plugin-promise: 6.1.1(eslint@8.57.0) - typescript: 5.4.5 - transitivePeerDependencies: - - supports-color - - eslint-config-standard@17.1.0(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0))(eslint-plugin-n@17.4.0(eslint@8.57.0))(eslint-plugin-promise@6.1.1(eslint@8.57.0))(eslint@8.57.0): + eslint-compat-utils@0.5.1(eslint@9.4.0): dependencies: - eslint: 8.57.0 - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) - eslint-plugin-n: 17.4.0(eslint@8.57.0) - eslint-plugin-promise: 6.1.1(eslint@8.57.0) + eslint: 9.4.0 + semver: 7.6.2 eslint-define-config@2.1.0: {} - eslint-import-resolver-node@0.3.9: - dependencies: - debug: 3.2.7 - is-core-module: 2.13.1 - resolve: 1.22.8 - transitivePeerDependencies: - - supports-color - - eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.29.1)(eslint@8.57.0): - dependencies: - debug: 4.3.4(supports-color@8.1.1) - enhanced-resolve: 5.16.0 - eslint: 8.57.0 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) - fast-glob: 3.3.2 - get-tsconfig: 4.7.3 - is-core-module: 2.13.1 - is-glob: 4.0.3 - transitivePeerDependencies: - - '@typescript-eslint/parser' - - eslint-import-resolver-node - - eslint-import-resolver-webpack - - supports-color - - eslint-module-utils@2.8.1(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0): + eslint-plugin-es-x@7.6.0(eslint@9.4.0): dependencies: - debug: 3.2.7 - optionalDependencies: - '@typescript-eslint/parser': 7.8.0(eslint@8.57.0)(typescript@5.4.5) - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.29.1)(eslint@8.57.0) - transitivePeerDependencies: - - supports-color - - eslint-plugin-es-x@7.6.0(eslint@8.57.0): - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.4.0) '@eslint-community/regexpp': 4.10.0 - eslint: 8.57.0 - eslint-compat-utils: 0.5.0(eslint@8.57.0) - - eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): - dependencies: - array-includes: 3.1.8 - array.prototype.findlastindex: 1.2.5 - array.prototype.flat: 1.3.2 - array.prototype.flatmap: 1.3.2 - debug: 3.2.7 - doctrine: 2.1.0 - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) - hasown: 2.0.2 - is-core-module: 2.13.1 - is-glob: 4.0.3 - minimatch: 3.1.2 - object.fromentries: 2.0.8 - object.groupby: 1.0.3 - object.values: 1.2.0 - semver: 7.6.0 - tsconfig-paths: 3.15.0 - optionalDependencies: - '@typescript-eslint/parser': 7.8.0(eslint@8.57.0)(typescript@5.4.5) - transitivePeerDependencies: - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color + eslint: 9.4.0 + eslint-compat-utils: 0.5.1(eslint@9.4.0) - eslint-plugin-jsdoc@48.2.3(eslint@8.57.0): + eslint-plugin-jsdoc@48.2.7(eslint@9.4.0): dependencies: - '@es-joy/jsdoccomment': 0.42.0 + '@es-joy/jsdoccomment': 0.43.1 are-docs-informative: 0.0.2 comment-parser: 1.4.1 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5 escape-string-regexp: 4.0.0 - eslint: 8.57.0 + eslint: 9.4.0 esquery: 1.5.0 - is-builtin-module: 3.2.1 - semver: 7.6.0 + semver: 7.6.2 spdx-expression-parse: 4.0.0 transitivePeerDependencies: - supports-color - eslint-plugin-n@17.4.0(eslint@8.57.0): + eslint-plugin-n@17.7.0(eslint@9.4.0): dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - enhanced-resolve: 5.16.0 - eslint: 8.57.0 - eslint-plugin-es-x: 7.6.0(eslint@8.57.0) - get-tsconfig: 4.7.3 - globals: 15.1.0 + '@eslint-community/eslint-utils': 4.4.0(eslint@9.4.0) + enhanced-resolve: 5.16.1 + eslint: 9.4.0 + eslint-plugin-es-x: 7.6.0(eslint@9.4.0) + get-tsconfig: 4.7.5 + globals: 15.3.0 ignore: 5.3.1 minimatch: 9.0.4 - semver: 7.6.0 - - eslint-plugin-promise@6.1.1(eslint@8.57.0): - dependencies: - eslint: 8.57.0 - - eslint-plugin-simple-import-sort@12.1.0(eslint@8.57.0): - dependencies: - eslint: 8.57.0 - - eslint-plugin-spellcheck@0.0.20(eslint@8.57.0): - dependencies: - eslint: 8.57.0 - globals: 13.24.0 - hunspell-spellchecker: 1.0.2 - lodash: 4.17.21 + semver: 7.6.2 - eslint-plugin-tsdoc@0.2.17: + eslint-plugin-simple-import-sort@12.1.0(eslint@9.4.0): dependencies: - '@microsoft/tsdoc': 0.14.2 - '@microsoft/tsdoc-config': 0.16.2 + eslint: 9.4.0 - eslint-scope@7.2.2: + eslint-scope@8.0.1: dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 eslint-visitor-keys@3.4.3: {} - eslint@8.57.0: + eslint-visitor-keys@4.0.0: {} + + eslint@9.4.0: dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.4.0) '@eslint-community/regexpp': 4.10.0 - '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.57.0 - '@humanwhocodes/config-array': 0.11.14 + '@eslint/config-array': 0.15.1 + '@eslint/eslintrc': 3.1.0 + '@eslint/js': 9.4.0 '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.3.0 '@nodelib/fs.walk': 1.2.8 - '@ungap/structured-clone': 1.2.0 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.4(supports-color@8.1.1) - doctrine: 3.0.0 + debug: 4.3.5 escape-string-regexp: 4.0.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 + eslint-scope: 8.0.1 + eslint-visitor-keys: 4.0.0 + espree: 10.0.1 esquery: 1.5.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 + file-entry-cache: 8.0.0 find-up: 5.0.0 glob-parent: 6.0.2 - globals: 13.24.0 - graphemer: 1.4.0 ignore: 5.3.1 imurmurhash: 0.1.4 is-glob: 4.0.3 is-path-inside: 3.0.3 - js-yaml: 4.1.0 json-stable-stringify-without-jsonify: 1.0.1 levn: 0.4.1 lodash.merge: 4.6.2 @@ -4625,6 +4993,12 @@ snapshots: transitivePeerDependencies: - supports-color + espree@10.0.1: + dependencies: + acorn: 8.11.3 + acorn-jsx: 5.3.2(acorn@8.11.3) + eslint-visitor-keys: 4.0.0 + espree@9.6.1: dependencies: acorn: 8.11.3 @@ -4645,6 +5019,10 @@ snapshots: estree-walker@2.0.2: {} + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.5 + esutils@2.0.3: {} eventemitter3@5.0.1: {} @@ -4689,13 +5067,15 @@ snapshots: fast-deep-equal@3.1.3: {} + fast-equals@5.0.1: {} + fast-glob@3.3.2: dependencies: '@nodelib/fs.stat': 2.0.5 '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 - micromatch: 4.0.5 + micromatch: 4.0.7 fast-json-stable-stringify@2.1.0: {} @@ -4710,11 +5090,11 @@ snapshots: node-domexception: 1.0.0 web-streams-polyfill: 3.3.3 - file-entry-cache@6.0.1: + file-entry-cache@8.0.0: dependencies: - flat-cache: 3.2.0 + flat-cache: 4.0.1 - fill-range@7.0.1: + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -4729,11 +5109,10 @@ snapshots: path-exists: 5.0.0 unicorn-magic: 0.1.0 - flat-cache@3.2.0: + flat-cache@4.0.1: dependencies: flatted: 3.3.1 keyv: 4.5.4 - rimraf: 3.0.2 flat@5.0.2: {} @@ -4784,6 +5163,8 @@ snapshots: functions-have-names@1.2.3: {} + gensequence@7.0.0: {} + get-caller-file@2.0.5: {} get-east-asian-width@1.2.0: {} @@ -4806,7 +5187,7 @@ snapshots: es-errors: 1.3.0 get-intrinsic: 1.2.4 - get-tsconfig@4.7.3: + get-tsconfig@4.7.5: dependencies: resolve-pkg-maps: 1.0.0 @@ -4814,7 +5195,7 @@ snapshots: dependencies: basic-ftp: 5.0.5 data-uri-to-buffer: 6.0.2 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5 fs-extra: 11.2.0 transitivePeerDependencies: - supports-color @@ -4867,11 +5248,9 @@ snapshots: dependencies: ini: 2.0.0 - globals@13.24.0: - dependencies: - type-fest: 0.20.2 + globals@14.0.0: {} - globals@15.1.0: {} + globals@15.3.0: {} globalthis@1.0.4: dependencies: @@ -4951,6 +5330,8 @@ snapshots: has-flag@4.0.0: {} + has-own-prop@2.0.0: {} + has-property-descriptors@1.0.2: dependencies: es-define-property: 1.0.0 @@ -4976,7 +5357,7 @@ snapshots: http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.1 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5 transitivePeerDependencies: - supports-color @@ -4988,7 +5369,7 @@ snapshots: https-proxy-agent@7.0.4: dependencies: agent-base: 7.1.1 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5 transitivePeerDependencies: - supports-color @@ -4996,8 +5377,6 @@ snapshots: human-signals@5.0.0: {} - hunspell-spellchecker@1.0.2: {} - husky@9.0.11: {} iconv-lite@0.4.24: @@ -5034,11 +5413,11 @@ snapshots: ini@4.1.1: {} - ini@4.1.2: {} + ini@4.1.3: {} - inquirer@9.2.19: + inquirer@9.2.22: dependencies: - '@inquirer/figures': 1.0.1 + '@inquirer/figures': 1.0.3 '@ljharb/through': 2.3.13 ansi-escapes: 4.3.2 chalk: 5.3.0 @@ -5092,10 +5471,6 @@ snapshots: call-bind: 1.0.7 has-tostringtag: 1.0.2 - is-builtin-module@3.2.1: - dependencies: - builtin-modules: 3.3.0 - is-callable@1.2.7: {} is-ci@3.0.1: @@ -5266,12 +5641,12 @@ snapshots: jest-message-util@29.7.0: dependencies: - '@babel/code-frame': 7.24.2 + '@babel/code-frame': 7.24.6 '@jest/types': 29.6.3 '@types/stack-utils': 2.0.3 chalk: 4.1.2 graceful-fs: 4.2.11 - micromatch: 4.0.5 + micromatch: 4.0.7 pretty-format: 29.7.0 slash: 3.0.0 stack-utils: 2.0.6 @@ -5279,7 +5654,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.12.8 + '@types/node': 20.14.0 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -5287,8 +5662,6 @@ snapshots: jiti@1.21.0: {} - jju@1.4.0: {} - js-tokens@4.0.0: {} js-yaml@4.1.0: @@ -5311,10 +5684,6 @@ snapshots: json-stringify-safe@5.0.1: {} - json5@1.0.2: - dependencies: - minimist: 1.2.8 - jsonc-parser@3.2.1: {} jsonfile@6.1.0: @@ -5340,26 +5709,26 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - lilconfig@3.0.0: {} + lilconfig@3.1.1: {} lines-and-columns@1.2.4: {} - lint-staged@15.2.2: + lint-staged@15.2.5: dependencies: chalk: 5.3.0 - commander: 11.1.0 - debug: 4.3.4(supports-color@8.1.1) + commander: 12.1.0 + debug: 4.3.5 execa: 8.0.1 - lilconfig: 3.0.0 - listr2: 8.0.1 - micromatch: 4.0.5 + lilconfig: 3.1.1 + listr2: 8.2.1 + micromatch: 4.0.7 pidtree: 0.6.0 string-argv: 0.3.2 - yaml: 2.3.4 + yaml: 2.4.3 transitivePeerDependencies: - supports-color - listr2@8.0.1: + listr2@8.2.1: dependencies: cli-truncate: 4.0.0 colorette: 2.0.20 @@ -5438,10 +5807,6 @@ snapshots: lowercase-keys@3.0.0: {} - lru-cache@6.0.0: - dependencies: - yallist: 4.0.0 - lru-cache@7.18.3: {} lunr@2.3.9: {} @@ -5454,7 +5819,7 @@ snapshots: make-dir@4.0.0: dependencies: - semver: 7.6.0 + semver: 7.6.2 marked@4.3.0: {} @@ -5464,16 +5829,11 @@ snapshots: merge2@1.4.1: {} - micromatch@4.0.5: + micromatch@4.0.7: dependencies: - braces: 3.0.2 + braces: 3.0.3 picomatch: 2.3.1 - microtime@3.1.1: - dependencies: - node-addon-api: 5.1.0 - node-gyp-build: 4.8.0 - mime-db@1.52.0: {} mime-types@2.1.35: @@ -5496,6 +5856,10 @@ snapshots: dependencies: brace-expansion: 2.0.1 + minimatch@9.0.3: + dependencies: + brace-expansion: 2.0.1 + minimatch@9.0.4: dependencies: brace-expansion: 2.0.1 @@ -5537,7 +5901,7 @@ snapshots: prop-types: 15.8.1 tcomb: 3.2.29 tcomb-validation: 3.4.1 - validator: 13.11.0 + validator: 13.12.0 yargs: 17.7.2 mochawesome@7.1.3(mocha@10.4.0): @@ -5562,13 +5926,28 @@ snapshots: natural-compare@1.4.0: {} + neostandard@0.5.1(@typescript-eslint/parser@8.0.0-alpha.25(eslint@9.4.0)(typescript@5.4.5))(eslint@9.4.0)(typescript@5.4.5): + dependencies: + '@stylistic/eslint-plugin': 1.8.1(eslint@9.4.0)(typescript@5.4.5) + '@typescript-eslint/eslint-plugin': 8.0.0-alpha.25(@typescript-eslint/parser@8.0.0-alpha.25(eslint@9.4.0)(typescript@5.4.5))(eslint@9.4.0)(typescript@5.4.5) + '@typescript-eslint/utils': 8.0.0-alpha.25(eslint@9.4.0)(typescript@5.4.5) + eslint: 9.4.0 + eslint-plugin-n: 17.7.0(eslint@9.4.0) + globals: 15.3.0 + peowly: 1.3.0 + typescript-eslint: 8.0.0-alpha.25(eslint@9.4.0)(typescript@5.4.5) + transitivePeerDependencies: + - '@typescript-eslint/parser' + - supports-color + - typescript + netmask@2.0.2: {} new-github-release-url@2.0.0: dependencies: type-fest: 2.19.0 - nise@5.1.9: + nise@6.0.0: dependencies: '@sinonjs/commons': 3.0.1 '@sinonjs/fake-timers': 11.2.2 @@ -5576,8 +5955,6 @@ snapshots: just-extend: 6.2.0 path-to-regexp: 6.2.2 - node-addon-api@5.1.0: {} - node-domexception@1.0.0: {} node-fetch@3.3.2: @@ -5586,8 +5963,6 @@ snapshots: fetch-blob: 3.2.0 formdata-polyfill: 4.0.10 - node-gyp-build@4.8.0: {} - normalize-path@3.0.0: {} normalize-url@8.0.1: {} @@ -5613,25 +5988,6 @@ snapshots: has-symbols: 1.0.3 object-keys: 1.1.1 - object.fromentries@2.0.8: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-object-atoms: 1.0.0 - - object.groupby@1.0.3: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - - object.values@1.2.0: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-object-atoms: 1.0.0 - once@1.4.0: dependencies: wrappy: 1.0.2 @@ -5719,7 +6075,7 @@ snapshots: dependencies: '@tootallnate/quickjs-emscripten': 0.23.0 agent-base: 7.1.1 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5 get-uri: 6.0.3 http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.4 @@ -5738,15 +6094,19 @@ snapshots: got: 12.6.1 registry-auth-token: 5.0.2 registry-url: 6.0.1 - semver: 7.6.0 + semver: 7.6.2 parent-module@1.0.1: dependencies: callsites: 3.1.0 + parent-module@2.0.0: + dependencies: + callsites: 3.1.0 + parse-json@5.2.0: dependencies: - '@babel/code-frame': 7.24.2 + '@babel/code-frame': 7.24.6 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -5777,19 +6137,21 @@ snapshots: path-type@5.0.0: {} - picocolors@1.0.0: {} + peowly@1.3.0: {} + + picocolors@1.0.1: {} picomatch@2.3.1: {} - pidtree@0.6.0: {} + picomatch@4.0.2: {} - platform@1.3.6: {} + pidtree@0.6.0: {} possible-typed-array-names@1.0.0: {} prelude-ls@1.2.1: {} - prettier@3.2.5: {} + prettier@3.3.0: {} pretty-format@29.7.0: dependencies: @@ -5819,7 +6181,7 @@ snapshots: proxy-agent@6.4.0: dependencies: agent-base: 7.1.1 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5 http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.4 lru-cache: 7.18.3 @@ -5885,10 +6247,10 @@ snapshots: dependencies: rc: 1.2.8 - release-it@17.2.1(typescript@5.4.5): + release-it@17.3.0(typescript@5.4.5): dependencies: '@iarna/toml': 2.2.5 - '@octokit/rest': 20.1.0 + '@octokit/rest': 20.1.1 async-retry: 1.3.3 chalk: 5.3.0 cosmiconfig: 9.0.0(typescript@5.4.5) @@ -5896,7 +6258,7 @@ snapshots: git-url-parse: 14.0.0 globby: 14.0.1 got: 13.0.0 - inquirer: 9.2.19 + inquirer: 9.2.22 is-ci: 3.0.1 issue-parser: 7.0.0 lodash: 4.17.21 @@ -5908,7 +6270,7 @@ snapshots: os-name: 5.1.0 promise.allsettled: 1.0.7 proxy-agent: 6.4.0 - semver: 7.6.0 + semver: 7.6.2 shelljs: 0.8.5 update-notifier: 7.0.0 url-join: 5.0.0 @@ -5918,6 +6280,8 @@ snapshots: - supports-color - typescript + repeat-string@1.6.1: {} + require-directory@2.1.1: {} require-from-string@2.0.2: {} @@ -5930,11 +6294,6 @@ snapshots: resolve-pkg-maps@1.0.0: {} - resolve@1.19.0: - dependencies: - is-core-module: 2.13.1 - path-parse: 1.0.7 - resolve@1.22.8: dependencies: is-core-module: 2.13.1 @@ -5973,34 +6332,34 @@ snapshots: dependencies: del: 5.1.0 - rollup-plugin-dts@6.1.0(rollup@4.17.2)(typescript@5.4.5): + rollup-plugin-dts@6.1.1(rollup@4.18.0)(typescript@5.4.5): dependencies: magic-string: 0.30.10 - rollup: 4.17.2 + rollup: 4.18.0 typescript: 5.4.5 optionalDependencies: - '@babel/code-frame': 7.24.2 + '@babel/code-frame': 7.24.6 - rollup@4.17.2: + rollup@4.18.0: dependencies: '@types/estree': 1.0.5 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.17.2 - '@rollup/rollup-android-arm64': 4.17.2 - '@rollup/rollup-darwin-arm64': 4.17.2 - '@rollup/rollup-darwin-x64': 4.17.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.17.2 - '@rollup/rollup-linux-arm-musleabihf': 4.17.2 - '@rollup/rollup-linux-arm64-gnu': 4.17.2 - '@rollup/rollup-linux-arm64-musl': 4.17.2 - '@rollup/rollup-linux-powerpc64le-gnu': 4.17.2 - '@rollup/rollup-linux-riscv64-gnu': 4.17.2 - '@rollup/rollup-linux-s390x-gnu': 4.17.2 - '@rollup/rollup-linux-x64-gnu': 4.17.2 - '@rollup/rollup-linux-x64-musl': 4.17.2 - '@rollup/rollup-win32-arm64-msvc': 4.17.2 - '@rollup/rollup-win32-ia32-msvc': 4.17.2 - '@rollup/rollup-win32-x64-msvc': 4.17.2 + '@rollup/rollup-android-arm-eabi': 4.18.0 + '@rollup/rollup-android-arm64': 4.18.0 + '@rollup/rollup-darwin-arm64': 4.18.0 + '@rollup/rollup-darwin-x64': 4.18.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.18.0 + '@rollup/rollup-linux-arm-musleabihf': 4.18.0 + '@rollup/rollup-linux-arm64-gnu': 4.18.0 + '@rollup/rollup-linux-arm64-musl': 4.18.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.18.0 + '@rollup/rollup-linux-riscv64-gnu': 4.18.0 + '@rollup/rollup-linux-s390x-gnu': 4.18.0 + '@rollup/rollup-linux-x64-gnu': 4.18.0 + '@rollup/rollup-linux-x64-musl': 4.18.0 + '@rollup/rollup-win32-arm64-msvc': 4.18.0 + '@rollup/rollup-win32-ia32-msvc': 4.18.0 + '@rollup/rollup-win32-x64-msvc': 4.18.0 fsevents: 2.3.3 run-applescript@7.0.0: {} @@ -6034,11 +6393,9 @@ snapshots: semver-diff@4.0.0: dependencies: - semver: 7.6.0 + semver: 7.6.2 - semver@7.6.0: - dependencies: - lru-cache: 6.0.0 + semver@7.6.2: {} serialize-javascript@6.0.0: dependencies: @@ -6094,13 +6451,13 @@ snapshots: signal-exit@4.1.0: {} - sinon@17.0.1: + sinon@18.0.0: dependencies: '@sinonjs/commons': 3.0.1 '@sinonjs/fake-timers': 11.2.2 '@sinonjs/samsam': 8.0.0 diff: 5.2.0 - nise: 5.1.9 + nise: 6.0.0 supports-color: 7.2.0 slash@3.0.0: {} @@ -6124,7 +6481,7 @@ snapshots: socks-proxy-agent@8.0.3: dependencies: agent-base: 7.1.1 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5 socks: 2.8.3 transitivePeerDependencies: - supports-color @@ -6146,9 +6503,9 @@ snapshots: spdx-expression-parse@4.0.0: dependencies: spdx-exceptions: 2.5.0 - spdx-license-ids: 3.0.17 + spdx-license-ids: 3.0.18 - spdx-license-ids@3.0.17: {} + spdx-license-ids@3.0.18: {} split2@4.2.0: {} @@ -6217,8 +6574,6 @@ snapshots: dependencies: ansi-regex: 6.0.1 - strip-bom@3.0.0: {} - strip-final-newline@2.0.0: {} strip-final-newline@3.0.0: {} @@ -6241,9 +6596,14 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} + synckit@0.9.0: + dependencies: + '@pkgr/core': 0.1.1 + tslib: 2.6.2 + tapable@2.2.1: {} - tatami-ng@0.4.4(typescript@5.4.5): + tatami-ng@0.4.13(typescript@5.4.5): dependencies: typescript: 5.4.5 @@ -6284,13 +6644,6 @@ snapshots: dependencies: typescript: 5.4.5 - tsconfig-paths@3.15.0: - dependencies: - '@types/json5': 0.0.29 - json5: 1.0.2 - minimist: 1.2.8 - strip-bom: 3.0.0 - tslib@2.6.2: {} type-check@0.4.0: @@ -6299,8 +6652,6 @@ snapshots: type-detect@4.0.8: {} - type-fest@0.20.2: {} - type-fest@0.21.3: {} type-fest@1.4.0: {} @@ -6351,6 +6702,17 @@ snapshots: shiki: 0.14.7 typescript: 5.4.5 + typescript-eslint@8.0.0-alpha.25(eslint@9.4.0)(typescript@5.4.5): + dependencies: + '@typescript-eslint/eslint-plugin': 8.0.0-alpha.25(@typescript-eslint/parser@8.0.0-alpha.25(eslint@9.4.0)(typescript@5.4.5))(eslint@9.4.0)(typescript@5.4.5) + '@typescript-eslint/parser': 8.0.0-alpha.25(eslint@9.4.0)(typescript@5.4.5) + '@typescript-eslint/utils': 8.0.0-alpha.25(eslint@9.4.0)(typescript@5.4.5) + optionalDependencies: + typescript: 5.4.5 + transitivePeerDependencies: + - eslint + - supports-color + typescript@5.4.5: {} unbox-primitive@1.0.2: @@ -6383,7 +6745,7 @@ snapshots: is-npm: 6.0.0 latest-version: 7.0.0 pupa: 3.1.0 - semver: 7.6.0 + semver: 7.6.2 semver-diff: 4.0.0 xdg-basedir: 5.1.0 @@ -6403,12 +6765,16 @@ snapshots: '@types/istanbul-lib-coverage': 2.0.6 convert-source-map: 2.0.0 - validator@13.11.0: {} + validator@13.12.0: {} + + vscode-languageserver-textdocument@1.0.11: {} vscode-oniguruma@1.7.0: {} vscode-textmate@8.0.0: {} + vscode-uri@3.0.8: {} + wcwidth@1.0.1: dependencies: defaults: 1.0.4 @@ -6486,9 +6852,7 @@ snapshots: y18n@5.0.8: {} - yallist@4.0.0: {} - - yaml@2.3.4: {} + yaml@2.4.3: {} yargs-parser@20.2.4: {} diff --git a/rollup.config.mjs b/rollup.config.mjs index 763a3e3c..a6d7eae8 100644 --- a/rollup.config.mjs +++ b/rollup.config.mjs @@ -43,15 +43,15 @@ export default defineConfig([ entryFileNames: '[name].cjs', chunkFileNames: '[name]-[hash].cjs', preserveModules: true, - preserveModulesRoot: './src' + preserveModulesRoot: './src', } : { file: './lib/index.cjs', - plugins: [terser({ maxWorkers })] + plugins: [terser({ maxWorkers })], }), ...(sourcemap && { - sourcemap - }) + sourcemap, + }), }, { format: 'esm', @@ -61,31 +61,31 @@ export default defineConfig([ entryFileNames: '[name].mjs', chunkFileNames: '[name]-[hash].mjs', preserveModules: true, - preserveModulesRoot: './src' + preserveModulesRoot: './src', } : { file: './lib/index.mjs', - plugins: [terser({ maxWorkers })] + plugins: [terser({ maxWorkers })], }), ...(sourcemap && { - sourcemap - }) - } + sourcemap, + }), + }, ], external: [/^node:*/], plugins: [ typescript({ tsconfig: './tsconfig.build.json', compilerOptions: { - sourceMap: sourcemap - } + sourceMap: sourcemap, + }, }), del({ - targets: ['./lib/*'] + targets: ['./lib/*'], }), isAnalyzeBuild && analyze(), - isDocumentationBuild && command('pnpm typedoc') - ] + isDocumentationBuild && command('pnpm typedoc'), + ], }, { input: './lib/dts/index.d.ts', @@ -96,9 +96,9 @@ export default defineConfig([ dts(), del({ targets: ['./lib/dts'], - hook: 'buildEnd' + hook: 'buildEnd', }), - isAnalyzeBuild && analyze() - ] - } + isAnalyzeBuild && analyze(), + ], + }, ]) diff --git a/sonar-project.properties b/sonar-project.properties index a6833229..631241ae 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -3,7 +3,7 @@ sonar.organization=poolifier sonar.javascript.exclusions=lib/**/*.mjs sonar.javascript.lcov.reportPaths=coverage/lcov.info sonar.projectName=poolifier -sonar.projectVersion=4.0.1 +sonar.projectVersion=4.0.13 sonar.host.url=https://sonarcloud.io #sonar.sources=src sonar.sources=lib diff --git a/src/circular-array.ts b/src/circular-array.ts deleted file mode 100644 index 23473279..00000000 --- a/src/circular-array.ts +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright Jerome Benoit. 2021-2024. All Rights Reserved. - -export const DEFAULT_CIRCULAR_ARRAY_SIZE = 385 - -/** - * Array with a maximum length and shifting items when full. - * - * @typeParam T - Type of items. - * @internal - */ -export class CircularArray extends Array { - public size: number - - constructor (size: number = DEFAULT_CIRCULAR_ARRAY_SIZE, ...items: T[]) { - super() - this.checkSize(size) - this.size = size - if (arguments.length > 1) { - this.push(...items) - } - } - - /** @inheritDoc */ - public push (...items: T[]): number { - const length = super.push(...items) - if (length > this.size) { - super.splice(0, length - this.size) - } - return this.length - } - - /** @inheritDoc */ - public unshift (...items: T[]): number { - const length = super.unshift(...items) - if (length > this.size) { - super.splice(this.size, items.length) - } - return this.length - } - - /** @inheritDoc */ - public concat (...items: Array>): CircularArray { - const concatenatedCircularArray = super.concat( - items as T[] - ) as CircularArray - concatenatedCircularArray.size = this.size - if (concatenatedCircularArray.length > concatenatedCircularArray.size) { - concatenatedCircularArray.splice( - 0, - concatenatedCircularArray.length - concatenatedCircularArray.size - ) - } - return concatenatedCircularArray - } - - /** @inheritDoc */ - public splice ( - start: number, - deleteCount?: number, - ...items: T[] - ): CircularArray { - let itemsRemoved: T[] = [] - if (arguments.length >= 3 && deleteCount != null) { - itemsRemoved = super.splice(start, deleteCount, ...items) - if (this.length > this.size) { - const itemsOverflowing = super.splice(0, this.length - this.size) - itemsRemoved = new CircularArray( - itemsRemoved.length + itemsOverflowing.length, - ...itemsRemoved, - ...itemsOverflowing - ) - } - } else if (arguments.length === 2) { - itemsRemoved = super.splice(start, deleteCount) - } else { - itemsRemoved = super.splice(start) - } - return itemsRemoved as CircularArray - } - - public resize (size: number): void { - this.checkSize(size) - if (size === 0) { - this.length = 0 - } else if (size < this.size) { - for (let i = size; i < this.size; i++) { - super.pop() - } - } - this.size = size - } - - public empty (): boolean { - return this.length === 0 - } - - public full (): boolean { - return this.length === this.size - } - - private checkSize (size: number): void { - if (!Number.isSafeInteger(size)) { - throw new TypeError( - `Invalid circular array size: ${size} is not a safe integer` - ) - } - if (size < 0) { - throw new RangeError(`Invalid circular array size: ${size} < 0`) - } - } -} diff --git a/src/circular-buffer.ts b/src/circular-buffer.ts new file mode 100644 index 00000000..5015483b --- /dev/null +++ b/src/circular-buffer.ts @@ -0,0 +1,97 @@ +/** + * Default buffer size. + */ +export const defaultBufferSize = 2048 + +/** + * Circular buffer designed for positive numbers. + * @internal + */ +export class CircularBuffer { + private readIdx: number + private writeIdx: number + private readonly items: Float32Array + private readonly maxArrayIdx: number + public size: number + + /** + * @param size - Buffer size. @defaultValue defaultBufferSize + * @returns CircularBuffer. + */ + constructor (size: number = defaultBufferSize) { + this.checkSize(size) + this.readIdx = 0 + this.writeIdx = 0 + this.maxArrayIdx = size - 1 + this.size = 0 + this.items = new Float32Array(size).fill(-1) + } + + /** + * Checks whether the buffer is empty. + * @returns Whether the buffer is empty. + */ + public empty (): boolean { + return this.size === 0 + } + + /** + * Checks whether the buffer is full. + * @returns Whether the buffer is full. + */ + public full (): boolean { + return this.size === this.items.length + } + + /** + * Puts number into buffer. + * @param number - Number to put into buffer. + */ + public put (number: number): void { + this.items[this.writeIdx] = number + this.writeIdx = this.writeIdx === this.maxArrayIdx ? 0 : this.writeIdx + 1 + if (this.size < this.items.length) { + ++this.size + } + } + + /** + * Gets number from buffer. + * @returns Number from buffer. + */ + public get (): number | undefined { + const number = this.items[this.readIdx] + if (number === -1) { + return + } + this.items[this.readIdx] = -1 + this.readIdx = this.readIdx === this.maxArrayIdx ? 0 : this.readIdx + 1 + --this.size + return number + } + + /** + * Returns buffer as numbers' array. + * @returns Numbers' array. + */ + public toArray (): number[] { + return Array.from(this.items.filter(item => item !== -1)) + } + + /** + * Checks the buffer size. + * @param size - Buffer size. + */ + private checkSize (size: number): void { + if (!Number.isSafeInteger(size)) { + throw new TypeError( + `Invalid circular buffer size: '${size.toString()}' is not an integer` + ) + } + if (size < 0) { + throw new RangeError( + `Invalid circular buffer size: ${size.toString()} < 0` + ) + } + } +} diff --git a/src/fixed-priority-queue.ts b/src/fixed-priority-queue.ts new file mode 100644 index 00000000..a3de0209 --- /dev/null +++ b/src/fixed-priority-queue.ts @@ -0,0 +1,187 @@ +/** + * Default buffer size. + */ +export const defaultQueueSize = 2048 + +/** + * Fixed priority queue node. + * @typeParam T - Type of priority queue node data. + * @internal + */ +export interface FixedPriorityQueueNode { + data: T + priority: number +} + +/** + * Fixed priority queue. + * @typeParam T - Type of fixed priority queue data. + * @internal + */ +export class FixedPriorityQueue { + private start!: number + private readonly nodeArray: FixedPriorityQueueNode[] + /** The fixed priority queue capacity. */ + public readonly capacity: number + /** The fixed priority queue size. */ + public size!: number + /** Whether to enable priority. */ + public enablePriority: boolean + + /** + * Constructs a fixed priority queue. + * @param size - Fixed priority queue size. @defaultValue defaultQueueSize + * @param enablePriority - Whether to enable priority. @defaultValue false + * @returns FixedPriorityQueue. + */ + constructor (size: number = defaultQueueSize, enablePriority = false) { + this.checkSize(size) + this.capacity = size + this.enablePriority = enablePriority + this.nodeArray = new Array>(this.capacity) + this.clear() + } + + /** + * Checks if the fixed priority queue is empty. + * @returns `true` if the fixed priority queue is empty, `false` otherwise. + */ + public empty (): boolean { + return this.size === 0 + } + + /** + * Checks if the fixed priority queue is full. + * @returns `true` if the fixed priority queue is full, `false` otherwise. + */ + public full (): boolean { + return this.size === this.capacity + } + + /** + * Enqueue data into the fixed priority queue. + * @param data - Data to enqueue. + * @param priority - Priority of the data. Lower values have higher priority. + * @returns The new size of the priority queue. + * @throws If the fixed priority queue is full. + */ + public enqueue (data: T, priority?: number): number { + if (this.full()) { + throw new Error('Priority queue is full') + } + priority = priority ?? 0 + let inserted = false + if (this.enablePriority) { + let index = this.start + for (let i = 0; i < this.size; i++) { + if (this.nodeArray[index].priority > priority) { + this.nodeArray.splice(index, 0, { data, priority }) + this.nodeArray.length !== this.capacity && + (this.nodeArray.length = this.capacity) + inserted = true + break + } + ++index + if (index === this.capacity) { + index = 0 + } + } + } + if (!inserted) { + let index = this.start + this.size + if (index >= this.capacity) { + index -= this.capacity + } + this.nodeArray[index] = { data, priority } + } + return ++this.size + } + + /** + * Gets data from the fixed priority queue. + * @param index - The index of the data to get. + * @returns The data at the index or `undefined` if the fixed priority queue is empty or the index is out of bounds. + */ + public get (index: number): T | undefined { + if (this.empty() || index >= this.size) { + return undefined + } + index += this.start + if (index >= this.capacity) { + index -= this.capacity + } + return this.nodeArray[index].data + } + + /** + * Dequeue data from the fixed priority queue. + * @returns The dequeued data or `undefined` if the priority queue is empty. + */ + public dequeue (): T | undefined { + if (this.empty()) { + return undefined + } + const index = this.start + --this.size + ++this.start + if (this.start === this.capacity) { + this.start = 0 + } + return this.nodeArray[index].data + } + + /** + * Clears the fixed priority queue. + */ + public clear (): void { + this.start = 0 + this.size = 0 + } + + /** + * Returns an iterator for the fixed priority queue. + * @returns An iterator for the fixed priority queue. + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols + */ + public [Symbol.iterator] (): Iterator { + let index = this.start + let i = 0 + return { + next: () => { + if (i >= this.size) { + return { + value: undefined, + done: true, + } + } + const value = this.nodeArray[index].data + ++index + ++i + if (index === this.capacity) { + index = 0 + } + return { + value, + done: false, + } + }, + } + } + + /** + * Checks the queue size. + * @param size - Queue size. + */ + private checkSize (size: number): void { + if (!Number.isSafeInteger(size)) { + throw new TypeError( + `Invalid fixed priority queue size: '${size.toString()}' is not an integer` + ) + } + if (size < 0) { + throw new RangeError( + `Invalid fixed priority queue size: ${size.toString()} < 0` + ) + } + } +} diff --git a/src/index.ts b/src/index.ts index cba06414..e779bf0c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,8 @@ -export type { CircularArray } from './circular-array.js' +export type { CircularBuffer } from './circular-buffer.js' +export type { + FixedPriorityQueue, + FixedPriorityQueueNode, +} from './fixed-priority-queue.js' export type { AbstractPool } from './pools/abstract-pool.js' export { DynamicClusterPool } from './pools/cluster/dynamic.js' export type { ClusterPoolOptions } from './pools/cluster/fixed.js' @@ -9,7 +13,7 @@ export type { PoolInfo, PoolOptions, PoolType, - TasksQueueOptions + TasksQueueOptions, } from './pools/pool.js' export { PoolEvents, PoolTypes } from './pools/pool.js' export type { @@ -20,11 +24,11 @@ export type { StrategyPolicy, TaskStatisticsRequirements, WorkerChoiceStrategy, - WorkerChoiceStrategyOptions + WorkerChoiceStrategyOptions, } from './pools/selection-strategies/selection-strategies-types.js' export { Measurements, - WorkerChoiceStrategies + WorkerChoiceStrategies, } from './pools/selection-strategies/selection-strategies-types.js' export type { WorkerChoiceStrategiesContext } from './pools/selection-strategies/worker-choice-strategies-context.js' export { DynamicThreadPool } from './pools/thread/dynamic.js' @@ -46,7 +50,7 @@ export type { WorkerNodeEventDetail, WorkerNodeOptions, WorkerType, - WorkerUsage + WorkerUsage, } from './pools/worker.js' export { WorkerTypes } from './pools/worker.js' export type { PriorityQueue, PriorityQueueNode } from './priority-queue.js' @@ -58,7 +62,7 @@ export type { TaskPerformance, WorkerError, WorkerStatistics, - Writable + Writable, } from './utility-types.js' export { availableParallelism } from './utils.js' export type { AbstractWorker } from './worker/abstract-worker.js' @@ -69,12 +73,12 @@ export type { TaskFunctionObject, TaskFunctionOperationResult, TaskFunctions, - TaskSyncFunction + TaskSyncFunction, } from './worker/task-functions.js' export { ThreadWorker } from './worker/thread-worker.js' export type { KillBehavior, KillHandler, - WorkerOptions + WorkerOptions, } from './worker/worker-options.js' export { KillBehaviors } from './worker/worker-options.js' diff --git a/src/pools/abstract-pool.ts b/src/pools/abstract-pool.ts index 677d33b6..3b676faa 100644 --- a/src/pools/abstract-pool.ts +++ b/src/pools/abstract-pool.ts @@ -4,11 +4,12 @@ import { EventEmitterAsyncResource } from 'node:events' import { performance } from 'node:perf_hooks' import type { TransferListItem } from 'node:worker_threads' +import { defaultBucketSize } from '../priority-queue.js' import type { MessageValue, PromiseResponseWrapper, Task, - TaskFunctionProperties + TaskFunctionProperties, } from '../utility-types.js' import { average, @@ -22,11 +23,11 @@ import { median, min, round, - sleep + sleep, } from '../utils.js' import type { TaskFunction, - TaskFunctionObject + TaskFunctionObject, } from '../worker/task-functions.js' import { KillBehaviors } from '../worker/worker-options.js' import { @@ -36,13 +37,13 @@ import { type PoolOptions, type PoolType, PoolTypes, - type TasksQueueOptions + type TasksQueueOptions, } from './pool.js' import { Measurements, WorkerChoiceStrategies, type WorkerChoiceStrategy, - type WorkerChoiceStrategyOptions + type WorkerChoiceStrategyOptions, } from './selection-strategies/selection-strategies-types.js' import { WorkerChoiceStrategiesContext } from './selection-strategies/worker-choice-strategies-context.js' import { @@ -55,7 +56,7 @@ import { updateRunTimeWorkerUsage, updateTaskStatisticsWorkerUsage, updateWaitTimeWorkerUsage, - waitWorkerNodeEvents + waitWorkerNodeEvents, } from './utils.js' import { version } from './version.js' import type { @@ -63,13 +64,12 @@ import type { IWorkerNode, WorkerInfo, WorkerNodeEventDetail, - WorkerType + WorkerType, } from './worker.js' import { WorkerNode } from './worker-node.js' /** * 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 structured-cloneable data. * @typeParam Response - Type of execution response. This can only be structured-cloneable data. @@ -80,7 +80,7 @@ export abstract class AbstractPool< Response = unknown > implements IPool { /** @inheritDoc */ - public readonly workerNodes: Array> = [] + public readonly workerNodes: IWorkerNode[] = [] /** @inheritDoc */ public emitter?: EventEmitterAsyncResource @@ -92,16 +92,21 @@ export abstract class AbstractPool< * * When we receive a message from the worker, we get a map entry with the promise resolve/reject bound to the message id. */ - protected promiseResponseMap: Map> = - new Map>() + protected promiseResponseMap: Map< + `${string}-${string}-${string}-${string}-${string}`, + PromiseResponseWrapper + > = new Map< + `${string}-${string}-${string}-${string}-${string}`, + PromiseResponseWrapper + >() /** * Worker choice strategies context referencing worker choice algorithms implementation. */ protected workerChoiceStrategiesContext?: WorkerChoiceStrategiesContext< - Worker, - Data, - Response + Worker, + Data, + Response > /** @@ -110,8 +115,8 @@ export abstract class AbstractPool< * - `value`: The task function object. */ private readonly taskFunctions: Map< - string, - TaskFunctionObject + string, + TaskFunctionObject > /** @@ -141,7 +146,6 @@ export abstract class AbstractPool< /** * Constructs a new poolifier pool. - * * @param minimumNumberOfWorkers - Minimum number of workers that this pool manages. * @param filePath - Path to the worker file. * @param opts - Options for the pool. @@ -171,9 +175,9 @@ export abstract class AbstractPool< this.initEventEmitter() } this.workerChoiceStrategiesContext = new WorkerChoiceStrategiesContext< - Worker, - Data, - Response + Worker, + Data, + Response >( this, // eslint-disable-next-line @typescript-eslint/no-non-null-assertion @@ -283,7 +287,7 @@ export abstract class AbstractPool< private initEventEmitter (): void { this.emitter = new EventEmitterAsyncResource({ - name: `poolifier:${this.type}-${this.worker}-pool` + name: `poolifier:${this.type}-${this.worker}-pool`, }) } @@ -304,7 +308,7 @@ export abstract class AbstractPool< .runTime.aggregate === true && this.workerChoiceStrategiesContext.getTaskStatisticsRequirements() .waitTime.aggregate && { - utilization: round(this.utilization) + utilization: round(this.utilization), }), workerNodes: this.workerNodes.length, idleWorkerNodes: this.workerNodes.reduce( @@ -319,10 +323,10 @@ export abstract class AbstractPool< (accumulator, workerNode) => workerNode.info.stealing ? accumulator + 1 : accumulator, 0 - ) + ), }), busyWorkerNodes: this.workerNodes.reduce( - (accumulator, _workerNode, workerNodeKey) => + (accumulator, _, workerNodeKey) => this.isWorkerNodeBusy(workerNodeKey) ? accumulator + 1 : accumulator, 0 ), @@ -341,24 +345,24 @@ export abstract class AbstractPool< (accumulator, workerNode) => accumulator + workerNode.usage.tasks.queued, 0 - ) + ), }), ...(this.opts.enableTasksQueue === true && { maxQueuedTasks: this.workerNodes.reduce( (accumulator, workerNode) => accumulator + (workerNode.usage.tasks.maxQueued ?? 0), 0 - ) + ), }), ...(this.opts.enableTasksQueue === true && { - backPressure: this.hasBackPressure() + backPressure: this.hasBackPressure(), }), ...(this.opts.enableTasksQueue === true && { stolenTasks: this.workerNodes.reduce( (accumulator, workerNode) => accumulator + workerNode.usage.tasks.stolen, 0 - ) + ), }), failedTasks: this.workerNodes.reduce( (accumulator, workerNode) => @@ -371,14 +375,16 @@ export abstract class AbstractPool< minimum: round( min( ...this.workerNodes.map( - workerNode => workerNode.usage.runTime.minimum ?? Infinity + workerNode => + workerNode.usage.runTime.minimum ?? Number.POSITIVE_INFINITY ) ) ), maximum: round( max( ...this.workerNodes.map( - workerNode => workerNode.usage.runTime.maximum ?? -Infinity + workerNode => + workerNode.usage.runTime.maximum ?? Number.NEGATIVE_INFINITY ) ) ), @@ -388,11 +394,13 @@ export abstract class AbstractPool< average( this.workerNodes.reduce( (accumulator, workerNode) => - accumulator.concat(workerNode.usage.runTime.history), + accumulator.concat( + workerNode.usage.runTime.history.toArray() + ), [] ) ) - ) + ), }), ...(this.workerChoiceStrategiesContext.getTaskStatisticsRequirements() .runTime.median && { @@ -400,13 +408,15 @@ export abstract class AbstractPool< median( this.workerNodes.reduce( (accumulator, workerNode) => - accumulator.concat(workerNode.usage.runTime.history), + accumulator.concat( + workerNode.usage.runTime.history.toArray() + ), [] ) ) - ) - }) - } + ), + }), + }, }), ...(this.workerChoiceStrategiesContext?.getTaskStatisticsRequirements() .waitTime.aggregate === true && { @@ -414,14 +424,16 @@ export abstract class AbstractPool< minimum: round( min( ...this.workerNodes.map( - workerNode => workerNode.usage.waitTime.minimum ?? Infinity + workerNode => + workerNode.usage.waitTime.minimum ?? Number.POSITIVE_INFINITY ) ) ), maximum: round( max( ...this.workerNodes.map( - workerNode => workerNode.usage.waitTime.maximum ?? -Infinity + workerNode => + workerNode.usage.waitTime.maximum ?? Number.NEGATIVE_INFINITY ) ) ), @@ -431,11 +443,13 @@ export abstract class AbstractPool< average( this.workerNodes.reduce( (accumulator, workerNode) => - accumulator.concat(workerNode.usage.waitTime.history), + accumulator.concat( + workerNode.usage.waitTime.history.toArray() + ), [] ) ) - ) + ), }), ...(this.workerChoiceStrategiesContext.getTaskStatisticsRequirements() .waitTime.median && { @@ -443,14 +457,133 @@ export abstract class AbstractPool< median( this.workerNodes.reduce( (accumulator, workerNode) => - accumulator.concat(workerNode.usage.waitTime.history), + accumulator.concat( + workerNode.usage.waitTime.history.toArray() + ), [] ) ) - ) - }) - } - }) + ), + }), + }, + }), + ...(this.workerChoiceStrategiesContext?.getTaskStatisticsRequirements() + .elu.aggregate === true && { + elu: { + idle: { + minimum: round( + min( + ...this.workerNodes.map( + workerNode => + workerNode.usage.elu.idle.minimum ?? + Number.POSITIVE_INFINITY + ) + ) + ), + maximum: round( + max( + ...this.workerNodes.map( + workerNode => + workerNode.usage.elu.idle.maximum ?? + Number.NEGATIVE_INFINITY + ) + ) + ), + ...(this.workerChoiceStrategiesContext.getTaskStatisticsRequirements() + .elu.average && { + average: round( + average( + this.workerNodes.reduce( + (accumulator, workerNode) => + accumulator.concat( + workerNode.usage.elu.idle.history.toArray() + ), + [] + ) + ) + ), + }), + ...(this.workerChoiceStrategiesContext.getTaskStatisticsRequirements() + .elu.median && { + median: round( + median( + this.workerNodes.reduce( + (accumulator, workerNode) => + accumulator.concat( + workerNode.usage.elu.idle.history.toArray() + ), + [] + ) + ) + ), + }), + }, + active: { + minimum: round( + min( + ...this.workerNodes.map( + workerNode => + workerNode.usage.elu.active.minimum ?? + Number.POSITIVE_INFINITY + ) + ) + ), + maximum: round( + max( + ...this.workerNodes.map( + workerNode => + workerNode.usage.elu.active.maximum ?? + Number.NEGATIVE_INFINITY + ) + ) + ), + ...(this.workerChoiceStrategiesContext.getTaskStatisticsRequirements() + .elu.average && { + average: round( + average( + this.workerNodes.reduce( + (accumulator, workerNode) => + accumulator.concat( + workerNode.usage.elu.active.history.toArray() + ), + [] + ) + ) + ), + }), + ...(this.workerChoiceStrategiesContext.getTaskStatisticsRequirements() + .elu.median && { + median: round( + median( + this.workerNodes.reduce( + (accumulator, workerNode) => + accumulator.concat( + workerNode.usage.elu.active.history.toArray() + ), + [] + ) + ) + ), + }), + }, + utilization: { + average: round( + average( + this.workerNodes.map( + workerNode => workerNode.usage.elu.utilization ?? 0 + ) + ) + ), + median: round( + median( + this.workerNodes.map( + workerNode => workerNode.usage.elu.utilization ?? 0 + ) + ) + ), + }, + }, + }), } } @@ -481,7 +614,6 @@ export abstract class AbstractPool< /** * The approximate pool utilization. - * * @returns The pool utilization. */ private get utilization (): number { @@ -518,7 +650,6 @@ export abstract class AbstractPool< /** * Checks if the worker id sent in the received message from a worker is valid. - * * @param message - The received message. * @throws {@link https://nodejs.org/api/errors.html#class-error} If the worker id is invalid. */ @@ -527,14 +658,13 @@ export abstract class AbstractPool< throw new Error('Worker message received without worker id') } else if (this.getWorkerNodeKeyByWorkerId(message.workerId) === -1) { throw new Error( - `Worker message received from unknown worker '${message.workerId}'` + `Worker message received from unknown worker '${message.workerId.toString()}'` ) } } /** * Gets the worker node key given its worker id. - * * @param workerId - The worker id. * @returns The worker node key if the worker id is found in the pool worker nodes, `-1` otherwise. */ @@ -566,7 +696,7 @@ export abstract class AbstractPool< } if (requireSync) { this.workerChoiceStrategiesContext?.syncWorkerChoiceStrategies( - this.getWorkerWorkerChoiceStrategies(), + this.getWorkerChoiceStrategies(), this.opts.workerChoiceStrategyOptions ) for (const workerNodeKey of this.workerNodes.keys()) { @@ -586,7 +716,7 @@ export abstract class AbstractPool< this.opts.workerChoiceStrategyOptions ) this.workerChoiceStrategiesContext?.syncWorkerChoiceStrategies( - this.getWorkerWorkerChoiceStrategies(), + this.getWorkerChoiceStrategies(), this.opts.workerChoiceStrategyOptions ) for (const workerNodeKey of this.workerNodes.keys()) { @@ -645,7 +775,7 @@ export abstract class AbstractPool< ...getDefaultTasksQueueOptions( this.maximumNumberOfWorkers ?? this.minimumNumberOfWorkers ), - ...tasksQueueOptions + ...tasksQueueOptions, } } @@ -709,7 +839,6 @@ export abstract class AbstractPool< /** * Whether worker nodes are executing concurrently their tasks quota or not. - * * @returns Worker nodes busyness boolean status. */ protected internalBusy (): boolean { @@ -762,7 +891,11 @@ export abstract class AbstractPool< } else { reject( new Error( - `Task function operation '${message.taskFunctionOperation}' failed on worker ${message.workerId} with error: '${message.workerError?.message}'` + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + `Task function operation '${message.taskFunctionOperation?.toString()}' failed on worker ${message.workerId?.toString()} with error: '${ + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + message.workerError?.message + }'` ) ) } @@ -810,7 +943,9 @@ export abstract class AbstractPool< new Error( `Task function operation '${ message.taskFunctionOperation as string - }' failed on worker ${errorResponse?.workerId} with error: '${ + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + }' failed on worker ${errorResponse?.workerId?.toString()} with error: '${ + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions errorResponse?.workerError?.message }'` ) @@ -862,12 +997,15 @@ export abstract class AbstractPool< const opResult = await this.sendTaskFunctionOperationToWorkers({ taskFunctionOperation: 'add', taskFunctionProperties: buildTaskFunctionProperties(name, fn), - taskFunction: fn.taskFunction.toString() + taskFunction: fn.taskFunction.toString(), }) this.taskFunctions.set(name, fn) this.workerChoiceStrategiesContext?.syncWorkerChoiceStrategies( - this.getWorkerWorkerChoiceStrategies() + this.getWorkerChoiceStrategies() ) + for (const workerNodeKey of this.workerNodes.keys()) { + this.sendStatisticsMessageToWorker(workerNodeKey) + } return opResult } @@ -883,13 +1021,18 @@ export abstract class AbstractPool< taskFunctionProperties: buildTaskFunctionProperties( name, this.taskFunctions.get(name) - ) + ), }) - this.deleteTaskFunctionWorkerUsages(name) + for (const workerNode of this.workerNodes) { + workerNode.deleteTaskFunctionWorkerUsage(name) + } this.taskFunctions.delete(name) this.workerChoiceStrategiesContext?.syncWorkerChoiceStrategies( - this.getWorkerWorkerChoiceStrategies() + this.getWorkerChoiceStrategies() ) + for (const workerNodeKey of this.workerNodes.keys()) { + this.sendStatisticsMessageToWorker(workerNodeKey) + } return opResult } @@ -907,47 +1050,77 @@ export abstract class AbstractPool< } /** - * Gets task function strategy, if any. - * + * Gets task function worker choice strategy, if any. * @param name - The task function name. * @returns The task function worker choice strategy if the task function worker choice strategy is defined, `undefined` otherwise. */ - private readonly getTaskFunctionWorkerWorkerChoiceStrategy = ( + private readonly getTaskFunctionWorkerChoiceStrategy = ( + name?: string + ): WorkerChoiceStrategy | undefined => { + name = name ?? DEFAULT_TASK_NAME + const taskFunctionsProperties = this.listTaskFunctionsProperties() + if (name === DEFAULT_TASK_NAME) { + name = taskFunctionsProperties[1]?.name + } + return taskFunctionsProperties.find( + (taskFunctionProperties: TaskFunctionProperties) => + taskFunctionProperties.name === name + )?.strategy + } + + /** + * Gets worker node task function worker choice strategy, if any. + * @param workerNodeKey - The worker node key. + * @param name - The task function name. + * @returns The worker node task function worker choice strategy if the worker node task function worker choice strategy is defined, `undefined` otherwise. + */ + private readonly getWorkerNodeTaskFunctionWorkerChoiceStrategy = ( + workerNodeKey: number, name?: string ): WorkerChoiceStrategy | undefined => { - if (name != null) { - return this.listTaskFunctionsProperties().find( - (taskFunctionProperties: TaskFunctionProperties) => - taskFunctionProperties.name === name - )?.strategy + const workerInfo = this.getWorkerInfo(workerNodeKey) + if (workerInfo == null) { + return + } + name = name ?? DEFAULT_TASK_NAME + if (name === DEFAULT_TASK_NAME) { + name = workerInfo.taskFunctionsProperties?.[1]?.name } + return workerInfo.taskFunctionsProperties?.find( + (taskFunctionProperties: TaskFunctionProperties) => + taskFunctionProperties.name === name + )?.strategy } /** * Gets worker node task function priority, if any. - * * @param workerNodeKey - The worker node key. * @param name - The task function name. - * @returns The task function worker choice priority if the task function worker choice priority is defined, `undefined` otherwise. + * @returns The worker node task function priority if the worker node task function priority is defined, `undefined` otherwise. */ private readonly getWorkerNodeTaskFunctionPriority = ( workerNodeKey: number, name?: string ): number | undefined => { - if (name != null) { - return this.getWorkerInfo(workerNodeKey)?.taskFunctionsProperties?.find( - (taskFunctionProperties: TaskFunctionProperties) => - taskFunctionProperties.name === name - )?.priority + const workerInfo = this.getWorkerInfo(workerNodeKey) + if (workerInfo == null) { + return + } + name = name ?? DEFAULT_TASK_NAME + if (name === DEFAULT_TASK_NAME) { + name = workerInfo.taskFunctionsProperties?.[1]?.name } + return workerInfo.taskFunctionsProperties?.find( + (taskFunctionProperties: TaskFunctionProperties) => + taskFunctionProperties.name === name + )?.priority } /** * Gets the worker choice strategies registered in this pool. - * * @returns The worker choice strategies. */ - private readonly getWorkerWorkerChoiceStrategies = + private readonly getWorkerChoiceStrategies = (): Set => { return new Set([ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion @@ -959,7 +1132,7 @@ export abstract class AbstractPool< ) .filter( (strategy: WorkerChoiceStrategy | undefined) => strategy != null - ) as WorkerChoiceStrategy[]) + ) as WorkerChoiceStrategy[]), ]) } @@ -970,16 +1143,10 @@ export abstract class AbstractPool< taskFunctionProperties: buildTaskFunctionProperties( name, this.taskFunctions.get(name) - ) + ), }) } - private deleteTaskFunctionWorkerUsages (name: string): void { - for (const workerNode of this.workerNodes) { - workerNode.deleteTaskFunctionWorkerUsage(name) - } - } - private shallExecuteTask (workerNodeKey: number): boolean { return ( this.tasksQueueSize(workerNodeKey) === 0 && @@ -1021,18 +1188,18 @@ export abstract class AbstractPool< return } const timestamp = performance.now() - const taskFunctionStrategy = - this.getTaskFunctionWorkerWorkerChoiceStrategy(name) - const workerNodeKey = this.chooseWorkerNode(taskFunctionStrategy) + const workerNodeKey = this.chooseWorkerNode(name) const task: Task = { name: name ?? DEFAULT_TASK_NAME, - // eslint-disable-next-line @typescript-eslint/consistent-type-assertions data: data ?? ({} as Data), priority: this.getWorkerNodeTaskFunctionPriority(workerNodeKey, name), - strategy: taskFunctionStrategy, + strategy: this.getWorkerNodeTaskFunctionWorkerChoiceStrategy( + workerNodeKey, + name + ), transferList, timestamp, - taskId: randomUUID() + taskId: randomUUID(), } // eslint-disable-next-line @typescript-eslint/no-non-null-assertion this.promiseResponseMap.set(task.taskId!, { @@ -1042,9 +1209,9 @@ export abstract class AbstractPool< ...(this.emitter != null && { asyncResource: new AsyncResource('poolifier:task', { triggerAsyncId: this.emitter.asyncId, - requireManualDestroy: true - }) - }) + requireManualDestroy: true, + }), + }), }) if ( this.opts.enableTasksQueue === false || @@ -1060,6 +1227,7 @@ export abstract class AbstractPool< /** * Starts the minimum number of workers. + * @param initWorkerNodeUsage - Whether to initialize the worker node usage or not. @defaultValue false */ private startMinimumNumberOfWorkers (initWorkerNodeUsage = false): void { this.startingMinimumNumberOfWorkers = true @@ -1108,7 +1276,7 @@ export abstract class AbstractPool< } this.destroying = true await Promise.all( - this.workerNodes.map(async (_workerNode, workerNodeKey) => { + this.workerNodes.map(async (_, workerNodeKey) => { await this.destroyWorkerNode(workerNodeKey) }) ) @@ -1134,7 +1302,8 @@ export abstract class AbstractPool< } else if (message.kill === 'failure') { reject( new Error( - `Kill message handling failed on worker ${message.workerId}` + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + `Kill message handling failed on worker ${message.workerId?.toString()}` ) ) } @@ -1147,7 +1316,6 @@ export abstract class AbstractPool< /** * Terminates the worker node given its worker node key. - * * @param workerNodeKey - The worker node key. */ protected async destroyWorkerNode (workerNodeKey: number): Promise { @@ -1170,8 +1338,6 @@ export abstract class AbstractPool< /** * Setup hook to execute code before worker nodes are created in the abstract constructor. * Can be overridden. - * - * @virtual */ protected setupHook (): void { /* Intentionally empty */ @@ -1179,7 +1345,6 @@ export abstract class AbstractPool< /** * Returns whether the worker is the main worker or not. - * * @returns `true` if the worker is the main worker, `false` otherwise. */ protected abstract isMain (): boolean @@ -1187,7 +1352,6 @@ export abstract class AbstractPool< /** * Hook executed before the worker task execution. * Can be overridden. - * * @param workerNodeKey - The worker node key. * @param task - The task to execute. */ @@ -1228,7 +1392,6 @@ export abstract class AbstractPool< /** * Hook executed after the worker task execution. * Can be overridden. - * * @param workerNodeKey - The worker node key. * @param message - The received message. */ @@ -1236,7 +1399,7 @@ export abstract class AbstractPool< workerNodeKey: number, message: MessageValue ): void { - let needWorkerChoiceStrategyUpdate = false + let needWorkerChoiceStrategiesUpdate = false // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (this.workerNodes[workerNodeKey]?.usage != null) { const workerUsage = this.workerNodes[workerNodeKey].usage @@ -1251,7 +1414,7 @@ export abstract class AbstractPool< workerUsage, message ) - needWorkerChoiceStrategyUpdate = true + needWorkerChoiceStrategiesUpdate = true } if ( this.shallUpdateTaskFunctionWorkerUsage(workerNodeKey) && @@ -1276,16 +1439,15 @@ export abstract class AbstractPool< taskFunctionWorkerUsage, message ) - needWorkerChoiceStrategyUpdate = true + needWorkerChoiceStrategiesUpdate = true } - if (needWorkerChoiceStrategyUpdate) { + if (needWorkerChoiceStrategiesUpdate) { this.workerChoiceStrategiesContext?.update(workerNodeKey) } } /** * Whether the worker node shall update its task function worker usage or not. - * * @param workerNodeKey - The worker node key. * @returns `true` if the worker node shall update its task function worker usage, `false` otherwise. */ @@ -1299,14 +1461,11 @@ export abstract class AbstractPool< } /** - * Chooses a worker node for the next task given the worker choice strategy. - * - * @param workerChoiceStrategy - The worker choice strategy. - * @returns The chosen worker node key + * Chooses a worker node for the next task. + * @param name - The task function name. + * @returns The chosen worker node key. */ - private chooseWorkerNode ( - workerChoiceStrategy?: WorkerChoiceStrategy - ): number { + private chooseWorkerNode (name?: string): number { if (this.shallCreateDynamicWorker()) { const workerNodeKey = this.createAndSetupDynamicWorkerNode() if ( @@ -1317,19 +1476,19 @@ export abstract class AbstractPool< } } // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return this.workerChoiceStrategiesContext!.execute(workerChoiceStrategy) + return this.workerChoiceStrategiesContext!.execute( + this.getTaskFunctionWorkerChoiceStrategy(name) + ) } /** * Conditions for dynamic worker creation. - * * @returns Whether to create a dynamic worker or not. */ protected abstract shallCreateDynamicWorker (): boolean /** * Sends a message to worker given its worker node key. - * * @param workerNodeKey - The worker node key. * @param message - The message. * @param transferList - The optional array of transferable objects. @@ -1342,7 +1501,6 @@ export abstract class AbstractPool< /** * Initializes the worker node usage with sensible default values gathered during runtime. - * * @param workerNode - The worker node. */ private initWorkerNodeUsage (workerNode: IWorkerNode): void { @@ -1352,7 +1510,8 @@ export abstract class AbstractPool< ) { workerNode.usage.runTime.aggregate = min( ...this.workerNodes.map( - workerNode => workerNode.usage.runTime.aggregate ?? Infinity + workerNode => + workerNode.usage.runTime.aggregate ?? Number.POSITIVE_INFINITY ) ) } @@ -1362,7 +1521,8 @@ export abstract class AbstractPool< ) { workerNode.usage.waitTime.aggregate = min( ...this.workerNodes.map( - workerNode => workerNode.usage.waitTime.aggregate ?? Infinity + workerNode => + workerNode.usage.waitTime.aggregate ?? Number.POSITIVE_INFINITY ) ) } @@ -1372,7 +1532,8 @@ export abstract class AbstractPool< ) { workerNode.usage.elu.active.aggregate = min( ...this.workerNodes.map( - workerNode => workerNode.usage.elu.active.aggregate ?? Infinity + workerNode => + workerNode.usage.elu.active.aggregate ?? Number.POSITIVE_INFINITY ) ) } @@ -1380,7 +1541,6 @@ export abstract class AbstractPool< /** * Creates a new, completely set up worker node. - * * @returns New, completely set up worker node key. */ protected createAndSetupWorkerNode (): number { @@ -1444,7 +1604,6 @@ export abstract class AbstractPool< /** * Creates a new, completely set up dynamic worker node. - * * @returns New, completely set up dynamic worker node key. */ protected createAndSetupDynamicWorkerNode (): number { @@ -1454,6 +1613,7 @@ export abstract class AbstractPool< const localWorkerNodeKey = this.getWorkerNodeKeyByWorkerId( message.workerId ) + const workerInfo = this.getWorkerInfo(localWorkerNodeKey) const workerUsage = this.workerNodes[localWorkerNodeKey]?.usage // Kill message received from worker if ( @@ -1462,6 +1622,8 @@ export abstract class AbstractPool< ((this.opts.enableTasksQueue === false && workerUsage.tasks.executing === 0) || (this.opts.enableTasksQueue === true && + workerInfo != null && + !workerInfo.stealing && workerUsage.tasks.executing === 0 && this.tasksQueueSize(localWorkerNodeKey) === 0))) ) { @@ -1473,7 +1635,7 @@ export abstract class AbstractPool< } }) this.sendToWorker(workerNodeKey, { - checkActive: true + checkActive: true, }) if (this.taskFunctions.size > 0) { for (const [taskFunctionName, taskFunctionObject] of this.taskFunctions) { @@ -1483,7 +1645,7 @@ export abstract class AbstractPool< taskFunctionName, taskFunctionObject ), - taskFunction: taskFunctionObject.taskFunction.toString() + taskFunction: taskFunctionObject.taskFunction.toString(), }).catch((error: unknown) => { this.emitter?.emit(PoolEvents.error, error) }) @@ -1506,7 +1668,6 @@ export abstract class AbstractPool< /** * Registers a listener callback on the worker given its worker node key. - * * @param workerNodeKey - The worker node key. * @param listener - The message listener callback. */ @@ -1519,7 +1680,6 @@ export abstract class AbstractPool< /** * Registers once a listener callback on the worker given its worker node key. - * * @param workerNodeKey - The worker node key. * @param listener - The message listener callback. */ @@ -1532,7 +1692,6 @@ export abstract class AbstractPool< /** * Deregisters a listener callback on the worker given its worker node key. - * * @param workerNodeKey - The worker node key. * @param listener - The message listener callback. */ @@ -1546,7 +1705,6 @@ export abstract class AbstractPool< /** * Method hooked up after a worker node has been newly created. * Can be overridden. - * * @param workerNodeKey - The newly created worker node key. */ protected afterWorkerNodeSetup (workerNodeKey: number): void { @@ -1577,14 +1735,12 @@ export abstract class AbstractPool< /** * Sends the startup message to worker given its worker node key. - * * @param workerNodeKey - The worker node key. */ protected abstract sendStartupMessageToWorker (workerNodeKey: number): void /** * Sends the statistics message to worker given its worker node key. - * * @param workerNodeKey - The worker node key. */ private sendStatisticsMessageToWorker (workerNodeKey: number): void { @@ -1595,8 +1751,8 @@ export abstract class AbstractPool< .runTime.aggregate ?? false, elu: this.workerChoiceStrategiesContext?.getTaskStatisticsRequirements() - .elu.aggregate ?? false - } + .elu.aggregate ?? false, + }, }) } @@ -1612,14 +1768,15 @@ export abstract class AbstractPool< } } - private redistributeQueuedTasks (workerNodeKey: number): void { - if (workerNodeKey === -1 || this.cannotStealTask()) { + private redistributeQueuedTasks (sourceWorkerNodeKey: number): void { + if (sourceWorkerNodeKey === -1 || this.cannotStealTask()) { return } - while (this.tasksQueueSize(workerNodeKey) > 0) { + while (this.tasksQueueSize(sourceWorkerNodeKey) > 0) { const destinationWorkerNodeKey = this.workerNodes.reduce( (minWorkerNodeKey, workerNode, workerNodeKey, workerNodes) => { - return workerNode.info.ready && + return sourceWorkerNodeKey !== workerNodeKey && + workerNode.info.ready && workerNode.usage.tasks.queued < workerNodes[minWorkerNodeKey].usage.tasks.queued ? workerNodeKey @@ -1630,7 +1787,7 @@ export abstract class AbstractPool< this.handleTask( destinationWorkerNodeKey, // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.dequeueTask(workerNodeKey)! + this.dequeueTask(sourceWorkerNodeKey)! ) } } @@ -1648,28 +1805,21 @@ export abstract class AbstractPool< this.shallUpdateTaskFunctionWorkerUsage(workerNodeKey) && workerNode.getTaskFunctionWorkerUsage(taskName) != null ) { - const taskFunctionWorkerUsage = - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - workerNode.getTaskFunctionWorkerUsage(taskName)! - ++taskFunctionWorkerUsage.tasks.stolen + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + ++workerNode.getTaskFunctionWorkerUsage(taskName)!.tasks.stolen } } private updateTaskSequentiallyStolenStatisticsWorkerUsage ( - workerNodeKey: number + workerNodeKey: number, + taskName: string, + previousTaskName?: string ): void { const workerNode = this.workerNodes[workerNodeKey] // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (workerNode?.usage != null) { ++workerNode.usage.tasks.sequentiallyStolen } - } - - private updateTaskSequentiallyStolenStatisticsTaskFunctionWorkerUsage ( - workerNodeKey: number, - taskName: string - ): void { - const workerNode = this.workerNodes[workerNodeKey] if ( this.shallUpdateTaskFunctionWorkerUsage(workerNodeKey) && workerNode.getTaskFunctionWorkerUsage(taskName) != null @@ -1677,33 +1827,36 @@ export abstract class AbstractPool< const taskFunctionWorkerUsage = // eslint-disable-next-line @typescript-eslint/no-non-null-assertion workerNode.getTaskFunctionWorkerUsage(taskName)! - ++taskFunctionWorkerUsage.tasks.sequentiallyStolen + if ( + taskFunctionWorkerUsage.tasks.sequentiallyStolen === 0 || + (previousTaskName != null && + previousTaskName === taskName && + taskFunctionWorkerUsage.tasks.sequentiallyStolen > 0) + ) { + ++taskFunctionWorkerUsage.tasks.sequentiallyStolen + } else if (taskFunctionWorkerUsage.tasks.sequentiallyStolen > 0) { + taskFunctionWorkerUsage.tasks.sequentiallyStolen = 0 + } } } private resetTaskSequentiallyStolenStatisticsWorkerUsage ( - workerNodeKey: number + workerNodeKey: number, + taskName: string ): void { const workerNode = this.workerNodes[workerNodeKey] // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (workerNode?.usage != null) { workerNode.usage.tasks.sequentiallyStolen = 0 } - } - - private resetTaskSequentiallyStolenStatisticsTaskFunctionWorkerUsage ( - workerNodeKey: number, - taskName: string - ): void { - const workerNode = this.workerNodes[workerNodeKey] if ( this.shallUpdateTaskFunctionWorkerUsage(workerNodeKey) && workerNode.getTaskFunctionWorkerUsage(taskName) != null ) { - const taskFunctionWorkerUsage = - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - workerNode.getTaskFunctionWorkerUsage(taskName)! - taskFunctionWorkerUsage.tasks.sequentiallyStolen = 0 + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + workerNode.getTaskFunctionWorkerUsage( + taskName + )!.tasks.sequentiallyStolen = 0 } } @@ -1718,69 +1871,49 @@ export abstract class AbstractPool< ) } const workerInfo = this.getWorkerInfo(workerNodeKey) + if (workerInfo == null) { + throw new Error( + `Worker node with key '${workerNodeKey.toString()}' not found in pool` + ) + } if ( this.cannotStealTask() || (this.info.stealingWorkerNodes ?? 0) > Math.floor(this.workerNodes.length / 2) ) { - if (workerInfo != null && previousStolenTask != null) { + if (previousStolenTask != null) { workerInfo.stealing = false + this.resetTaskSequentiallyStolenStatisticsWorkerUsage( + workerNodeKey, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + previousStolenTask.name! + ) } return } const workerNodeTasksUsage = this.workerNodes[workerNodeKey].usage.tasks if ( - workerInfo != null && previousStolenTask != null && - workerNodeTasksUsage.sequentiallyStolen > 0 && (workerNodeTasksUsage.executing > 0 || this.tasksQueueSize(workerNodeKey) > 0) ) { workerInfo.stealing = false - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - for (const taskFunctionProperties of workerInfo.taskFunctionsProperties!) { - this.resetTaskSequentiallyStolenStatisticsTaskFunctionWorkerUsage( - workerNodeKey, - taskFunctionProperties.name - ) - } - this.resetTaskSequentiallyStolenStatisticsWorkerUsage(workerNodeKey) - return - } - if (workerInfo == null) { - throw new Error( - `Worker node with key '${workerNodeKey}' not found in pool` + this.resetTaskSequentiallyStolenStatisticsWorkerUsage( + workerNodeKey, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + previousStolenTask.name! ) + return } workerInfo.stealing = true const stolenTask = this.workerNodeStealTask(workerNodeKey) - if ( - this.shallUpdateTaskFunctionWorkerUsage(workerNodeKey) && - stolenTask != null - ) { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const taskFunctionTasksWorkerUsage = this.workerNodes[ - workerNodeKey + if (stolenTask != null) { + this.updateTaskSequentiallyStolenStatisticsWorkerUsage( + workerNodeKey, // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - ].getTaskFunctionWorkerUsage(stolenTask.name!)!.tasks - if ( - taskFunctionTasksWorkerUsage.sequentiallyStolen === 0 || - (previousStolenTask != null && - previousStolenTask.name === stolenTask.name && - taskFunctionTasksWorkerUsage.sequentiallyStolen > 0) - ) { - this.updateTaskSequentiallyStolenStatisticsTaskFunctionWorkerUsage( - workerNodeKey, - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - stolenTask.name! - ) - } else { - this.resetTaskSequentiallyStolenStatisticsTaskFunctionWorkerUsage( - workerNodeKey, - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - stolenTask.name! - ) - } + stolenTask.name!, + previousStolenTask?.name + ) } sleep(exponentialDelay(workerNodeTasksUsage.sequentiallyStolen)) .then(() => { @@ -1810,9 +1943,8 @@ export abstract class AbstractPool< ) if (sourceWorkerNode != null) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const task = sourceWorkerNode.dequeueTask(1)! + const task = sourceWorkerNode.dequeueLastPrioritizedTask()! this.handleTask(workerNodeKey, task) - this.updateTaskSequentiallyStolenStatisticsWorkerUsage(workerNodeKey) // eslint-disable-next-line @typescript-eslint/no-non-null-assertion this.updateTaskStolenStatisticsWorkerUsage(workerNodeKey, task.name!) return task @@ -1824,17 +1956,18 @@ export abstract class AbstractPool< ): void => { if ( this.cannotStealTask() || + this.hasBackPressure() || (this.info.stealingWorkerNodes ?? 0) > Math.floor(this.workerNodes.length / 2) ) { return } - const { workerId } = eventDetail const sizeOffset = 1 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion if (this.opts.tasksQueueOptions!.size! <= sizeOffset) { return } + const { workerId } = eventDetail const sourceWorkerNode = this.workerNodes[this.getWorkerNodeKeyByWorkerId(workerId)] const workerNodes = this.workerNodes @@ -1856,12 +1989,12 @@ export abstract class AbstractPool< const workerInfo = this.getWorkerInfo(workerNodeKey) if (workerInfo == null) { throw new Error( - `Worker node with key '${workerNodeKey}' not found in pool` + `Worker node with key '${workerNodeKey.toString()}' not found in pool` ) } workerInfo.stealing = true // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const task = sourceWorkerNode.dequeueTask(1)! + const task = sourceWorkerNode.dequeueLastPrioritizedTask()! this.handleTask(workerNodeKey, task) // eslint-disable-next-line @typescript-eslint/no-non-null-assertion this.updateTaskStolenStatisticsWorkerUsage(workerNodeKey, task.name!) @@ -1870,8 +2003,15 @@ export abstract class AbstractPool< } } + private setTasksQueuePriority (workerNodeKey: number): void { + this.workerNodes[workerNodeKey].setTasksQueuePriority( + this.getTasksQueuePriority() + ) + } + /** * This method is the message listener registered on each worker. + * @param message - The message received from the worker. */ protected readonly workerMessageListener = ( message: MessageValue @@ -1883,11 +2023,12 @@ export abstract class AbstractPool< this.handleWorkerReadyResponse(message) } else if (taskFunctionsProperties != null) { // Task function properties message received from worker - const workerInfo = this.getWorkerInfo( - this.getWorkerNodeKeyByWorkerId(workerId) - ) + const workerNodeKey = this.getWorkerNodeKeyByWorkerId(workerId) + const workerInfo = this.getWorkerInfo(workerNodeKey) if (workerInfo != null) { workerInfo.taskFunctionsProperties = taskFunctionsProperties + this.sendStatisticsMessageToWorker(workerNodeKey) + this.setTasksQueuePriority(workerNodeKey) } } else if (taskId != null) { // Task execution response received from worker @@ -1905,12 +2046,15 @@ export abstract class AbstractPool< private handleWorkerReadyResponse (message: MessageValue): void { const { workerId, ready, taskFunctionsProperties } = message if (ready == null || !ready) { - throw new Error(`Worker ${workerId} failed to initialize`) + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + throw new Error(`Worker ${workerId?.toString()} failed to initialize`) } - const workerNode = - this.workerNodes[this.getWorkerNodeKeyByWorkerId(workerId)] + const workerNodeKey = this.getWorkerNodeKeyByWorkerId(workerId) + const workerNode = this.workerNodes[workerNodeKey] workerNode.info.ready = ready workerNode.info.taskFunctionsProperties = taskFunctionsProperties + this.sendStatisticsMessageToWorker(workerNodeKey) + this.setTasksQueuePriority(workerNodeKey) this.checkAndEmitReadyEvent() } @@ -1964,7 +2108,7 @@ export abstract class AbstractPool< ) { workerNode.emit('idle', { workerId, - workerNodeKey + workerNodeKey, }) } } @@ -1990,7 +2134,6 @@ export abstract class AbstractPool< /** * Gets the worker information given its worker node key. - * * @param workerNodeKey - The worker node key. * @returns The worker information. */ @@ -1998,9 +2141,14 @@ export abstract class AbstractPool< return this.workerNodes[workerNodeKey]?.info } + private getTasksQueuePriority (): boolean { + return this.listTaskFunctionsProperties().some( + taskFunctionProperties => taskFunctionProperties.priority != null + ) + } + /** * Creates a worker node. - * * @returns The created worker node. */ private createWorkerNode (): IWorkerNode { @@ -2015,8 +2163,8 @@ export abstract class AbstractPool< getDefaultTasksQueueOptions( this.maximumNumberOfWorkers ?? this.minimumNumberOfWorkers ).size, - tasksQueueBucketSize: - (this.maximumNumberOfWorkers ?? this.minimumNumberOfWorkers) * 2 + tasksQueueBucketSize: defaultBucketSize, + tasksQueuePriority: this.getTasksQueuePriority(), } ) // Flag the worker node as ready at pool startup. @@ -2028,7 +2176,6 @@ export abstract class AbstractPool< /** * Adds the given worker node in the pool worker nodes. - * * @param workerNode - The worker node. * @returns The added worker node key. * @throws {@link https://nodejs.org/api/errors.html#class-error} If the added worker node is not found. @@ -2051,7 +2198,6 @@ export abstract class AbstractPool< /** * Removes the worker node from the pool worker nodes. - * * @param workerNode - The worker node. */ private removeWorkerNode (workerNode: IWorkerNode): void { @@ -2081,7 +2227,6 @@ export abstract class AbstractPool< /** * Executes the given task on the worker given its worker node key. - * * @param workerNodeKey - The worker node key. * @param task - The task to execute. */ @@ -2097,11 +2242,8 @@ export abstract class AbstractPool< return tasksQueueSize } - private dequeueTask ( - workerNodeKey: number, - bucket?: number - ): Task | undefined { - return this.workerNodes[workerNodeKey].dequeueTask(bucket) + private dequeueTask (workerNodeKey: number): Task | undefined { + return this.workerNodes[workerNodeKey].dequeueTask() } private tasksQueueSize (workerNodeKey: number): number { diff --git a/src/pools/cluster/dynamic.ts b/src/pools/cluster/dynamic.ts index 51d1cbee..47799f5e 100644 --- a/src/pools/cluster/dynamic.ts +++ b/src/pools/cluster/dynamic.ts @@ -7,7 +7,6 @@ import { type ClusterPoolOptions, FixedClusterPool } from './fixed.js' * * 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 structured-cloneable data. * @typeParam Response - Type of execution response. This can only be structured-cloneable data. * @author [Christopher Quadflieg](https://github.com/Shinigami92) @@ -19,7 +18,6 @@ export class DynamicClusterPool< > extends FixedClusterPool { /** * Constructs a new poolifier dynamic cluster pool. - * * @param min - Minimum number of workers which are always active. * @param max - Maximum number of workers that can be created by this pool. * @param filePath - Path to an implementation of a `ClusterWorker` file, which can be relative or absolute. diff --git a/src/pools/cluster/fixed.ts b/src/pools/cluster/fixed.ts index 4a8cb4f1..bf61cd47 100644 --- a/src/pools/cluster/fixed.ts +++ b/src/pools/cluster/fixed.ts @@ -12,7 +12,6 @@ export type ClusterPoolOptions = PoolOptions /** * A cluster pool with a fixed number of workers. - * * @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) @@ -24,10 +23,10 @@ export class FixedClusterPool< > extends AbstractPool { /** * Constructs a new poolifier fixed cluster pool. - * * @param numberOfWorkers - Number of workers for this pool. * @param filePath - Path to an implementation of a `ClusterWorker` file, which can be relative or absolute. * @param opts - Options for this fixed cluster pool. + * @param maximumNumberOfWorkers - The maximum number of workers for this pool. */ public constructor ( numberOfWorkers: number, @@ -55,14 +54,14 @@ export class FixedClusterPool< ): void { this.workerNodes[workerNodeKey]?.worker.send({ ...message, - workerId: this.getWorkerInfo(workerNodeKey)?.id + workerId: this.getWorkerInfo(workerNodeKey)?.id, } satisfies MessageValue) } /** @inheritDoc */ protected sendStartupMessageToWorker (workerNodeKey: number): void { this.sendToWorker(workerNodeKey, { - ready: false + ready: false, }) } diff --git a/src/pools/pool.ts b/src/pools/pool.ts index ccb4b5b9..c2d54987 100644 --- a/src/pools/pool.ts +++ b/src/pools/pool.ts @@ -3,10 +3,13 @@ import type { EventEmitterAsyncResource } from 'node:events' import type { TransferListItem, WorkerOptions } from 'node:worker_threads' import type { TaskFunctionProperties } from '../utility-types.js' -import type { TaskFunction } from '../worker/task-functions.js' +import type { + TaskFunction, + TaskFunctionObject, +} from '../worker/task-functions.js' import type { WorkerChoiceStrategy, - WorkerChoiceStrategyOptions + WorkerChoiceStrategyOptions, } from './selection-strategies/selection-strategies-types.js' import type { ErrorHandler, @@ -15,7 +18,7 @@ import type { IWorkerNode, MessageHandler, OnlineHandler, - WorkerType + WorkerType, } from './worker.js' /** @@ -32,7 +35,7 @@ export const PoolTypes: Readonly<{ /** * Dynamic pool type. */ - dynamic: 'dynamic' + dynamic: 'dynamic', } as const) /** @@ -60,7 +63,7 @@ export const PoolEvents: Readonly<{ destroy: 'destroy', error: 'error', taskError: 'taskError', - backPressure: 'backPressure' + backPressure: 'backPressure', } as const) /** @@ -110,6 +113,24 @@ export interface PoolInfo { readonly average?: number readonly median?: number } + readonly elu?: { + idle: { + readonly minimum: number + readonly maximum: number + readonly average?: number + readonly median?: number + } + active: { + readonly minimum: number + readonly maximum: number + readonly average?: number + readonly median?: number + } + utilization: { + readonly average?: number + readonly median?: number + } + } } /** @@ -118,31 +139,26 @@ export interface PoolInfo { export interface TasksQueueOptions { /** * Maximum tasks queue size per worker node flagging it as back pressured. - * * @defaultValue (pool maximum size)^2 */ readonly size?: number /** * Maximum number of tasks that can be executed concurrently on a worker node. - * * @defaultValue 1 */ readonly concurrency?: number /** * Whether to enable task stealing on idle. - * * @defaultValue true */ readonly taskStealing?: boolean /** * Whether to enable tasks stealing under back pressure. - * - * @defaultValue true + * @defaultValue false */ readonly tasksStealingOnBackPressure?: boolean /** * Queued tasks finished timeout in milliseconds at worker node termination. - * * @defaultValue 2000 */ readonly tasksFinishedTimeout?: number @@ -150,43 +166,36 @@ export interface TasksQueueOptions { /** * Options for a poolifier pool. - * * @typeParam Worker - Type of worker. */ export interface PoolOptions { /** * A function that will listen for online event on each worker. - * * @defaultValue `() => {}` */ onlineHandler?: OnlineHandler /** * A function that will listen for message event on each worker. - * * @defaultValue `() => {}` */ messageHandler?: MessageHandler /** * A function that will listen for error event on each worker. - * * @defaultValue `() => {}` */ errorHandler?: ErrorHandler /** * A function that will listen for exit event on each worker. - * * @defaultValue `() => {}` */ exitHandler?: ExitHandler /** * Whether to start the minimum number of workers at pool initialization. - * * @defaultValue true */ startWorkers?: boolean /** * The default worker choice strategy to use in this pool. - * * @defaultValue WorkerChoiceStrategies.ROUND_ROBIN */ workerChoiceStrategy?: WorkerChoiceStrategy @@ -200,13 +209,11 @@ export interface PoolOptions { restartWorkerOnError?: boolean /** * Pool events integrated with async resource emission. - * * @defaultValue true */ enableEvents?: boolean /** * Pool worker node tasks queue. - * * @defaultValue false */ enableTasksQueue?: boolean @@ -216,19 +223,16 @@ export interface PoolOptions { tasksQueueOptions?: TasksQueueOptions /** * Worker options. - * * @see https://nodejs.org/api/worker_threads.html#new-workerfilename-options */ workerOptions?: WorkerOptions /** * Key/value pairs to add to worker process environment. - * * @see https://nodejs.org/api/cluster.html#cluster_cluster_fork_env */ env?: Record /** * Cluster settings. - * * @see https://nodejs.org/api/cluster.html#cluster_cluster_settings */ settings?: ClusterSettings @@ -236,7 +240,6 @@ 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 structured-cloneable data. * @typeParam Response - Type of execution response. This can only be structured-cloneable data. @@ -252,10 +255,9 @@ export interface IPool< readonly info: PoolInfo /** * Pool worker nodes. - * * @internal */ - readonly workerNodes: Array> + readonly workerNodes: IWorkerNode[] /** * Pool event emitter integrated with async resource. * The async tracking tooling identifier is `poolifier:--pool`. @@ -274,7 +276,6 @@ export interface IPool< readonly emitter?: EventEmitterAsyncResource /** * Executes the specified function in the worker constructor with the task data input parameter. - * * @param data - The optional task input data for the specified task function. This can only be structured-cloneable data. * @param name - The optional name of the task function to execute. If not specified, the default task function will be executed. * @param transferList - An optional array of transferable objects to transfer ownership of. Ownership of the transferred objects is given to the chosen pool's worker_threads worker and they should not be used in the main thread afterwards. @@ -295,7 +296,6 @@ export interface IPool< readonly destroy: () => Promise /** * Whether the specified task function exists in this pool. - * * @param name - The name of the task function. * @returns `true` if the task function exists, `false` otherwise. */ @@ -303,40 +303,35 @@ export interface IPool< /** * Adds a task function to this pool. * If a task function with the same name already exists, it will be overwritten. - * * @param name - The name of the task function. * @param fn - The task function. * @returns `true` if the task function was added, `false` otherwise. * @throws {@link https://nodejs.org/api/errors.html#class-typeerror} If the `name` parameter is not a string or an empty string. - * @throws {@link https://nodejs.org/api/errors.html#class-typeerror} If the `fn` parameter is not a function. + * @throws {@link https://nodejs.org/api/errors.html#class-typeerror} If the `fn` parameter is not a function or task function object. */ readonly addTaskFunction: ( name: string, - fn: TaskFunction + fn: TaskFunction | TaskFunctionObject ) => Promise /** * Removes a task function from this pool. - * * @param name - The name of the task function. * @returns `true` if the task function was removed, `false` otherwise. */ readonly removeTaskFunction: (name: string) => Promise /** * Lists the properties of task functions available in this pool. - * * @returns The properties of task functions available in this pool. */ readonly listTaskFunctionsProperties: () => TaskFunctionProperties[] /** * Sets the default task function in this pool. - * * @param name - The name of the task function. * @returns `true` if the default task function was set, `false` otherwise. */ readonly setDefaultTaskFunction: (name: string) => Promise /** * Sets the default worker choice strategy in this pool. - * * @param workerChoiceStrategy - The default worker choice strategy. * @param workerChoiceStrategyOptions - The worker choice strategy options. */ @@ -346,7 +341,6 @@ export interface IPool< ) => void /** * Sets the worker choice strategy options in this pool. - * * @param workerChoiceStrategyOptions - The worker choice strategy options. * @returns `true` if the worker choice strategy options were set, `false` otherwise. */ @@ -355,7 +349,6 @@ export interface IPool< ) => boolean /** * Enables/disables the worker node tasks queue in this pool. - * * @param enable - Whether to enable or disable the worker node tasks queue. * @param tasksQueueOptions - The worker node tasks queue options. */ @@ -365,7 +358,6 @@ export interface IPool< ) => void /** * Sets the worker node tasks queue options in this pool. - * * @param tasksQueueOptions - The worker node tasks queue options. */ readonly setTasksQueueOptions: (tasksQueueOptions: TasksQueueOptions) => void diff --git a/src/pools/selection-strategies/abstract-worker-choice-strategy.ts b/src/pools/selection-strategies/abstract-worker-choice-strategy.ts index 2b40f0c6..f4273dcd 100644 --- a/src/pools/selection-strategies/abstract-worker-choice-strategy.ts +++ b/src/pools/selection-strategies/abstract-worker-choice-strategy.ts @@ -5,16 +5,15 @@ import type { IWorkerChoiceStrategy, StrategyPolicy, TaskStatisticsRequirements, - WorkerChoiceStrategyOptions + WorkerChoiceStrategyOptions, } from './selection-strategies-types.js' import { buildWorkerChoiceStrategyOptions, - toggleMedianMeasurementStatisticsRequirements + toggleMedianMeasurementStatisticsRequirements, } from './selection-strategies-utils.js' /** * 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 structured-cloneable data. * @typeParam Response - Type of execution response. This can only be structured-cloneable data. @@ -37,19 +36,18 @@ export abstract class AbstractWorkerChoiceStrategy< /** @inheritDoc */ public readonly strategyPolicy: StrategyPolicy = { dynamicWorkerUsage: false, - dynamicWorkerReady: true + dynamicWorkerReady: true, } /** @inheritDoc */ public readonly taskStatisticsRequirements: TaskStatisticsRequirements = { runTime: DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS, waitTime: DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS, - elu: DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS + elu: DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS, } /** * Constructs a worker choice strategy bound to the pool. - * * @param pool - The pool instance. * @param opts - The worker choice strategy options. */ @@ -109,7 +107,6 @@ export abstract class AbstractWorkerChoiceStrategy< /** * Whether the worker node is ready or not. - * * @param workerNodeKey - The worker node key. * @returns Whether the worker node is ready or not. */ @@ -134,7 +131,6 @@ export abstract class AbstractWorkerChoiceStrategy< * Gets the worker node task runtime. * If the task statistics require the average runtime, the average runtime is returned. * If the task statistics require the median runtime, the median runtime is returned. - * * @param workerNodeKey - The worker node key. * @returns The worker node task runtime. */ @@ -148,7 +144,6 @@ export abstract class AbstractWorkerChoiceStrategy< * Gets the worker node task wait time. * If the task statistics require the average wait time, the average wait time is returned. * If the task statistics require the median wait time, the median wait time is returned. - * * @param workerNodeKey - The worker node key. * @returns The worker node task wait time. */ @@ -162,7 +157,6 @@ export abstract class AbstractWorkerChoiceStrategy< * Gets the worker node task ELU. * If the task statistics require the average ELU, the average ELU is returned. * If the task statistics require the median ELU, the median ELU is returned. - * * @param workerNodeKey - The worker node key. * @returns The worker node task ELU. */ @@ -174,7 +168,6 @@ export abstract class AbstractWorkerChoiceStrategy< /** * Sets safely the previous worker node key. - * * @param workerNodeKey - The worker node key. */ protected setPreviousWorkerNodeKey (workerNodeKey: number | undefined): void { 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 2f2686e9..88e12b94 100644 --- a/src/pools/selection-strategies/fair-share-worker-choice-strategy.ts +++ b/src/pools/selection-strategies/fair-share-worker-choice-strategy.ts @@ -5,13 +5,12 @@ import { type IWorkerChoiceStrategy, Measurements, type TaskStatisticsRequirements, - type WorkerChoiceStrategyOptions + type WorkerChoiceStrategyOptions, } from './selection-strategies-types.js' /** * Selects the next worker with a fair share scheduling algorithm. * 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 structured-cloneable data. * @typeParam Response - Type of execution response. This can only be structured-cloneable data. @@ -28,18 +27,18 @@ export class FairShareWorkerChoiceStrategy< runTime: { aggregate: true, average: true, - median: false + median: false, }, waitTime: { aggregate: true, average: true, - median: false + median: false, }, elu: { aggregate: true, average: true, - median: false - } + median: false, + }, } /** @inheritDoc */ @@ -63,7 +62,7 @@ export class FairShareWorkerChoiceStrategy< public update (workerNodeKey: number): boolean { this.pool.workerNodes[workerNodeKey].strategyData = { virtualTaskEndTimestamp: - this.computeWorkerNodeVirtualTaskEndTimestamp(workerNodeKey) + this.computeWorkerNodeVirtualTaskEndTimestamp(workerNodeKey), } return true } @@ -81,15 +80,12 @@ export class FairShareWorkerChoiceStrategy< } private fairShareNextWorkerNodeKey (): number | undefined { - if (this.pool.workerNodes.length === 0) { - return undefined - } return this.pool.workerNodes.reduce( (minWorkerNodeKey, workerNode, workerNodeKey, workerNodes) => { if (workerNode.strategyData?.virtualTaskEndTimestamp == null) { workerNode.strategyData = { virtualTaskEndTimestamp: - this.computeWorkerNodeVirtualTaskEndTimestamp(workerNodeKey) + this.computeWorkerNodeVirtualTaskEndTimestamp(workerNodeKey), } } return this.isWorkerNodeReady(workerNodeKey) && @@ -106,7 +102,6 @@ export class FairShareWorkerChoiceStrategy< /** * Computes the worker node key virtual task end timestamp. - * * @param workerNodeKey - The worker node key. * @returns The worker node key virtual task end timestamp. */ @@ -139,7 +134,7 @@ export class FairShareWorkerChoiceStrategy< this.pool.workerNodes[workerNodeKey]?.strategyData ?.virtualTaskEndTimestamp const now = performance.now() - return now < (virtualTaskEndTimestamp ?? -Infinity) + return now < (virtualTaskEndTimestamp ?? Number.NEGATIVE_INFINITY) ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion virtualTaskEndTimestamp! : now 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 4048924c..61dd2cff 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 @@ -5,12 +5,11 @@ import { AbstractWorkerChoiceStrategy } from './abstract-worker-choice-strategy. import type { IWorkerChoiceStrategy, TaskStatisticsRequirements, - WorkerChoiceStrategyOptions + WorkerChoiceStrategyOptions, } from './selection-strategies-types.js' /** * 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 structured-cloneable data. * @typeParam Response - Type of execution response. This can only be structured-cloneable data. @@ -27,14 +26,14 @@ export class InterleavedWeightedRoundRobinWorkerChoiceStrategy< runTime: { aggregate: true, average: true, - median: false + median: false, }, waitTime: { aggregate: true, average: true, - median: false + median: false, }, - elu: DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS + elu: DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS, } /** @@ -170,7 +169,7 @@ export class InterleavedWeightedRoundRobinWorkerChoiceStrategy< Object.values(this.opts!.weights!) .slice() .sort((a, b) => a - b) - ) + ), ] } } 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 a9fe3d1c..33199368 100644 --- a/src/pools/selection-strategies/least-busy-worker-choice-strategy.ts +++ b/src/pools/selection-strategies/least-busy-worker-choice-strategy.ts @@ -5,12 +5,11 @@ import { AbstractWorkerChoiceStrategy } from './abstract-worker-choice-strategy. import type { IWorkerChoiceStrategy, TaskStatisticsRequirements, - WorkerChoiceStrategyOptions + WorkerChoiceStrategyOptions, } from './selection-strategies-types.js' /** * 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 structured-cloneable data. * @typeParam Response - Type of execution response. This can only be structured-cloneable data. @@ -27,14 +26,14 @@ export class LeastBusyWorkerChoiceStrategy< runTime: { aggregate: true, average: false, - median: false + median: false, }, waitTime: { aggregate: true, average: false, - median: false + median: false, }, - elu: DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS + elu: DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS, } /** @inheritDoc */ @@ -69,9 +68,6 @@ export class LeastBusyWorkerChoiceStrategy< } private leastBusyNextWorkerNodeKey (): number | undefined { - if (this.pool.workerNodes.length === 0) { - return undefined - } return this.pool.workerNodes.reduce( (minWorkerNodeKey, workerNode, workerNodeKey, workerNodes) => { return this.isWorkerNodeReady(workerNodeKey) && 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 9cb28bac..ead02e85 100644 --- a/src/pools/selection-strategies/least-elu-worker-choice-strategy.ts +++ b/src/pools/selection-strategies/least-elu-worker-choice-strategy.ts @@ -5,12 +5,11 @@ import { AbstractWorkerChoiceStrategy } from './abstract-worker-choice-strategy. import type { IWorkerChoiceStrategy, TaskStatisticsRequirements, - WorkerChoiceStrategyOptions + WorkerChoiceStrategyOptions, } from './selection-strategies-types.js' /** * 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 structured-cloneable data. * @typeParam Response - Type of execution response. This can only be structured-cloneable data. @@ -29,8 +28,8 @@ export class LeastEluWorkerChoiceStrategy< elu: { aggregate: true, average: false, - median: false - } + median: false, + }, } /** @inheritDoc */ @@ -65,9 +64,6 @@ export class LeastEluWorkerChoiceStrategy< } private leastEluNextWorkerNodeKey (): number | undefined { - if (this.pool.workerNodes.length === 0) { - return undefined - } return this.pool.workerNodes.reduce( (minWorkerNodeKey, workerNode, workerNodeKey, workerNodes) => { return this.isWorkerNodeReady(workerNodeKey) && 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 cd93d752..1ee6b7b8 100644 --- a/src/pools/selection-strategies/least-used-worker-choice-strategy.ts +++ b/src/pools/selection-strategies/least-used-worker-choice-strategy.ts @@ -3,12 +3,11 @@ import type { IWorker } from '../worker.js' import { AbstractWorkerChoiceStrategy } from './abstract-worker-choice-strategy.js' import type { IWorkerChoiceStrategy, - WorkerChoiceStrategyOptions + WorkerChoiceStrategyOptions, } from './selection-strategies-types.js' /** * 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 structured-cloneable data. * @typeParam Response - Type of execution response. This can only be structured-cloneable data. @@ -51,9 +50,6 @@ export class LeastUsedWorkerChoiceStrategy< } private leastUsedNextWorkerNodeKey (): number | undefined { - if (this.pool.workerNodes.length === 0) { - return undefined - } return this.pool.workerNodes.reduce( (minWorkerNodeKey, workerNode, workerNodeKey, workerNodes) => { return this.isWorkerNodeReady(workerNodeKey) && 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 83126d97..1f5c499e 100644 --- a/src/pools/selection-strategies/round-robin-worker-choice-strategy.ts +++ b/src/pools/selection-strategies/round-robin-worker-choice-strategy.ts @@ -3,12 +3,11 @@ import type { IWorker } from '../worker.js' import { AbstractWorkerChoiceStrategy } from './abstract-worker-choice-strategy.js' import type { IWorkerChoiceStrategy, - WorkerChoiceStrategyOptions + WorkerChoiceStrategyOptions, } from './selection-strategies-types.js' /** * 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 structured-cloneable data. * @typeParam Response - Type of execution response. This can only be structured-cloneable data. diff --git a/src/pools/selection-strategies/selection-strategies-types.ts b/src/pools/selection-strategies/selection-strategies-types.ts index 1a8ea298..745b140a 100644 --- a/src/pools/selection-strategies/selection-strategies-types.ts +++ b/src/pools/selection-strategies/selection-strategies-types.ts @@ -36,10 +36,9 @@ export const WorkerChoiceStrategies: Readonly<{ WEIGHTED_ROUND_ROBIN: 'WEIGHTED_ROUND_ROBIN', /** * Interleaved weighted round robin worker selection strategy. - * * @experimental */ - INTERLEAVED_WEIGHTED_ROUND_ROBIN: 'INTERLEAVED_WEIGHTED_ROUND_ROBIN' + INTERLEAVED_WEIGHTED_ROUND_ROBIN: 'INTERLEAVED_WEIGHTED_ROUND_ROBIN', } as const) /** @@ -57,7 +56,7 @@ export const Measurements: Readonly<{ }> = Object.freeze({ runTime: 'runTime', waitTime: 'waitTime', - elu: 'elu' + elu: 'elu', } as const) /** @@ -85,26 +84,22 @@ export interface WorkerChoiceStrategyOptions { readonly measurement?: Measurement /** * Runtime options. - * * @defaultValue \{ median: false \} */ readonly runTime?: MeasurementOptions /** * Wait time options. - * * @defaultValue \{ median: false \} */ readonly waitTime?: MeasurementOptions /** * Event loop utilization options. - * * @defaultValue \{ median: false \} */ readonly elu?: MeasurementOptions /** * Worker weights to use for weighted round robin worker selection strategies. * A weight is tasks maximum execution time in milliseconds for a worker node. - * * @defaultValue Weights computed automatically given the CPU performance. */ weights?: Record @@ -112,7 +107,6 @@ export interface WorkerChoiceStrategyOptions { /** * Measurement statistics requirements. - * * @internal */ export interface MeasurementStatisticsRequirements { @@ -132,7 +126,6 @@ export interface MeasurementStatisticsRequirements { /** * Pool worker node worker usage statistics requirements. - * * @internal */ export interface TaskStatisticsRequirements { @@ -152,7 +145,6 @@ export interface TaskStatisticsRequirements { /** * Strategy policy. - * * @internal */ export interface StrategyPolicy { @@ -168,7 +160,6 @@ export interface StrategyPolicy { /** * Worker choice strategy interface. - * * @internal */ export interface IWorkerChoiceStrategy { @@ -182,14 +173,12 @@ export interface IWorkerChoiceStrategy { readonly taskStatisticsRequirements: TaskStatisticsRequirements /** * Resets strategy internals. - * * @returns `true` if the reset is successful, `false` otherwise. */ readonly reset: () => boolean /** * Updates the worker node key strategy internals. * This is called after a task has been executed on a worker node. - * * @returns `true` if the update is successful, `false` otherwise. */ readonly update: (workerNodeKey: number) => boolean @@ -197,20 +186,17 @@ export interface IWorkerChoiceStrategy { * Chooses a worker node in the pool and returns its key. * If no worker nodes are not eligible, `undefined` is returned. * If `undefined` is returned, the caller retry. - * * @returns The worker node key or `undefined`. */ readonly choose: () => number | undefined /** * Removes the worker node key from strategy internals. - * * @param workerNodeKey - The worker node key. * @returns `true` if the worker node key is removed, `false` otherwise. */ readonly remove: (workerNodeKey: number) => boolean /** * Sets the worker choice strategy options. - * * @param opts - The worker choice strategy options. */ readonly setOptions: (opts: WorkerChoiceStrategyOptions | undefined) => void diff --git a/src/pools/selection-strategies/selection-strategies-utils.ts b/src/pools/selection-strategies/selection-strategies-utils.ts index 6e63f781..1c0b91b4 100644 --- a/src/pools/selection-strategies/selection-strategies-utils.ts +++ b/src/pools/selection-strategies/selection-strategies-utils.ts @@ -15,7 +15,7 @@ import { type TaskStatisticsRequirements, WorkerChoiceStrategies, type WorkerChoiceStrategy, - type WorkerChoiceStrategyOptions + type WorkerChoiceStrategyOptions, } from './selection-strategies-types.js' import { WeightedRoundRobinWorkerChoiceStrategy } from './weighted-round-robin-worker-choice-strategy.js' import type { WorkerChoiceStrategiesContext } from './worker-choice-strategies-context.js' @@ -95,9 +95,9 @@ export const buildWorkerChoiceStrategyOptions = < ...{ runTime: { median: false }, waitTime: { median: false }, - elu: { median: false } + elu: { median: false }, }, - ...opts + ...opts, } } @@ -118,41 +118,40 @@ export const toggleMedianMeasurementStatisticsRequirements = ( export const buildWorkerChoiceStrategiesPolicy = ( workerChoiceStrategies: Map ): StrategyPolicy => { - const policies: StrategyPolicy[] = [] - for (const workerChoiceStrategy of workerChoiceStrategies.values()) { - policies.push(workerChoiceStrategy.strategyPolicy) - } + const policies: StrategyPolicy[] = Array.from( + workerChoiceStrategies, + ([_, workerChoiceStrategy]) => workerChoiceStrategy.strategyPolicy + ) return { dynamicWorkerUsage: policies.some(p => p.dynamicWorkerUsage), - dynamicWorkerReady: policies.some(p => p.dynamicWorkerReady) + dynamicWorkerReady: policies.some(p => p.dynamicWorkerReady), } } export const buildWorkerChoiceStrategiesTaskStatisticsRequirements = ( workerChoiceStrategies: Map ): TaskStatisticsRequirements => { - const taskStatisticsRequirements: TaskStatisticsRequirements[] = [] - for (const workerChoiceStrategy of workerChoiceStrategies.values()) { - taskStatisticsRequirements.push( + const taskStatisticsRequirements: TaskStatisticsRequirements[] = Array.from( + workerChoiceStrategies, + ([_, workerChoiceStrategy]) => workerChoiceStrategy.taskStatisticsRequirements - ) - } + ) return { runTime: { aggregate: taskStatisticsRequirements.some(r => r.runTime.aggregate), average: taskStatisticsRequirements.some(r => r.runTime.average), - median: taskStatisticsRequirements.some(r => r.runTime.median) + median: taskStatisticsRequirements.some(r => r.runTime.median), }, waitTime: { aggregate: taskStatisticsRequirements.some(r => r.waitTime.aggregate), average: taskStatisticsRequirements.some(r => r.waitTime.average), - median: taskStatisticsRequirements.some(r => r.waitTime.median) + median: taskStatisticsRequirements.some(r => r.waitTime.median), }, elu: { aggregate: taskStatisticsRequirements.some(r => r.elu.aggregate), average: taskStatisticsRequirements.some(r => r.elu.average), - median: taskStatisticsRequirements.some(r => r.elu.median) - } + median: taskStatisticsRequirements.some(r => r.elu.median), + }, } } 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 6ce55c9a..ffd4fc39 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 @@ -5,13 +5,12 @@ import { AbstractWorkerChoiceStrategy } from './abstract-worker-choice-strategy. import type { IWorkerChoiceStrategy, TaskStatisticsRequirements, - WorkerChoiceStrategyOptions + WorkerChoiceStrategyOptions, } from './selection-strategies-types.js' /** * Selects the next worker with a weighted round robin scheduling algorithm. * 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 structured-cloneable data. * @typeParam Response - Type of execution response. This can only be structured-cloneable data. @@ -28,14 +27,14 @@ export class WeightedRoundRobinWorkerChoiceStrategy< runTime: { aggregate: true, average: true, - median: false + median: false, }, waitTime: { aggregate: true, average: true, - median: false + median: false, }, - elu: DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS + elu: DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS, } /** diff --git a/src/pools/selection-strategies/worker-choice-strategies-context.ts b/src/pools/selection-strategies/worker-choice-strategies-context.ts index d088015a..a736896a 100644 --- a/src/pools/selection-strategies/worker-choice-strategies-context.ts +++ b/src/pools/selection-strategies/worker-choice-strategies-context.ts @@ -5,19 +5,18 @@ import type { StrategyPolicy, TaskStatisticsRequirements, WorkerChoiceStrategy, - WorkerChoiceStrategyOptions + WorkerChoiceStrategyOptions, } from './selection-strategies-types.js' import { WorkerChoiceStrategies } from './selection-strategies-types.js' import { buildWorkerChoiceStrategiesPolicy, buildWorkerChoiceStrategiesTaskStatisticsRequirements, getWorkerChoiceStrategiesRetries, - getWorkerChoiceStrategy + getWorkerChoiceStrategy, } from './selection-strategies-utils.js' /** * The worker choice strategies context. - * * @typeParam Worker - Type of worker. * @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. @@ -41,8 +40,8 @@ export class WorkerChoiceStrategiesContext< * The worker choice strategies registered in the context. */ private readonly workerChoiceStrategies: Map< - WorkerChoiceStrategy, - IWorkerChoiceStrategy + WorkerChoiceStrategy, + IWorkerChoiceStrategy > /** @@ -62,7 +61,6 @@ export class WorkerChoiceStrategiesContext< /** * Worker choice strategies context constructor. - * * @param pool - The pool instance. * @param workerChoiceStrategies - The worker choice strategies. @defaultValue [WorkerChoiceStrategies.ROUND_ROBIN] * @param opts - The worker choice strategy options. @@ -70,15 +68,15 @@ export class WorkerChoiceStrategiesContext< public constructor ( private readonly pool: IPool, workerChoiceStrategies: WorkerChoiceStrategy[] = [ - WorkerChoiceStrategies.ROUND_ROBIN + WorkerChoiceStrategies.ROUND_ROBIN, ], opts?: WorkerChoiceStrategyOptions ) { this.execute = this.execute.bind(this) this.defaultWorkerChoiceStrategy = workerChoiceStrategies[0] this.workerChoiceStrategies = new Map< - WorkerChoiceStrategy, - IWorkerChoiceStrategy + WorkerChoiceStrategy, + IWorkerChoiceStrategy >() for (const workerChoiceStrategy of workerChoiceStrategies) { this.addWorkerChoiceStrategy(workerChoiceStrategy, this.pool, opts) @@ -99,7 +97,6 @@ export class WorkerChoiceStrategiesContext< /** * Gets the active worker choice strategies in the context policy. - * * @returns The strategies policy. */ public getPolicy (): StrategyPolicy { @@ -108,7 +105,6 @@ export class WorkerChoiceStrategiesContext< /** * Gets the active worker choice strategies in the context task statistics requirements. - * * @returns The strategies task statistics requirements. */ public getTaskStatisticsRequirements (): TaskStatisticsRequirements { @@ -117,7 +113,6 @@ export class WorkerChoiceStrategiesContext< /** * Sets the default worker choice strategy to use in the context. - * * @param workerChoiceStrategy - The default worker choice strategy to set. * @param opts - The worker choice strategy options. */ @@ -133,20 +128,18 @@ export class WorkerChoiceStrategiesContext< /** * Updates the worker node key in the active worker choice strategies in the context internals. - * + * @param workerNodeKey - The worker node key. * @returns `true` if the update is successful, `false` otherwise. */ public update (workerNodeKey: number): boolean { - const res: boolean[] = [] - for (const workerChoiceStrategy of this.workerChoiceStrategies.values()) { - res.push(workerChoiceStrategy.update(workerNodeKey)) - } - return res.every(r => r) + return Array.from( + this.workerChoiceStrategies, + ([_, workerChoiceStrategy]) => workerChoiceStrategy.update(workerNodeKey) + ).every(r => r) } /** * Executes the given worker choice strategy in the context algorithm. - * * @param workerChoiceStrategy - The worker choice strategy algorithm to execute. @defaultValue this.defaultWorkerChoiceStrategy * @returns The key of the worker node. * @throws {@link https://nodejs.org/api/errors.html#class-error} If after computed retries the worker node key is null or undefined. @@ -163,7 +156,6 @@ export class WorkerChoiceStrategiesContext< /** * Executes the given worker choice strategy. - * * @param workerChoiceStrategy - The worker choice strategy. * @returns The key of the worker node. * @throws {@link https://nodejs.org/api/errors.html#class-error} If after computed retries the worker node key is null or undefined. @@ -182,7 +174,7 @@ export class WorkerChoiceStrategiesContext< } while (workerNodeKey == null && retriesCount < this.retries) if (workerNodeKey == null) { throw new Error( - `Worker node key chosen is null or undefined after ${retriesCount} retries` + `Worker node key chosen is null or undefined after ${retriesCount.toString()} retries` ) } return workerNodeKey @@ -190,21 +182,18 @@ export class WorkerChoiceStrategiesContext< /** * Removes the worker node key from the active worker choice strategies in the context. - * * @param workerNodeKey - The worker node key. * @returns `true` if the removal is successful, `false` otherwise. */ public remove (workerNodeKey: number): boolean { - const res: boolean[] = [] - for (const workerChoiceStrategy of this.workerChoiceStrategies.values()) { - res.push(workerChoiceStrategy.remove(workerNodeKey)) - } - return res.every(r => r) + return Array.from( + this.workerChoiceStrategies, + ([_, workerChoiceStrategy]) => workerChoiceStrategy.remove(workerNodeKey) + ).every(r => r) } /** * Sets the active worker choice strategies in the context options. - * * @param opts - The worker choice strategy options. */ public setOptions (opts: WorkerChoiceStrategyOptions | undefined): void { @@ -215,7 +204,6 @@ export class WorkerChoiceStrategiesContext< /** * Synchronizes the active worker choice strategies in the context with the given worker choice strategies. - * * @param workerChoiceStrategies - The worker choice strategies to synchronize. * @param opts - The worker choice strategy options. */ @@ -244,8 +232,8 @@ export class WorkerChoiceStrategiesContext< /** * Adds a worker choice strategy to the context. - * * @param workerChoiceStrategy - The worker choice strategy to add. + * @param pool - The pool instance. * @param opts - The worker choice strategy options. * @returns The worker choice strategies. */ @@ -270,7 +258,6 @@ export class WorkerChoiceStrategiesContext< /** * Removes a worker choice strategy from the context. - * * @param workerChoiceStrategy - The worker choice strategy to remove. * @returns `true` if the worker choice strategy is removed, `false` otherwise. */ diff --git a/src/pools/thread/dynamic.ts b/src/pools/thread/dynamic.ts index 8e795512..0d088da1 100644 --- a/src/pools/thread/dynamic.ts +++ b/src/pools/thread/dynamic.ts @@ -7,7 +7,6 @@ import { FixedThreadPool, type ThreadPoolOptions } from './fixed.js' * * 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 structured-cloneable data. * @typeParam Response - Type of execution response. This can only be structured-cloneable data. * @author [Alessandro Pio Ardizio](https://github.com/pioardi) @@ -19,7 +18,6 @@ export class DynamicThreadPool< > extends FixedThreadPool { /** * Constructs a new poolifier dynamic thread pool. - * * @param min - Minimum number of threads which are always active. * @param max - Maximum number of threads that can be created by this pool. * @param filePath - Path to an implementation of a `ThreadWorker` file, which can be relative or absolute. diff --git a/src/pools/thread/fixed.ts b/src/pools/thread/fixed.ts index 7977cd61..69b3c307 100644 --- a/src/pools/thread/fixed.ts +++ b/src/pools/thread/fixed.ts @@ -1,7 +1,7 @@ import { isMainThread, type TransferListItem, - type Worker + type Worker, } from 'node:worker_threads' import type { MessageValue } from '../../utility-types.js' @@ -16,7 +16,6 @@ export type ThreadPoolOptions = PoolOptions /** * A thread pool with a fixed number of threads. - * * @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) @@ -28,10 +27,10 @@ export class FixedThreadPool< > extends AbstractPool { /** * Constructs a new poolifier fixed thread pool. - * * @param numberOfThreads - Number of threads for this pool. * @param filePath - Path to an implementation of a `ThreadWorker` file, which can be relative or absolute. * @param opts - Options for this fixed thread pool. + * @param maximumNumberOfThreads - The maximum number of threads for this pool. */ public constructor ( numberOfThreads: number, @@ -56,7 +55,7 @@ export class FixedThreadPool< this.workerNodes[workerNodeKey]?.messageChannel?.port1.postMessage( { ...message, - workerId: this.getWorkerInfo(workerNodeKey)?.id + workerId: this.getWorkerInfo(workerNodeKey)?.id, } satisfies MessageValue, transferList ) @@ -71,7 +70,7 @@ export class FixedThreadPool< { ready: false, workerId: this.getWorkerInfo(workerNodeKey)?.id, - port: port2 + port: port2, } satisfies MessageValue, [port2] ) diff --git a/src/pools/utils.ts b/src/pools/utils.ts index 3fa17312..24f2cfb2 100644 --- a/src/pools/utils.ts +++ b/src/pools/utils.ts @@ -4,7 +4,7 @@ import { env } from 'node:process' import { SHARE_ENV, Worker as ThreadWorker, - type WorkerOptions + type WorkerOptions, } from 'node:worker_threads' import type { MessageValue, Task } from '../utility-types.js' @@ -13,7 +13,7 @@ import type { TasksQueueOptions } from './pool.js' import { type MeasurementStatisticsRequirements, WorkerChoiceStrategies, - type WorkerChoiceStrategy + type WorkerChoiceStrategy, } from './selection-strategies/selection-strategies-types.js' import type { WorkerChoiceStrategiesContext } from './selection-strategies/worker-choice-strategies-context.js' import { @@ -23,7 +23,7 @@ import { type WorkerNodeOptions, type WorkerType, WorkerTypes, - type WorkerUsage + type WorkerUsage, } from './worker.js' /** @@ -33,7 +33,7 @@ export const DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS: MeasurementStatisticsR { aggregate: false, average: false, - median: false + median: false, } export const getDefaultTasksQueueOptions = ( @@ -43,8 +43,8 @@ export const getDefaultTasksQueueOptions = ( size: Math.pow(poolMaxSize, 2), concurrency: 1, taskStealing: true, - tasksStealingOnBackPressure: true, - tasksFinishedTimeout: 2000 + tasksStealingOnBackPressure: false, + tasksFinishedTimeout: 2000, } } @@ -89,7 +89,7 @@ export const checkDynamicPoolSize = ( export const checkValidPriority = (priority: number | undefined): void => { if (priority != null && !Number.isSafeInteger(priority)) { - throw new TypeError(`Invalid property 'priority': '${priority}'`) + throw new TypeError(`Invalid property 'priority': '${priority.toString()}'`) } if ( priority != null && @@ -130,7 +130,7 @@ export const checkValidTasksQueueOptions = ( tasksQueueOptions.concurrency <= 0 ) { throw new RangeError( - `Invalid worker node tasks concurrency: ${tasksQueueOptions.concurrency} is a negative integer or zero` + `Invalid worker node tasks concurrency: ${tasksQueueOptions.concurrency.toString()} is a negative integer or zero` ) } if ( @@ -143,7 +143,7 @@ export const checkValidTasksQueueOptions = ( } if (tasksQueueOptions?.size != null && tasksQueueOptions.size <= 0) { throw new RangeError( - `Invalid worker node tasks queue size: ${tasksQueueOptions.size} is a negative integer or zero` + `Invalid worker node tasks queue size: ${tasksQueueOptions.size.toString()} is a negative integer or zero` ) } } @@ -169,7 +169,7 @@ export const checkWorkerNodeArguments = ( } if (!isPlainObject(opts)) { throw new TypeError( - 'Cannot construct a worker node with invalid options: must be a plain object' + 'Cannot construct a worker node with invalid worker node options: must be a plain object' ) } if (opts.tasksQueueBackPressureSize == null) { @@ -187,11 +187,35 @@ export const checkWorkerNodeArguments = ( 'Cannot construct a worker node with a tasks queue back pressure size option that is not a positive integer' ) } + if (opts.tasksQueueBucketSize == null) { + throw new TypeError( + 'Cannot construct a worker node without a tasks queue bucket size option' + ) + } + if (!Number.isSafeInteger(opts.tasksQueueBucketSize)) { + throw new TypeError( + 'Cannot construct a worker node with a tasks queue bucket size option that is not an integer' + ) + } + if (opts.tasksQueueBucketSize <= 0) { + throw new RangeError( + 'Cannot construct a worker node with a tasks queue bucket size option that is not a positive integer' + ) + } + if (opts.tasksQueuePriority == null) { + throw new TypeError( + 'Cannot construct a worker node without a tasks queue priority option' + ) + } + if (typeof opts.tasksQueuePriority !== 'boolean') { + throw new TypeError( + 'Cannot construct a worker node with a tasks queue priority option that is not a boolean' + ) + } } /** * Updates the given measurement statistics. - * * @param measurementStatistics - The measurement statistics to update. * @param measurementRequirements - The measurement statistics requirements. * @param measurementValue - The measurement value. @@ -211,21 +235,25 @@ const updateMeasurementStatistics = ( (measurementStatistics.aggregate ?? 0) + measurementValue measurementStatistics.minimum = min( measurementValue, - measurementStatistics.minimum ?? Infinity + measurementStatistics.minimum ?? Number.POSITIVE_INFINITY ) measurementStatistics.maximum = max( measurementValue, - measurementStatistics.maximum ?? -Infinity + measurementStatistics.maximum ?? Number.NEGATIVE_INFINITY ) if (measurementRequirements.average || measurementRequirements.median) { - measurementStatistics.history.push(measurementValue) + measurementStatistics.history.put(measurementValue) if (measurementRequirements.average) { - measurementStatistics.average = average(measurementStatistics.history) + measurementStatistics.average = average( + measurementStatistics.history.toArray() + ) } else if (measurementStatistics.average != null) { delete measurementStatistics.average } if (measurementRequirements.median) { - measurementStatistics.median = median(measurementStatistics.history) + measurementStatistics.median = median( + measurementStatistics.history.toArray() + ) } else if (measurementStatistics.median != null) { delete measurementStatistics.median } @@ -242,7 +270,7 @@ export const updateWaitTimeWorkerUsage = < Data = unknown, Response = unknown >( - workerChoiceStrategyContext: + workerChoiceStrategiesContext: | WorkerChoiceStrategiesContext | undefined, workerUsage: WorkerUsage, @@ -252,7 +280,7 @@ export const updateWaitTimeWorkerUsage = < const taskWaitTime = timestamp - (task.timestamp ?? timestamp) updateMeasurementStatistics( workerUsage.waitTime, - workerChoiceStrategyContext?.getTaskStatisticsRequirements().waitTime, + workerChoiceStrategiesContext?.getTaskStatisticsRequirements().waitTime, taskWaitTime ) } @@ -281,7 +309,7 @@ export const updateRunTimeWorkerUsage = < Data = unknown, Response = unknown >( - workerChoiceStrategyContext: + workerChoiceStrategiesContext: | WorkerChoiceStrategiesContext | undefined, workerUsage: WorkerUsage, @@ -292,7 +320,7 @@ export const updateRunTimeWorkerUsage = < } updateMeasurementStatistics( workerUsage.runTime, - workerChoiceStrategyContext?.getTaskStatisticsRequirements().runTime, + workerChoiceStrategiesContext?.getTaskStatisticsRequirements().runTime, message.taskPerformance?.runTime ?? 0 ) } @@ -302,7 +330,7 @@ export const updateEluWorkerUsage = < Data = unknown, Response = unknown >( - workerChoiceStrategyContext: + workerChoiceStrategiesContext: | WorkerChoiceStrategiesContext | undefined, workerUsage: WorkerUsage, @@ -312,7 +340,7 @@ export const updateEluWorkerUsage = < return } const eluTaskStatisticsRequirements = - workerChoiceStrategyContext?.getTaskStatisticsRequirements().elu + workerChoiceStrategiesContext?.getTaskStatisticsRequirements().elu updateMeasurementStatistics( workerUsage.elu.active, eluTaskStatisticsRequirements, @@ -340,13 +368,13 @@ export const updateEluWorkerUsage = < export const createWorker = ( type: WorkerType, filePath: string, - opts: { env?: Record, workerOptions?: WorkerOptions } + opts: { env?: Record; workerOptions?: WorkerOptions } ): Worker => { switch (type) { case WorkerTypes.thread: return new ThreadWorker(filePath, { env: SHARE_ENV, - ...opts.workerOptions + ...opts.workerOptions, }) as unknown as Worker case WorkerTypes.cluster: return cluster.fork(opts.env) as unknown as Worker @@ -358,7 +386,6 @@ export const createWorker = ( /** * Returns the worker type of the given worker. - * * @param worker - The worker to get the type of. * @returns The worker type of the given worker. * @internal @@ -373,7 +400,6 @@ export const getWorkerType = (worker: IWorker): WorkerType | undefined => { /** * Returns the worker id of the given worker. - * * @param worker - The worker to get the id of. * @returns The worker id of the given worker. * @internal @@ -401,12 +427,20 @@ export const waitWorkerNodeEvents = async < resolve(events) return } - workerNode.on(workerNodeEvent, () => { - ++events - if (events === numberOfEventsToWait) { - resolve(events) - } - }) + switch (workerNodeEvent) { + case 'idle': + case 'backPressure': + case 'taskFinished': + workerNode.on(workerNodeEvent, () => { + ++events + if (events === numberOfEventsToWait) { + resolve(events) + } + }) + break + default: + throw new Error('Invalid worker node event') + } if (timeout >= 0) { setTimeout(() => { resolve(events) diff --git a/src/pools/version.ts b/src/pools/version.ts index 270a9db9..f4b6c49e 100644 --- a/src/pools/version.ts +++ b/src/pools/version.ts @@ -1 +1 @@ -export const version = '4.0.1' +export const version = '4.0.13' diff --git a/src/pools/worker-node.ts b/src/pools/worker-node.ts index 64400d9e..d29a6e32 100644 --- a/src/pools/worker-node.ts +++ b/src/pools/worker-node.ts @@ -1,7 +1,7 @@ import { EventEmitter } from 'node:events' import { MessageChannel } from 'node:worker_threads' -import { CircularArray } from '../circular-array.js' +import { CircularBuffer } from '../circular-buffer.js' import { PriorityQueue } from '../priority-queue.js' import type { Task } from '../utility-types.js' import { DEFAULT_TASK_NAME } from '../utils.js' @@ -9,23 +9,23 @@ import { checkWorkerNodeArguments, createWorker, getWorkerId, - getWorkerType + getWorkerType, } from './utils.js' import { type EventHandler, type IWorker, type IWorkerNode, + MeasurementHistorySize, type StrategyData, type WorkerInfo, type WorkerNodeOptions, type WorkerType, WorkerTypes, - type WorkerUsage + type WorkerUsage, } from './worker.js' /** * Worker node. - * * @typeParam Worker - Type of worker. * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. */ @@ -45,12 +45,11 @@ export class WorkerNode /** @inheritdoc */ public tasksQueueBackPressureSize: number private readonly tasksQueue: PriorityQueue> - private onBackPressureStarted: boolean + private setBackPressureFlag: boolean private readonly taskFunctionsUsage: Map /** * Constructs a new worker node. - * * @param type - The worker type. * @param filePath - Path to the worker file. * @param opts - The worker node options. @@ -60,7 +59,7 @@ export class WorkerNode checkWorkerNodeArguments(type, filePath, opts) this.worker = createWorker(type, filePath, { env: opts.env, - workerOptions: opts.workerOptions + workerOptions: opts.workerOptions, }) this.info = this.initWorkerInfo(this.worker) this.usage = this.initWorkerUsage() @@ -69,11 +68,19 @@ export class WorkerNode } // eslint-disable-next-line @typescript-eslint/no-non-null-assertion this.tasksQueueBackPressureSize = opts.tasksQueueBackPressureSize! - this.tasksQueue = new PriorityQueue>(opts.tasksQueueBucketSize) - this.onBackPressureStarted = false + this.tasksQueue = new PriorityQueue>( + opts.tasksQueueBucketSize, + opts.tasksQueuePriority + ) + this.setBackPressureFlag = false this.taskFunctionsUsage = new Map() } + /** @inheritdoc */ + public setTasksQueuePriority (enablePriority: boolean): void { + this.tasksQueue.enablePriority = enablePriority + } + /** @inheritdoc */ public tasksQueueSize (): number { return this.tasksQueue.size @@ -82,17 +89,38 @@ export class WorkerNode /** @inheritdoc */ public enqueueTask (task: Task): number { const tasksQueueSize = this.tasksQueue.enqueue(task, task.priority) - if (this.hasBackPressure() && !this.onBackPressureStarted) { - this.onBackPressureStarted = true + if ( + !this.setBackPressureFlag && + this.hasBackPressure() && + !this.info.backPressure + ) { + this.setBackPressureFlag = true + this.info.backPressure = true this.emit('backPressure', { workerId: this.info.id }) - this.onBackPressureStarted = false + this.setBackPressureFlag = false } return tasksQueueSize } /** @inheritdoc */ public dequeueTask (bucket?: number): Task | undefined { - return this.tasksQueue.dequeue(bucket) + const task = this.tasksQueue.dequeue(bucket) + if ( + !this.setBackPressureFlag && + !this.hasBackPressure() && + this.info.backPressure + ) { + this.setBackPressureFlag = true + this.info.backPressure = false + this.setBackPressureFlag = false + } + return task + } + + /** @inheritdoc */ + public dequeueLastPrioritizedTask (): Task | undefined { + // Start from the last empty or partially filled bucket + return this.dequeueTask(this.tasksQueue.buckets + 1) } /** @inheritdoc */ @@ -191,7 +219,8 @@ export class WorkerNode type: getWorkerType(worker)!, dynamic: false, ready: false, - stealing: false + stealing: false, + backPressure: false, } } @@ -214,22 +243,22 @@ export class WorkerNode }, sequentiallyStolen: 0, stolen: 0, - failed: 0 + failed: 0, }, runTime: { - history: new CircularArray() + history: new CircularBuffer(MeasurementHistorySize), }, waitTime: { - history: new CircularArray() + history: new CircularBuffer(MeasurementHistorySize), }, elu: { idle: { - history: new CircularArray() + history: new CircularBuffer(MeasurementHistorySize), }, active: { - history: new CircularArray() - } - } + history: new CircularBuffer(MeasurementHistorySize), + }, + }, } } @@ -257,22 +286,22 @@ export class WorkerNode }, sequentiallyStolen: 0, stolen: 0, - failed: 0 + failed: 0, }, runTime: { - history: new CircularArray() + history: new CircularBuffer(MeasurementHistorySize), }, waitTime: { - history: new CircularArray() + history: new CircularBuffer(MeasurementHistorySize), }, elu: { idle: { - history: new CircularArray() + history: new CircularBuffer(MeasurementHistorySize), }, active: { - history: new CircularArray() - } - } + history: new CircularBuffer(MeasurementHistorySize), + }, + }, } } } diff --git a/src/pools/worker.ts b/src/pools/worker.ts index 35d9f755..9f5fc0c1 100644 --- a/src/pools/worker.ts +++ b/src/pools/worker.ts @@ -1,19 +1,17 @@ import type { EventEmitter } from 'node:events' import type { MessageChannel, WorkerOptions } from 'node:worker_threads' -import type { CircularArray } from '../circular-array.js' +import type { CircularBuffer } from '../circular-buffer.js' import type { Task, TaskFunctionProperties } from '../utility-types.js' /** * Callback invoked when the worker has started successfully. - * * @typeParam Worker - Type of worker. */ export type OnlineHandler = (this: Worker) => void /** * Callback invoked if the worker has received a message. - * * @typeParam Worker - Type of worker. */ export type MessageHandler = ( @@ -23,7 +21,6 @@ export type MessageHandler = ( /** * Callback invoked if the worker raised an error. - * * @typeParam Worker - Type of worker. */ export type ErrorHandler = ( @@ -33,7 +30,6 @@ export type ErrorHandler = ( /** * Callback invoked when the worker exits successfully. - * * @typeParam Worker - Type of worker. */ export type ExitHandler = ( @@ -43,7 +39,6 @@ export type ExitHandler = ( /** * Worker event handler. - * * @typeParam Worker - Type of worker. */ export type EventHandler = @@ -52,9 +47,13 @@ export type EventHandler = | ErrorHandler | ExitHandler +/** + * Measurement history size. + */ +export const MeasurementHistorySize = 386 + /** * Measurement statistics. - * * @internal */ export interface MeasurementStatistics { @@ -81,12 +80,11 @@ export interface MeasurementStatistics { /** * Measurement history. */ - readonly history: CircularArray + readonly history: CircularBuffer } /** * Event loop utilization measurement statistics. - * * @internal */ export interface EventLoopUtilizationMeasurementStatistics { @@ -97,7 +95,6 @@ export interface EventLoopUtilizationMeasurementStatistics { /** * Task statistics. - * * @internal */ export interface TaskStatistics { @@ -134,10 +131,10 @@ export interface TaskStatistics { /** * Enumeration of worker types. */ -export const WorkerTypes: Readonly<{ thread: 'thread', cluster: 'cluster' }> = +export const WorkerTypes: Readonly<{ thread: 'thread'; cluster: 'cluster' }> = Object.freeze({ thread: 'thread', - cluster: 'cluster' + cluster: 'cluster', } as const) /** @@ -147,7 +144,6 @@ export type WorkerType = keyof typeof WorkerTypes /** * Worker information. - * * @internal */ export interface WorkerInfo { @@ -172,6 +168,11 @@ export interface WorkerInfo { * This flag is set to `true` when worker node is stealing tasks from another worker node. */ stealing: boolean + /** + * Back pressure flag. + * This flag is set to `true` when worker node tasks queue has back pressure. + */ + backPressure: boolean /** * Task functions properties. */ @@ -180,7 +181,6 @@ export interface WorkerInfo { /** * Worker usage statistics. - * * @internal */ export interface WorkerUsage { @@ -204,7 +204,6 @@ export interface WorkerUsage { /** * Worker choice strategy data. - * * @internal */ export interface StrategyData { @@ -225,14 +224,12 @@ export interface IWorker extends EventEmitter { readonly threadId?: number /** * Registers an event handler. - * * @param event - The event. * @param handler - The event handler. */ readonly on: (event: string, handler: EventHandler) => this /** * Registers once an event handler. - * * @param event - The event. * @param handler - The event handler. */ @@ -260,7 +257,6 @@ export interface IWorker extends EventEmitter { /** * Worker node options. - * * @internal */ export interface WorkerNodeOptions { @@ -268,11 +264,11 @@ export interface WorkerNodeOptions { env?: Record tasksQueueBackPressureSize: number | undefined tasksQueueBucketSize: number | undefined + tasksQueuePriority: boolean | undefined } /** * Worker node interface. - * * @typeParam Worker - Type of worker. * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. * @internal @@ -305,33 +301,39 @@ export interface IWorkerNode * This is the number of tasks that can be enqueued before the worker node has back pressure. */ tasksQueueBackPressureSize: number + /** + * Sets tasks queue priority. + * @param enablePriority - Whether to enable tasks queue priority. + */ + readonly setTasksQueuePriority: (enablePriority: boolean) => void /** * Tasks queue size. - * * @returns The tasks queue size. */ readonly tasksQueueSize: () => number /** * Enqueue task. - * * @param task - The task to queue. * @returns The tasks queue size. */ readonly enqueueTask: (task: Task) => number /** * Dequeue task. - * * @param bucket - The prioritized bucket to dequeue from. @defaultValue 0 * @returns The dequeued task. */ readonly dequeueTask: (bucket?: number) => Task | undefined + /** + * Dequeue last prioritized task. + * @returns The dequeued task. + */ + readonly dequeueLastPrioritizedTask: () => Task | undefined /** * Clears tasks queue. */ readonly clearTasksQueue: () => void /** * Whether the worker node has back pressure (i.e. its tasks queue is full). - * * @returns `true` if the worker node has back pressure, `false` otherwise. */ readonly hasBackPressure: () => boolean @@ -341,7 +343,6 @@ export interface IWorkerNode readonly terminate: () => Promise /** * Registers a worker event handler. - * * @param event - The event. * @param handler - The event handler. */ @@ -351,7 +352,6 @@ export interface IWorkerNode ) => void /** * Registers once a worker event handler. - * * @param event - The event. * @param handler - The event handler. */ @@ -361,14 +361,12 @@ export interface IWorkerNode ) => void /** * Gets task function worker usage statistics. - * * @param name - The task function name. * @returns The task function worker usage statistics if the task function worker usage statistics are initialized, `undefined` otherwise. */ readonly getTaskFunctionWorkerUsage: (name: string) => WorkerUsage | undefined /** * Deletes task function worker usage statistics. - * * @param name - The task function name. * @returns `true` if the task function worker usage statistics were deleted, `false` otherwise. */ @@ -377,7 +375,6 @@ export interface IWorkerNode /** * Worker node event detail. - * * @internal */ export interface WorkerNodeEventDetail { diff --git a/src/priority-queue.ts b/src/priority-queue.ts index 64b5a924..93e7b76d 100644 --- a/src/priority-queue.ts +++ b/src/priority-queue.ts @@ -1,159 +1,196 @@ // Copyright Jerome Benoit. 2024. All Rights Reserved. +import { FixedPriorityQueue } from './fixed-priority-queue.js' + +/** + * Default bucket size. + */ +export const defaultBucketSize = 2048 + /** * Priority queue node. - * * @typeParam T - Type of priority queue node data. * @internal */ -export interface PriorityQueueNode { - data: T - priority: number +export interface PriorityQueueNode extends FixedPriorityQueue { + next?: FixedPriorityQueue } /** * Priority queue. - * * @typeParam T - Type of priority queue data. * @internal */ export class PriorityQueue { - private nodeArray!: Array> - /** Prioritized bucket size. */ - private readonly k: number - /** The size of the priority queue. */ - public size!: number - /** The maximum size of the priority queue. */ + private head!: PriorityQueueNode + private tail!: PriorityQueueNode + private readonly bucketSize: number + /** The priority queue maximum size. */ public maxSize!: number /** * Constructs a priority queue. - * - * @param k - Prioritized bucket size. @defaultValue Infinity + * @param bucketSize - Prioritized bucket size. @defaultValue defaultBucketSize + * @param enablePriority - Whether to enable priority. @defaultValue false + * @returns PriorityQueue. + */ + public constructor ( + bucketSize: number = defaultBucketSize, + enablePriority = false + ) { + if (!Number.isSafeInteger(bucketSize)) { + throw new TypeError( + `Invalid bucket size: '${bucketSize.toString()}' is not an integer` + ) + } + if (bucketSize < 0) { + throw new RangeError(`Invalid bucket size: ${bucketSize.toString()} < 0`) + } + this.bucketSize = bucketSize + this.head = this.tail = new FixedPriorityQueue( + this.bucketSize, + enablePriority + ) + this.maxSize = 0 + } + + /** + * The priority queue size. */ - public constructor (k = Infinity) { - if (k !== Infinity && !Number.isSafeInteger(k)) { - throw new TypeError('k must be an integer') + public get size (): number { + let node: PriorityQueueNode | undefined = this.tail + let size = 0 + while (node != null) { + size += node.size + node = node.next + } + return size + } + + public get enablePriority (): boolean { + return this.head.enablePriority + } + + public set enablePriority (enablePriority: boolean) { + if (this.head.enablePriority === enablePriority) { + return } - if (k < 1) { - throw new RangeError('k must be greater than or equal to 1') + let node: PriorityQueueNode | undefined = this.tail + while (node != null) { + node.enablePriority = enablePriority + node = node.next } - this.k = k - this.clear() + } + + /** + * The number of filled prioritized buckets. + */ + public get buckets (): number { + return Math.trunc(this.size / this.bucketSize) } /** * Enqueue data into the priority queue. - * * @param data - Data to enqueue. * @param priority - Priority of the data. Lower values have higher priority. * @returns The new size of the priority queue. */ public enqueue (data: T, priority?: number): number { - priority = priority ?? 0 - const startIndex = - this.k === Infinity || this.nodeArray.length / this.k < 1 - ? 0 - : Math.trunc(this.nodeArray.length / this.k) * this.k - let inserted = false - for (let index = startIndex; index < this.nodeArray.length; index++) { - if (this.nodeArray[index].priority > priority) { - this.nodeArray.splice(index, 0, { data, priority }) - inserted = true - break - } + if (this.head.full()) { + this.head = this.head.next = new FixedPriorityQueue( + this.bucketSize, + this.enablePriority + ) } - if (!inserted) { - this.nodeArray.push({ data, priority }) + this.head.enqueue(data, priority) + const size = this.size + if (size > this.maxSize) { + this.maxSize = size } - return this.incrementSize() + return size } /** * Dequeue data from the priority queue. - * - * @param bucket - The prioritized bucket to dequeue from. @defaultValue 0 + * @param bucket - The prioritized bucket to dequeue from. * @returns The dequeued data or `undefined` if the priority queue is empty. */ - public dequeue (bucket = 0): T | undefined { - if (this.k !== Infinity && bucket > 0) { - while (bucket > 0) { - const index = bucket * this.k - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - if (this.nodeArray[index] != null) { - --this.size - return this.nodeArray.splice(index, 1)[0].data + public dequeue (bucket?: number): T | undefined { + let tail: PriorityQueueNode | undefined = this.tail + let tailChanged = false + if (bucket != null && bucket > 0) { + let currentBucket = 1 + while (tail != null) { + if (currentBucket === bucket) { + break } - --bucket + ++currentBucket + tail = tail.next + tailChanged = true } } - if (this.size > 0) { - --this.size + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const data = tail!.dequeue() + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + if (tail!.empty() && tail!.next != null) { + if (!tailChanged) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + this.tail = tail!.next + } else { + let node: PriorityQueueNode | undefined = this.tail + while (node != null) { + if (node.next === tail) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + node.next = tail!.next + break + } + node = node.next + } + } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + delete tail!.next } - return this.nodeArray.shift()?.data - } - - /** - * Peeks at the first data. - * @returns The first data or `undefined` if the priority queue is empty. - */ - public peekFirst (): T | undefined { - return this.nodeArray[0]?.data - } - - /** - * Peeks at the last data. - * @returns The last data or `undefined` if the priority queue is empty. - */ - public peekLast (): T | undefined { - return this.nodeArray[this.nodeArray.length - 1]?.data + return data } /** * Clears the priority queue. */ public clear (): void { - this.nodeArray = [] - this.size = 0 + this.head = this.tail = new FixedPriorityQueue( + this.bucketSize, + this.enablePriority + ) this.maxSize = 0 } /** * Returns an iterator for the priority queue. - * * @returns An iterator for the priority queue. * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols */ - [Symbol.iterator] (): Iterator { - let i = 0 + public [Symbol.iterator] (): Iterator { + let index = 0 + let node = this.tail return { next: () => { - if (i >= this.nodeArray.length) { + const value = node.get(index) as T + if (value == null) { return { value: undefined, - done: true + done: true, } } - const value = this.nodeArray[i].data - i++ + ++index + if (index === node.capacity && node.next != null) { + node = node.next + index = 0 + } return { value, - done: false + done: false, } - } - } - } - - /** - * Increments the size of the priority queue. - * - * @returns The new size of the priority queue. - */ - private incrementSize (): number { - ++this.size - if (this.size > this.maxSize) { - this.maxSize = this.size + }, } - return this.size } } diff --git a/src/utility-types.ts b/src/utility-types.ts index 82f79230..f13cce6a 100644 --- a/src/utility-types.ts +++ b/src/utility-types.ts @@ -7,7 +7,6 @@ import type { KillBehavior } from './worker/worker-options.js' /** * Worker error. - * * @typeParam Data - Type of data sent to the worker triggering an error. This can only be structured-cloneable data. */ export interface WorkerError { @@ -27,7 +26,6 @@ export interface WorkerError { /** * Task performance. - * * @internal */ export interface TaskPerformance { @@ -51,7 +49,6 @@ export interface TaskPerformance { /** * Worker task performance statistics computation settings. - * * @internal */ export interface WorkerStatistics { @@ -85,7 +82,6 @@ export interface TaskFunctionProperties { /** * 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 structured-cloneable data. * @internal */ @@ -100,7 +96,6 @@ export interface Task { readonly data?: Data /** * Task priority. Lower values have higher priority. - * * @defaultValue 0 */ readonly priority?: number @@ -124,7 +119,6 @@ export interface Task { /** * Message object that is passed between main worker and worker. - * * @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. * @internal @@ -190,7 +184,6 @@ export interface MessageValue /** * An object holding the task execution response promise resolve/reject callbacks. - * * @typeParam Response - Type of execution response. This can only be structured-cloneable data. * @internal */ diff --git a/src/utils.ts b/src/utils.ts index dd839bc4..b36eba27 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -20,7 +20,6 @@ export const EMPTY_FUNCTION: () => void = Object.freeze(() => { /** * Returns safe host OS optimized estimate of the default amount of parallelism a pool should use. * Always returns a value greater than zero. - * * @returns The host OS optimized maximum pool size. */ export const availableParallelism = (): number => { @@ -38,7 +37,6 @@ export const availableParallelism = (): number => { /** * Sleeps for the given amount of milliseconds. - * * @param ms - The amount of milliseconds to sleep. * @returns A promise that resolves after the given amount of milliseconds. * @internal @@ -51,7 +49,6 @@ export const sleep = async (ms: number): Promise => { /** * Computes the retry delay in milliseconds using an exponential back off algorithm. - * * @param retryNumber - The number of retries that have already been attempted * @param delayFactor - The base delay factor in milliseconds * @returns Delay in milliseconds @@ -68,7 +65,6 @@ export const exponentialDelay = ( /** * Computes the average of the given data set. - * * @param dataSet - Data set. * @returns The average of the given data set. * @internal @@ -87,7 +83,6 @@ export const average = (dataSet: number[]): number => { /** * Computes the median of the given data set. - * * @param dataSet - Data set. * @returns The median of the given data set. * @internal @@ -109,7 +104,6 @@ export const median = (dataSet: number[]): number => { /** * Rounds the given number to the given scale. * The rounding is done using the "round half away from zero" method. - * * @param num - The number to round. * @param scale - The scale to round to. * @returns The rounded number. @@ -122,7 +116,6 @@ export const round = (num: number, scale = 2): number => { /** * Is the given value a plain object? - * * @param value - The value to check. * @returns `true` if the given value is a plain object, `false` otherwise. * @internal @@ -135,7 +128,6 @@ export const isPlainObject = (value: unknown): value is object => /** * Detects whether the given value is a kill behavior or not. - * * @typeParam KB - Which specific KillBehavior type to test against. * @param killBehavior - Which kind of kill behavior to detect. * @param value - Unknown value. @@ -151,7 +143,6 @@ export const isKillBehavior = ( /** * Detects whether the given value is an asynchronous function or not. - * * @param fn - Unknown value. * @returns `true` if `fn` was an asynchronous function, otherwise `false`. * @internal @@ -164,7 +155,6 @@ export const isAsyncFunction = ( /** * Generates a cryptographically secure random number in the [0,1[ range - * * @returns A number in the [0,1[ range * @internal */ @@ -174,33 +164,35 @@ export const secureRandom = (): number => { /** * Returns the minimum of the given numbers. - * If no numbers are given, `Infinity` is returned. - * + * If no numbers are given, `Number.POSITIVE_INFINITY` is returned. * @param args - The numbers to get the minimum of. * @returns The minimum of the given numbers. * @internal */ export const min = (...args: number[]): number => - args.reduce((minimum, num) => (minimum < num ? minimum : num), Infinity) + args.reduce( + (minimum, num) => (minimum < num ? minimum : num), + Number.POSITIVE_INFINITY + ) /** * Returns the maximum of the given numbers. - * If no numbers are given, `-Infinity` is returned. - * + * If no numbers are given, `Number.NEGATIVE_INFINITY` is returned. * @param args - The numbers to get the maximum of. * @returns The maximum of the given numbers. * @internal */ export const max = (...args: number[]): number => - args.reduce((maximum, num) => (maximum > num ? maximum : num), -Infinity) + args.reduce( + (maximum, num) => (maximum > num ? maximum : num), + Number.NEGATIVE_INFINITY + ) /** * Wraps a function so that it can only be called once. - * * @param fn - The function to wrap. * @param context - The context to bind the function to. * @returns The wrapped function. - * * @typeParam A - The function's arguments. * @typeParam R - The function's return value. * @typeParam C - The function's context. @@ -230,10 +222,10 @@ export const buildTaskFunctionProperties = ( return { name, ...(taskFunctionObject?.priority != null && { - priority: taskFunctionObject.priority + priority: taskFunctionObject.priority, }), ...(taskFunctionObject?.strategy != null && { - strategy: taskFunctionObject.strategy - }) + strategy: taskFunctionObject.strategy, + }), } } diff --git a/src/worker/abstract-worker.ts b/src/worker/abstract-worker.ts index 2a5f1121..ec77ccab 100644 --- a/src/worker/abstract-worker.ts +++ b/src/worker/abstract-worker.ts @@ -7,14 +7,14 @@ import type { Task, TaskFunctionProperties, TaskPerformance, - WorkerStatistics + WorkerStatistics, } from '../utility-types.js' import { buildTaskFunctionProperties, DEFAULT_TASK_NAME, EMPTY_FUNCTION, isAsyncFunction, - isPlainObject + isPlainObject, } from '../utils.js' import type { TaskAsyncFunction, @@ -22,12 +22,12 @@ import type { TaskFunctionObject, TaskFunctionOperationResult, TaskFunctions, - TaskSyncFunction + TaskSyncFunction, } from './task-functions.js' import { checkTaskFunctionName, checkValidTaskFunctionObjectEntry, - checkValidWorkerOptions + checkValidWorkerOptions, } from './utils.js' import { KillBehaviors, type WorkerOptions } from './worker-options.js' @@ -45,12 +45,11 @@ const DEFAULT_WORKER_OPTIONS: WorkerOptions = { /** * The function to call when the worker is killed. */ - killHandler: EMPTY_FUNCTION + killHandler: EMPTY_FUNCTION, } /** * 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 structured-cloneable data. * @typeParam Response - Type of response the worker sends back to the main worker. This can only be structured-cloneable data. @@ -79,11 +78,11 @@ export abstract class AbstractWorker< /** * Handler id of the `activeInterval` worker activity check. */ + // eslint-disable-next-line no-undef protected activeInterval?: NodeJS.Timeout /** * Constructs a new poolifier worker. - * * @param isMain - Whether this is the main worker or not. * @param mainWorker - Reference to main worker. * @param taskFunctions - Task function(s) processed by the worker when the pool's `execution` function is invoked. The first function is the default function. @@ -113,14 +112,13 @@ export abstract class AbstractWorker< /** * Checks if the `taskFunctions` parameter is passed to the constructor and valid. - * * @param taskFunctions - The task function(s) parameter that should be checked. */ private checkTaskFunctions ( taskFunctions: - | TaskFunction - | TaskFunctions - | undefined + | TaskFunction + | TaskFunctions + | undefined ): void { if (taskFunctions == null) { throw new Error('taskFunctions parameter is mandatory') @@ -141,8 +139,8 @@ export abstract class AbstractWorker< for (let [name, fnObj] of Object.entries(taskFunctions)) { if (typeof fnObj === 'function') { fnObj = { taskFunction: fnObj } satisfies TaskFunctionObject< - Data, - Response + Data, + Response > } checkValidTaskFunctionObjectEntry(name, fnObj) @@ -165,7 +163,6 @@ export abstract class AbstractWorker< /** * Checks if the worker has a task function with the given name. - * * @param name - The name of the task function to check. * @returns Whether the worker has a task function with the given name or not. */ @@ -181,7 +178,6 @@ export abstract class AbstractWorker< /** * Adds a task function to the worker. * If a task function with the same name already exists, it is replaced. - * * @param name - The name of the task function to add. * @param fn - The task function to add. * @returns Whether the task function was added or not. @@ -218,7 +214,6 @@ export abstract class AbstractWorker< /** * Removes a task function from the worker. - * * @param name - The name of the task function to remove. * @returns Whether the task function existed and was removed or not. */ @@ -248,7 +243,6 @@ export abstract class AbstractWorker< /** * Lists the properties of the worker's task functions. - * * @returns The properties of the worker's task functions. */ public listTaskFunctionsProperties (): TaskFunctionProperties[] { @@ -278,13 +272,12 @@ export abstract class AbstractWorker< defaultTaskFunctionName, this.taskFunctions.get(defaultTaskFunctionName) ), - ...taskFunctionsProperties + ...taskFunctionsProperties, ] } /** * Sets the default task function to use in the worker. - * * @param name - The name of the task function to use as default task function. * @returns Whether the default task function was set or not. */ @@ -312,31 +305,37 @@ export abstract class AbstractWorker< /** * Handles the ready message sent by the main worker. - * * @param message - The ready message. */ protected abstract handleReadyMessage (message: MessageValue): void /** * Worker message listener. - * * @param message - The received message. */ protected messageListener (message: MessageValue): void { this.checkMessageWorkerId(message) - if (message.statistics != null) { + const { + statistics, + checkActive, + taskFunctionOperation, + taskId, + data, + kill, + } = message + if (statistics != null) { // Statistics message received - this.statistics = message.statistics - } else if (message.checkActive != null) { + this.statistics = statistics + } else if (checkActive != null) { // Check active message received - message.checkActive ? this.startCheckActive() : this.stopCheckActive() - } else if (message.taskFunctionOperation != null) { + checkActive ? this.startCheckActive() : this.stopCheckActive() + } else if (taskFunctionOperation != null) { // Task function operation message received this.handleTaskFunctionOperationMessage(message) - } else if (message.taskId != null && message.data != null) { + } else if (taskId != null && data != null) { // Task message received this.run(message) - } else if (message.kill === true) { + } else if (kill === true) { // Kill message received this.handleKillMessage(message) } @@ -358,14 +357,15 @@ export abstract class AbstractWorker< response = this.addTaskFunction(taskFunctionProperties.name, { // eslint-disable-next-line @typescript-eslint/no-implied-eval, no-new-func taskFunction: new Function( - `return ${taskFunction}` + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + `return ${taskFunction!}` )() as TaskFunction, ...(taskFunctionProperties.priority != null && { - priority: taskFunctionProperties.priority + priority: taskFunctionProperties.priority, }), ...(taskFunctionProperties.strategy != null && { - strategy: taskFunctionProperties.strategy - }) + strategy: taskFunctionProperties.strategy, + }), }) break case 'remove': @@ -386,21 +386,20 @@ export abstract class AbstractWorker< response.error != null && { workerError: { name: taskFunctionProperties.name, - message: this.handleError(response.error as Error | string) - } - }) + message: this.handleError(response.error as Error | string), + }, + }), }) } /** * Handles a kill message sent by the main worker. - * * @param message - The kill message. */ - protected handleKillMessage (_message: MessageValue): void { + protected handleKillMessage (message: MessageValue): void { this.stopCheckActive() if (isAsyncFunction(this.opts.killHandler)) { - (this.opts.killHandler() as Promise) + ;(this.opts.killHandler as () => Promise)() .then(() => { this.sendToMainWorker({ kill: 'success' }) return undefined @@ -410,8 +409,7 @@ export abstract class AbstractWorker< }) } else { try { - // eslint-disable-next-line @typescript-eslint/no-invalid-void-type - this.opts.killHandler?.() as void + ;(this.opts.killHandler as (() => void) | undefined)?.() this.sendToMainWorker({ kill: 'success' }) } catch { this.sendToMainWorker({ kill: 'failure' }) @@ -421,7 +419,6 @@ export abstract class AbstractWorker< /** * Check if the message worker id is set and matches the worker id. - * * @param message - The message to check. * @throws {@link https://nodejs.org/api/errors.html#class-error} If the message worker id is not set or does not match the worker id. */ @@ -430,7 +427,7 @@ export abstract class AbstractWorker< throw new Error('Message worker id is not set') } else if (message.workerId !== this.id) { throw new Error( - `Message worker id ${message.workerId} does not match the worker id ${this.id}` + `Message worker id ${message.workerId.toString()} does not match the worker id ${this.id.toString()}` ) } } @@ -470,7 +467,6 @@ export abstract class AbstractWorker< /** * Returns the main worker. - * * @returns Reference to the main worker. * @throws {@link https://nodejs.org/api/errors.html#class-error} If the main worker is not set. */ @@ -483,7 +479,6 @@ export abstract class AbstractWorker< /** * Sends a message to main worker. - * * @param message - The response message. */ protected abstract sendToMainWorker ( @@ -495,13 +490,12 @@ export abstract class AbstractWorker< */ protected sendTaskFunctionsPropertiesToMainWorker (): void { this.sendToMainWorker({ - taskFunctionsProperties: this.listTaskFunctionsProperties() + taskFunctionsProperties: this.listTaskFunctionsProperties(), }) } /** * Handles an error and convert it to a string so it can be sent back to the main worker. - * * @param error - The error raised by the worker. * @returns The error message. */ @@ -511,7 +505,6 @@ export abstract class AbstractWorker< /** * Runs the given task. - * * @param task - The task to execute. */ protected readonly run = (task: Task): void => { @@ -522,10 +515,11 @@ export abstract class AbstractWorker< workerError: { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion name: name!, - message: `Task function '${name}' not found`, - data + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + message: `Task function '${name!}' not found`, + data, }, - taskId + taskId, }) return } @@ -539,7 +533,6 @@ export abstract class AbstractWorker< /** * Runs the given task function synchronously. - * * @param fn - Task function that will be executed. * @param task - Input data for the task function. */ @@ -555,7 +548,7 @@ export abstract class AbstractWorker< this.sendToMainWorker({ data: res, taskPerformance, - taskId + taskId, }) } catch (error) { this.sendToMainWorker({ @@ -563,9 +556,9 @@ export abstract class AbstractWorker< // eslint-disable-next-line @typescript-eslint/no-non-null-assertion name: name!, message: this.handleError(error as Error | string), - data + data, }, - taskId + taskId, }) } finally { this.updateLastTaskTimestamp() @@ -574,7 +567,6 @@ export abstract class AbstractWorker< /** * Runs the given task function asynchronously. - * * @param fn - Task function that will be executed. * @param task - Input data for the task function. */ @@ -590,7 +582,7 @@ export abstract class AbstractWorker< this.sendToMainWorker({ data: res, taskPerformance, - taskId + taskId, }) return undefined }) @@ -600,9 +592,9 @@ export abstract class AbstractWorker< // eslint-disable-next-line @typescript-eslint/no-non-null-assertion name: name!, message: this.handleError(error as Error | string), - data + data, }, - taskId + taskId, }) }) .finally(() => { @@ -619,8 +611,8 @@ export abstract class AbstractWorker< name: name ?? DEFAULT_TASK_NAME, timestamp: performance.now(), ...(this.statistics.elu && { - elu: performance.eventLoopUtilization() - }) + elu: performance.eventLoopUtilization(), + }), } } @@ -633,11 +625,11 @@ export abstract class AbstractWorker< return { ...taskPerformance, ...(this.statistics.runTime && { - runTime: performance.now() - taskPerformance.timestamp + runTime: performance.now() - taskPerformance.timestamp, }), ...(this.statistics.elu && { - elu: performance.eventLoopUtilization(taskPerformance.elu) - }) + elu: performance.eventLoopUtilization(taskPerformance.elu), + }), } } diff --git a/src/worker/cluster-worker.ts b/src/worker/cluster-worker.ts index 847f2174..d9f6e647 100644 --- a/src/worker/cluster-worker.ts +++ b/src/worker/cluster-worker.ts @@ -13,7 +13,6 @@ import type { WorkerOptions } from './worker-options.js' * * 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 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) @@ -25,7 +24,6 @@ export class ClusterWorker< > extends AbstractWorker { /** * Constructs a new poolifier cluster worker. - * * @param taskFunctions - Task function(s) processed by the worker when the pool's `execution` function is invoked. * @param opts - Options for the worker. */ @@ -43,12 +41,12 @@ export class ClusterWorker< this.getMainWorker().on('message', this.messageListener.bind(this)) this.sendToMainWorker({ ready: true, - taskFunctionsProperties: this.listTaskFunctionsProperties() + taskFunctionsProperties: this.listTaskFunctionsProperties(), }) } catch { this.sendToMainWorker({ ready: false, - taskFunctionsProperties: this.listTaskFunctionsProperties() + taskFunctionsProperties: this.listTaskFunctionsProperties(), }) } } @@ -65,7 +63,7 @@ export class ClusterWorker< ): void => { this.getMainWorker().send({ ...message, - workerId: this.id + workerId: this.id, } satisfies MessageValue) } } diff --git a/src/worker/task-functions.ts b/src/worker/task-functions.ts index 0b3083c3..2fd951fb 100644 --- a/src/worker/task-functions.ts +++ b/src/worker/task-functions.ts @@ -2,10 +2,8 @@ import type { WorkerChoiceStrategy } from '../pools/selection-strategies/selecti /** * Task synchronous function that can be executed. - * * @param data - Data sent to the worker. * @returns Execution response. - * * @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. */ @@ -16,10 +14,8 @@ export type TaskSyncFunction = ( /** * Task asynchronous function that can be executed. * This function must return a promise. - * * @param data - Data sent to the worker. * @returns Execution response promise. - * * @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. */ @@ -30,7 +26,6 @@ export type TaskAsyncFunction = ( /** * Task 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 structured-cloneable data. * @typeParam Response - Type of execution response. This can only be structured-cloneable data. */ @@ -40,7 +35,6 @@ export type TaskFunction = /** * Task function object. - * * @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. */ @@ -63,13 +57,12 @@ export interface TaskFunctionObject { * Tasks functions that can be executed. * The key is the name of the task function or task function object. * The value is the task function or task function object. - * * @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, -TaskFunction | TaskFunctionObject + string, + TaskFunction | TaskFunctionObject > /** diff --git a/src/worker/thread-worker.ts b/src/worker/thread-worker.ts index bf8647c5..8057d6f3 100644 --- a/src/worker/thread-worker.ts +++ b/src/worker/thread-worker.ts @@ -2,7 +2,7 @@ import { isMainThread, type MessagePort, parentPort, - threadId + threadId, } from 'node:worker_threads' import type { MessageValue } from '../utility-types.js' @@ -18,7 +18,6 @@ import type { WorkerOptions } from './worker-options.js' * * 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 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) @@ -35,7 +34,6 @@ export class ThreadWorker< /** * Constructs a new poolifier thread worker. - * * @param taskFunctions - Task function(s) processed by the worker when the pool's `execution` function is invoked. * @param opts - Options for the worker. */ @@ -58,12 +56,12 @@ export class ThreadWorker< this.port.on('message', this.messageListener.bind(this)) this.sendToMainWorker({ ready: true, - taskFunctionsProperties: this.listTaskFunctionsProperties() + taskFunctionsProperties: this.listTaskFunctionsProperties(), }) } catch { this.sendToMainWorker({ ready: false, - taskFunctionsProperties: this.listTaskFunctionsProperties() + taskFunctionsProperties: this.listTaskFunctionsProperties(), }) } } @@ -87,13 +85,12 @@ export class ThreadWorker< ): void => { this.port?.postMessage({ ...message, - workerId: this.id + workerId: this.id, } satisfies MessageValue) } /** * @inheritDoc - * @override */ protected handleError (error: Error | string): string { return error as string diff --git a/src/worker/utils.ts b/src/worker/utils.ts index d0883893..59a0289b 100644 --- a/src/worker/utils.ts +++ b/src/worker/utils.ts @@ -1,6 +1,6 @@ import { checkValidPriority, - checkValidWorkerChoiceStrategy + checkValidWorkerChoiceStrategy, } from '../pools/utils.js' import { isPlainObject } from '../utils.js' import type { TaskFunctionObject } from './task-functions.js' diff --git a/src/worker/worker-options.ts b/src/worker/worker-options.ts index 7f9c6506..92761840 100644 --- a/src/worker/worker-options.ts +++ b/src/worker/worker-options.ts @@ -1,16 +1,16 @@ /** * Enumeration of kill behaviors. */ -export const KillBehaviors: Readonly<{ SOFT: 'SOFT', HARD: 'HARD' }> = +export const KillBehaviors: Readonly<{ SOFT: 'SOFT'; HARD: 'HARD' }> = Object.freeze({ /** - * If `currentTime - lastActiveTime` is greater than `maxInactiveTime` but a task is still executing or queued, then the worker **wont** be deleted. + * If `currentTime - lastActiveTime` is greater than `maxInactiveTime` but the worker is stealing tasks or a task is executing or queued, then the worker **wont** be deleted. */ SOFT: 'SOFT', /** - * If `currentTime - lastActiveTime` is greater than `maxInactiveTime` but a task is still executing or queued, then the worker will be deleted. + * If `currentTime - lastActiveTime` is greater than `maxInactiveTime` but the worker is stealing tasks or a task is executing or queued, then the worker will be deleted. */ - HARD: 'HARD' + HARD: 'HARD', } as const) /** @@ -30,11 +30,10 @@ export interface WorkerOptions { /** * `killBehavior` dictates if your worker will be deleted in case a task is active on it. * - * - SOFT: If `currentTime - lastActiveTime` is greater than `maxInactiveTime` but a task is still executing or queued, then the worker **won't** be deleted. - * - HARD: If `currentTime - lastActiveTime` is greater than `maxInactiveTime` but a task is still executing or queued, then the worker will be deleted. + * - SOFT: If `currentTime - lastActiveTime` is greater than `maxInactiveTime` but the worker is stealing tasks or a task is executing or queued, then the worker **won't** be deleted. + * - HARD: If `currentTime - lastActiveTime` is greater than `maxInactiveTime` but the worker is stealing tasks or a task is executing or queued, then the worker will be deleted. * * This option only apply to the newly created workers. - * * @defaultValue KillBehaviors.SOFT */ killBehavior?: KillBehavior @@ -45,15 +44,13 @@ export interface WorkerOptions { * The last active time of your worker will be updated when it terminates a task. * * - If `killBehavior` is set to `KillBehaviors.HARD` this value represents also the timeout for the tasks that you submit to the pool, - * when this timeout expires your tasks is interrupted before completion and removed. The worker is killed if is not part of the minimum size of the pool. + * when this timeout expires your tasks is interrupted before completion and removed. The worker is killed if is not part of the minimum size of the pool. * - If `killBehavior` is set to `KillBehaviors.SOFT` your tasks have no timeout and your workers will not be terminated until your task is completed. - * * @defaultValue 60000 */ maxInactiveTime?: number /** * The function to call when a worker is killed. - * * @defaultValue `() => {}` */ killHandler?: KillHandler diff --git a/tests/circular-array.test.mjs b/tests/circular-array.test.mjs deleted file mode 100644 index a6f2f693..00000000 --- a/tests/circular-array.test.mjs +++ /dev/null @@ -1,152 +0,0 @@ -import { expect } from 'expect' - -import { - CircularArray, - DEFAULT_CIRCULAR_ARRAY_SIZE -} from '../lib/circular-array.cjs' - -describe('Circular array test suite', () => { - it('Verify that circular array can be instantiated', () => { - const circularArray = new CircularArray() - expect(circularArray).toBeInstanceOf(CircularArray) - }) - - it('Verify circular array default size at instance creation', () => { - const circularArray = new CircularArray() - expect(circularArray.size).toBe(DEFAULT_CIRCULAR_ARRAY_SIZE) - }) - - it('Verify that circular array size can be set at instance creation', () => { - const circularArray = new CircularArray(1000) - expect(circularArray.size).toBe(1000) - }) - - it('Verify that circular array size and items can be set at instance creation', () => { - let circularArray = new CircularArray(1000, 1, 2, 3, 4, 5) - expect(circularArray.size).toBe(1000) - expect(circularArray.length).toBe(5) - circularArray = new CircularArray(4, 1, 2, 3, 4, 5) - expect(circularArray.size).toBe(4) - expect(circularArray.length).toBe(4) - }) - - it('Verify that circular array size is valid at instance creation', () => { - expect(() => new CircularArray(0.25)).toThrow( - new TypeError('Invalid circular array size: 0.25 is not a safe integer') - ) - expect(() => new CircularArray(-1)).toThrow( - new RangeError('Invalid circular array size: -1 < 0') - ) - expect(() => new CircularArray(Number.MAX_SAFE_INTEGER + 1)).toThrow( - new TypeError( - `Invalid circular array size: ${ - Number.MAX_SAFE_INTEGER + 1 - } is not a safe integer` - ) - ) - }) - - it('Verify that circular array empty works as intended', () => { - const circularArray = new CircularArray() - expect(circularArray.empty()).toBe(true) - }) - - it('Verify that circular array full works as intended', () => { - const circularArray = new CircularArray(5, 1, 2, 3, 4, 5) - expect(circularArray.full()).toBe(true) - }) - - it('Verify that circular array push works as intended', () => { - let circularArray = new CircularArray(4) - let arrayLength = circularArray.push(1, 2, 3, 4, 5) - expect(arrayLength).toBe(circularArray.size) - expect(circularArray.length).toBe(circularArray.size) - expect(circularArray).toStrictEqual(new CircularArray(4, 2, 3, 4, 5)) - arrayLength = circularArray.push(6, 7) - expect(arrayLength).toBe(circularArray.size) - expect(circularArray.length).toBe(circularArray.size) - expect(circularArray).toStrictEqual(new CircularArray(4, 4, 5, 6, 7)) - circularArray = new CircularArray(100) - arrayLength = circularArray.push(1, 2, 3, 4, 5) - expect(arrayLength).toBe(5) - expect(circularArray.size).toBe(100) - expect(circularArray.length).toBe(5) - expect(circularArray).toStrictEqual(new CircularArray(100, 1, 2, 3, 4, 5)) - }) - - it('Verify that circular array splice works as intended', () => { - let circularArray = new CircularArray(1000, 1, 2, 3, 4, 5) - let deletedItems = circularArray.splice(2) - expect(deletedItems).toStrictEqual(new CircularArray(3, 3, 4, 5)) - expect(circularArray.length).toBe(2) - expect(circularArray).toStrictEqual(new CircularArray(1000, 1, 2)) - circularArray = new CircularArray(1000, 1, 2, 3, 4, 5) - deletedItems = circularArray.splice(2, 1) - expect(deletedItems).toStrictEqual(new CircularArray(1, 3)) - expect(circularArray.length).toBe(4) - expect(circularArray).toStrictEqual(new CircularArray(1000, 1, 2, 4, 5)) - circularArray = new CircularArray(4, 1, 2, 3, 4) - deletedItems = circularArray.splice(2, 1, 5, 6) - expect(deletedItems).toStrictEqual(new CircularArray(2, 3, 1)) - expect(circularArray.length).toBe(4) - expect(circularArray).toStrictEqual(new CircularArray(4, 2, 5, 6, 4)) - }) - - it('Verify that circular array concat works as intended', () => { - let circularArray = new CircularArray(5, 1, 2, 3, 4, 5) - circularArray = circularArray.concat(6, 7) - expect(circularArray.length).toBe(5) - expect(circularArray).toStrictEqual(new CircularArray(5, 3, 4, 5, 6, 7)) - circularArray = new CircularArray(1) - circularArray = circularArray.concat(6, 7) - expect(circularArray.length).toBe(1) - expect(circularArray).toStrictEqual(new CircularArray(1, 7)) - }) - - it('Verify that circular array unshift works as intended', () => { - let circularArray = new CircularArray(5, 1, 2, 3, 4, 5) - let arrayLength = circularArray.unshift(6, 7) - expect(arrayLength).toBe(5) - expect(circularArray.length).toBe(5) - expect(circularArray).toStrictEqual(new CircularArray(5, 6, 7, 1, 2, 3)) - circularArray = new CircularArray(1) - arrayLength = circularArray.unshift(6, 7) - expect(arrayLength).toBe(1) - expect(circularArray.length).toBe(1) - expect(circularArray).toStrictEqual(new CircularArray(1, 6)) - }) - - it('Verify that circular array resize works as intended', () => { - expect(() => new CircularArray().resize(0.25)).toThrow( - new TypeError('Invalid circular array size: 0.25 is not a safe integer') - ) - expect(() => new CircularArray().resize(-1)).toThrow( - new RangeError('Invalid circular array size: -1 < 0') - ) - expect(() => - new CircularArray().resize(Number.MAX_SAFE_INTEGER + 1) - ).toThrow( - new TypeError( - `Invalid circular array size: ${ - Number.MAX_SAFE_INTEGER + 1 - } is not a safe integer` - ) - ) - let circularArray = new CircularArray(5, 1, 2, 3, 4, 5) - circularArray.resize(0) - expect(circularArray.size).toBe(0) - expect(circularArray).toStrictEqual(new CircularArray(0)) - circularArray = new CircularArray(5, 1, 2, 3, 4, 5) - circularArray.resize(1) - expect(circularArray.size).toBe(1) - expect(circularArray).toStrictEqual(new CircularArray(1, 1)) - circularArray = new CircularArray(5, 1, 2, 3, 4, 5) - circularArray.resize(3) - expect(circularArray.size).toBe(3) - expect(circularArray).toStrictEqual(new CircularArray(3, 1, 2, 3)) - circularArray = new CircularArray(5, 1, 2, 3, 4, 5) - circularArray.resize(8) - expect(circularArray.size).toBe(8) - expect(circularArray).toStrictEqual(new CircularArray(8, 1, 2, 3, 4, 5)) - }) -}) diff --git a/tests/circular-buffer.test.mjs b/tests/circular-buffer.test.mjs new file mode 100644 index 00000000..751ece90 --- /dev/null +++ b/tests/circular-buffer.test.mjs @@ -0,0 +1,159 @@ +import { expect } from 'expect' + +import { CircularBuffer, defaultBufferSize } from '../lib/circular-buffer.cjs' + +describe('Circular buffer test suite', () => { + it('Verify that circular buffer can be instantiated', () => { + const circularBuffer = new CircularBuffer() + expect(circularBuffer).toBeInstanceOf(CircularBuffer) + expect(circularBuffer.readIdx).toBe(0) + expect(circularBuffer.writeIdx).toBe(0) + expect(circularBuffer.maxArrayIdx).toBe(defaultBufferSize - 1) + expect(circularBuffer.size).toBe(0) + expect(circularBuffer.items).toBeInstanceOf(Float32Array) + expect(circularBuffer.items.length).toBe(defaultBufferSize) + }) + + it('Verify that circular buffer size can be set at instance creation', () => { + const size = 1000 + const circularBuffer = new CircularBuffer(size) + expect(circularBuffer.maxArrayIdx).toBe(size - 1) + expect(circularBuffer.items).toBeInstanceOf(Float32Array) + expect(circularBuffer.items.length).toBe(size) + }) + + it('Verify that circular buffer size is valid at instance creation', () => { + expect(() => new CircularBuffer(0.25)).toThrow( + new TypeError("Invalid circular buffer size: '0.25' is not an integer") + ) + expect(() => new CircularBuffer(-1)).toThrow( + new RangeError('Invalid circular buffer size: -1 < 0') + ) + expect(() => new CircularBuffer(Number.MAX_SAFE_INTEGER + 1)).toThrow( + new TypeError( + `Invalid circular buffer size: '${ + Number.MAX_SAFE_INTEGER + 1 + }' is not an integer` + ) + ) + }) + + it('Verify that circular buffer put() works as intended', () => { + const circularBuffer = new CircularBuffer(4) + circularBuffer.put(1) + expect(circularBuffer.items).toStrictEqual( + new Float32Array([1, -1, -1, -1]) + ) + expect(circularBuffer.writeIdx).toBe(1) + expect(circularBuffer.size).toBe(1) + circularBuffer.put(2) + expect(circularBuffer.items).toStrictEqual(new Float32Array([1, 2, -1, -1])) + expect(circularBuffer.writeIdx).toBe(2) + expect(circularBuffer.size).toBe(2) + circularBuffer.put(3) + expect(circularBuffer.items).toStrictEqual(new Float32Array([1, 2, 3, -1])) + expect(circularBuffer.writeIdx).toBe(3) + expect(circularBuffer.size).toBe(3) + circularBuffer.put(4) + expect(circularBuffer.items).toStrictEqual(new Float32Array([1, 2, 3, 4])) + expect(circularBuffer.writeIdx).toBe(0) + expect(circularBuffer.size).toBe(4) + circularBuffer.put(5) + expect(circularBuffer.items).toStrictEqual(new Float32Array([5, 2, 3, 4])) + expect(circularBuffer.writeIdx).toBe(1) + expect(circularBuffer.size).toBe(4) + circularBuffer.put(6) + expect(circularBuffer.items).toStrictEqual(new Float32Array([5, 6, 3, 4])) + expect(circularBuffer.writeIdx).toBe(2) + expect(circularBuffer.size).toBe(4) + }) + + it('Verify that circular buffer get() works as intended', () => { + const circularBuffer = new CircularBuffer(4) + circularBuffer.put(1) + circularBuffer.put(2) + circularBuffer.put(3) + circularBuffer.put(4) + expect(circularBuffer.get()).toBe(1) + expect(circularBuffer.readIdx).toBe(1) + expect(circularBuffer.size).toBe(3) + expect(circularBuffer.get()).toBe(2) + expect(circularBuffer.readIdx).toBe(2) + expect(circularBuffer.size).toBe(2) + circularBuffer.put(5) + circularBuffer.put(6) + expect(circularBuffer.get()).toBe(3) + expect(circularBuffer.readIdx).toBe(3) + expect(circularBuffer.size).toBe(3) + expect(circularBuffer.get()).toBe(4) + expect(circularBuffer.readIdx).toBe(0) + expect(circularBuffer.size).toBe(2) + expect(circularBuffer.get()).toBe(5) + expect(circularBuffer.readIdx).toBe(1) + expect(circularBuffer.size).toBe(1) + expect(circularBuffer.get()).toBe(6) + expect(circularBuffer.readIdx).toBe(2) + expect(circularBuffer.size).toBe(0) + expect(circularBuffer.get()).toBe(undefined) + expect(circularBuffer.readIdx).toBe(2) + expect(circularBuffer.size).toBe(0) + }) + + it('Verify that circular buffer empty() works as intended', () => { + const circularBuffer = new CircularBuffer(4) + expect(circularBuffer.empty()).toBe(true) + circularBuffer.put(1) + expect(circularBuffer.empty()).toBe(false) + circularBuffer.put(2) + expect(circularBuffer.empty()).toBe(false) + circularBuffer.put(3) + expect(circularBuffer.empty()).toBe(false) + circularBuffer.put(4) + expect(circularBuffer.empty()).toBe(false) + circularBuffer.get() + expect(circularBuffer.empty()).toBe(false) + circularBuffer.get() + expect(circularBuffer.empty()).toBe(false) + circularBuffer.get() + expect(circularBuffer.empty()).toBe(false) + circularBuffer.get() + expect(circularBuffer.empty()).toBe(true) + }) + + it('Verify that circular buffer full() works as intended', () => { + const circularBuffer = new CircularBuffer(4) + expect(circularBuffer.full()).toBe(false) + circularBuffer.put(1) + expect(circularBuffer.full()).toBe(false) + circularBuffer.put(2) + expect(circularBuffer.full()).toBe(false) + circularBuffer.put(3) + expect(circularBuffer.full()).toBe(false) + circularBuffer.put(4) + expect(circularBuffer.full()).toBe(true) + circularBuffer.get() + expect(circularBuffer.full()).toBe(false) + circularBuffer.put(5) + expect(circularBuffer.full()).toBe(true) + circularBuffer.get() + expect(circularBuffer.full()).toBe(false) + circularBuffer.get() + expect(circularBuffer.full()).toBe(false) + circularBuffer.get() + expect(circularBuffer.full()).toBe(false) + circularBuffer.get() + expect(circularBuffer.full()).toBe(false) + expect(circularBuffer.empty()).toBe(true) + }) + + it('Verify that circular buffer toArray() works as intended', () => { + const circularBuffer = new CircularBuffer(4) + circularBuffer.put(1) + circularBuffer.put(2) + circularBuffer.put(3) + circularBuffer.put(4) + circularBuffer.put(5) + circularBuffer.put(6) + expect(circularBuffer.toArray()).toStrictEqual([5, 6, 3, 4]) + }) +}) diff --git a/tests/fixed-priority-queue.test.mjs b/tests/fixed-priority-queue.test.mjs new file mode 100644 index 00000000..40b55643 --- /dev/null +++ b/tests/fixed-priority-queue.test.mjs @@ -0,0 +1,204 @@ +import { expect } from 'expect' + +import { + defaultQueueSize, + FixedPriorityQueue, +} from '../lib/fixed-priority-queue.cjs' + +describe('Fixed priority queue test suite', () => { + it('Verify constructor() behavior', () => { + expect(() => new FixedPriorityQueue('')).toThrow( + new TypeError("Invalid fixed priority queue size: '' is not an integer") + ) + expect(() => new FixedPriorityQueue(-1)).toThrow( + new RangeError('Invalid fixed priority queue size: -1 < 0') + ) + let fixedPriorityQueue = new FixedPriorityQueue() + expect(fixedPriorityQueue.start).toBe(0) + expect(fixedPriorityQueue.size).toBe(0) + expect(fixedPriorityQueue.nodeArray).toBeInstanceOf(Array) + expect(fixedPriorityQueue.capacity).toBe(defaultQueueSize) + expect(fixedPriorityQueue.enablePriority).toBe(false) + fixedPriorityQueue = new FixedPriorityQueue(2, true) + expect(fixedPriorityQueue.start).toBe(0) + expect(fixedPriorityQueue.size).toBe(0) + expect(fixedPriorityQueue.nodeArray).toBeInstanceOf(Array) + expect(fixedPriorityQueue.capacity).toBe(2) + expect(fixedPriorityQueue.enablePriority).toBe(true) + }) + + it('Verify enqueue() behavior', () => { + const queueSize = 5 + const fixedPriorityQueue = new FixedPriorityQueue(queueSize, true) + let rtSize = fixedPriorityQueue.enqueue(1) + expect(fixedPriorityQueue.start).toBe(0) + expect(fixedPriorityQueue.size).toBe(1) + expect(rtSize).toBe(fixedPriorityQueue.size) + expect(fixedPriorityQueue.nodeArray).toMatchObject([ + { data: 1, priority: 0 }, + ]) + expect(fixedPriorityQueue.capacity).toBe(queueSize) + rtSize = fixedPriorityQueue.enqueue(2) + expect(fixedPriorityQueue.start).toBe(0) + expect(fixedPriorityQueue.size).toBe(2) + expect(rtSize).toBe(fixedPriorityQueue.size) + expect(fixedPriorityQueue.nodeArray).toMatchObject([ + { data: 1, priority: 0 }, + { data: 2, priority: 0 }, + ]) + expect(fixedPriorityQueue.capacity).toBe(queueSize) + rtSize = fixedPriorityQueue.enqueue(3) + expect(fixedPriorityQueue.start).toBe(0) + expect(fixedPriorityQueue.size).toBe(3) + expect(rtSize).toBe(fixedPriorityQueue.size) + expect(fixedPriorityQueue.nodeArray).toMatchObject([ + { data: 1, priority: 0 }, + { data: 2, priority: 0 }, + { data: 3, priority: 0 }, + ]) + expect(fixedPriorityQueue.capacity).toBe(queueSize) + rtSize = fixedPriorityQueue.enqueue(3, -1) + expect(fixedPriorityQueue.start).toBe(0) + expect(fixedPriorityQueue.size).toBe(4) + expect(rtSize).toBe(fixedPriorityQueue.size) + expect(fixedPriorityQueue.nodeArray).toMatchObject([ + { data: 3, priority: -1 }, + { data: 1, priority: 0 }, + { data: 2, priority: 0 }, + { data: 3, priority: 0 }, + ]) + expect(fixedPriorityQueue.capacity).toBe(queueSize) + rtSize = fixedPriorityQueue.enqueue(1, 1) + expect(fixedPriorityQueue.start).toBe(0) + expect(fixedPriorityQueue.size).toBe(5) + expect(rtSize).toBe(fixedPriorityQueue.size) + expect(fixedPriorityQueue.nodeArray).toMatchObject([ + { data: 3, priority: -1 }, + { data: 1, priority: 0 }, + { data: 2, priority: 0 }, + { data: 3, priority: 0 }, + { data: 1, priority: 1 }, + ]) + expect(fixedPriorityQueue.capacity).toBe(queueSize) + expect(() => fixedPriorityQueue.enqueue(4)).toThrow( + new Error('Priority queue is full') + ) + }) + + it('Verify get() behavior', () => { + const fixedPriorityQueue = new FixedPriorityQueue(defaultQueueSize, true) + fixedPriorityQueue.enqueue(1) + fixedPriorityQueue.enqueue(2, -1) + fixedPriorityQueue.enqueue(3) + expect(fixedPriorityQueue.get(0)).toBe(2) + expect(fixedPriorityQueue.get(1)).toBe(1) + expect(fixedPriorityQueue.get(2)).toBe(3) + expect(fixedPriorityQueue.get(3)).toBe(undefined) + }) + + it('Verify dequeue() behavior', () => { + const queueSize = 5 + const fixedPriorityQueue = new FixedPriorityQueue(queueSize, true) + fixedPriorityQueue.enqueue(1) + fixedPriorityQueue.enqueue(2, -1) + fixedPriorityQueue.enqueue(3) + expect(fixedPriorityQueue.start).toBe(0) + expect(fixedPriorityQueue.size).toBe(3) + expect(fixedPriorityQueue.capacity).toBe(queueSize) + let rtItem = fixedPriorityQueue.dequeue() + expect(fixedPriorityQueue.start).toBe(1) + expect(fixedPriorityQueue.size).toBe(2) + expect(rtItem).toBe(2) + expect(fixedPriorityQueue.nodeArray).toMatchObject([ + { data: 2, priority: -1 }, + { data: 1, priority: 0 }, + { data: 3, priority: 0 }, + ]) + expect(fixedPriorityQueue.capacity).toBe(queueSize) + rtItem = fixedPriorityQueue.dequeue() + expect(fixedPriorityQueue.start).toBe(2) + expect(fixedPriorityQueue.size).toBe(1) + expect(rtItem).toBe(1) + expect(fixedPriorityQueue.nodeArray).toMatchObject([ + { data: 2, priority: -1 }, + { data: 1, priority: 0 }, + { data: 3, priority: 0 }, + ]) + expect(fixedPriorityQueue.capacity).toBe(queueSize) + rtItem = fixedPriorityQueue.dequeue() + expect(fixedPriorityQueue.start).toBe(3) + expect(fixedPriorityQueue.size).toBe(0) + expect(rtItem).toBe(3) + expect(fixedPriorityQueue.nodeArray).toMatchObject([ + { data: 2, priority: -1 }, + { data: 1, priority: 0 }, + { data: 3, priority: 0 }, + ]) + expect(fixedPriorityQueue.capacity).toBe(queueSize) + rtItem = fixedPriorityQueue.dequeue() + expect(fixedPriorityQueue.start).toBe(3) + expect(fixedPriorityQueue.size).toBe(0) + expect(rtItem).toBe(undefined) + expect(fixedPriorityQueue.nodeArray).toMatchObject([ + { data: 2, priority: -1 }, + { data: 1, priority: 0 }, + { data: 3, priority: 0 }, + ]) + expect(fixedPriorityQueue.capacity).toBe(queueSize) + }) + + it('Verify iterator behavior', () => { + const fixedPriorityQueue = new FixedPriorityQueue() + fixedPriorityQueue.enqueue(1) + fixedPriorityQueue.enqueue(2) + fixedPriorityQueue.enqueue(3) + let i = fixedPriorityQueue.start + 1 + for (const value of fixedPriorityQueue) { + expect(value).toBe(i) + ++i + } + fixedPriorityQueue.dequeue() + i = fixedPriorityQueue.start + 1 + for (const value of fixedPriorityQueue) { + expect(value).toBe(i) + ++i + } + }) + + it('Verify empty() behavior', () => { + const fixedPriorityQueue = new FixedPriorityQueue() + expect(fixedPriorityQueue.empty()).toBe(true) + fixedPriorityQueue.enqueue(1) + expect(fixedPriorityQueue.empty()).toBe(false) + fixedPriorityQueue.dequeue() + expect(fixedPriorityQueue.empty()).toBe(true) + }) + + it('Verify full() behavior', () => { + const fixedPriorityQueue = new FixedPriorityQueue(2) + expect(fixedPriorityQueue.full()).toBe(false) + fixedPriorityQueue.enqueue(1) + expect(fixedPriorityQueue.full()).toBe(false) + fixedPriorityQueue.enqueue(2) + expect(fixedPriorityQueue.full()).toBe(true) + fixedPriorityQueue.dequeue() + expect(fixedPriorityQueue.full()).toBe(false) + }) + + it('Verify clear() behavior', () => { + const fixedPriorityQueue = new FixedPriorityQueue() + fixedPriorityQueue.start = 1 + fixedPriorityQueue.size = 2 + fixedPriorityQueue.nodeArray = [ + { data: 2, priority: 0 }, + { data: 3, priority: 0 }, + ] + fixedPriorityQueue.clear() + expect(fixedPriorityQueue.start).toBe(0) + expect(fixedPriorityQueue.size).toBe(0) + expect(fixedPriorityQueue.nodeArray).toMatchObject([ + { data: 2, priority: 0 }, + { data: 3, priority: 0 }, + ]) + }) +}) diff --git a/tests/pools/abstract-pool.test.mjs b/tests/pools/abstract-pool.test.mjs index 42e2959b..ec481d2c 100644 --- a/tests/pools/abstract-pool.test.mjs +++ b/tests/pools/abstract-pool.test.mjs @@ -8,7 +8,7 @@ import { fileURLToPath } from 'node:url' import { expect } from 'expect' import { restore, stub } from 'sinon' -import { CircularArray } from '../../lib/circular-array.cjs' +import { CircularBuffer } from '../../lib/circular-buffer.cjs' import { DynamicClusterPool, DynamicThreadPool, @@ -17,10 +17,10 @@ import { PoolEvents, PoolTypes, WorkerChoiceStrategies, - WorkerTypes + WorkerTypes, } from '../../lib/index.cjs' import { WorkerNode } from '../../lib/pools/worker-node.cjs' -import { PriorityQueue } from '../../lib/priority-queue.cjs' +import { defaultBucketSize, PriorityQueue } from '../../lib/priority-queue.cjs' import { DEFAULT_TASK_NAME } from '../../lib/utils.cjs' import { waitPoolEvents } from '../test-utils.cjs' @@ -58,7 +58,7 @@ describe('Abstract pool test suite', () => { numberOfWorkers, './tests/worker-files/thread/testWorker.mjs', { - errorHandler: e => console.error(e) + errorHandler: e => console.error(e), } ) ).toThrow( @@ -230,7 +230,7 @@ describe('Abstract pool test suite', () => { enableEvents: true, restartWorkerOnError: true, enableTasksQueue: false, - workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN + workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN, }) for (const [, workerChoiceStrategy] of pool.workerChoiceStrategiesContext .workerChoiceStrategies) { @@ -240,8 +240,8 @@ describe('Abstract pool test suite', () => { elu: { median: false }, weights: expect.objectContaining({ 0: expect.any(Number), - [pool.info.maxSize - 1]: expect.any(Number) - }) + [pool.info.maxSize - 1]: expect.any(Number), + }), }) } await pool.destroy() @@ -253,7 +253,7 @@ describe('Abstract pool test suite', () => { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_USED, workerChoiceStrategyOptions: { runTime: { median: true }, - weights: { 0: 300, 1: 200 } + weights: { 0: 300, 1: 200 }, }, enableEvents: false, restartWorkerOnError: false, @@ -262,7 +262,7 @@ describe('Abstract pool test suite', () => { messageHandler: testHandler, errorHandler: testHandler, onlineHandler: testHandler, - exitHandler: testHandler + exitHandler: testHandler, } ) expect(pool.emitter).toBeUndefined() @@ -275,18 +275,18 @@ describe('Abstract pool test suite', () => { concurrency: 2, size: Math.pow(numberOfWorkers, 2), taskStealing: true, - tasksStealingOnBackPressure: true, - tasksFinishedTimeout: 2000 + tasksStealingOnBackPressure: false, + tasksFinishedTimeout: 2000, }, workerChoiceStrategy: WorkerChoiceStrategies.LEAST_USED, workerChoiceStrategyOptions: { runTime: { median: true }, - weights: { 0: 300, 1: 200 } + weights: { 0: 300, 1: 200 }, }, onlineHandler: testHandler, messageHandler: testHandler, errorHandler: testHandler, - exitHandler: testHandler + exitHandler: testHandler, }) for (const [, workerChoiceStrategy] of pool.workerChoiceStrategiesContext .workerChoiceStrategies) { @@ -294,7 +294,7 @@ describe('Abstract pool test suite', () => { runTime: { median: true }, waitTime: { median: false }, elu: { median: false }, - weights: { 0: 300, 1: 200 } + weights: { 0: 300, 1: 200 }, }) } await pool.destroy() @@ -307,7 +307,7 @@ describe('Abstract pool test suite', () => { numberOfWorkers, './tests/worker-files/thread/testWorker.mjs', { - workerChoiceStrategy: 'invalidStrategy' + workerChoiceStrategy: 'invalidStrategy', } ) ).toThrow(new Error("Invalid worker choice strategy 'invalidStrategy'")) @@ -317,7 +317,7 @@ describe('Abstract pool test suite', () => { numberOfWorkers, './tests/worker-files/thread/testWorker.mjs', { - workerChoiceStrategyOptions: { weights: {} } + workerChoiceStrategyOptions: { weights: {} }, } ) ).toThrow( @@ -331,7 +331,7 @@ describe('Abstract pool test suite', () => { numberOfWorkers, './tests/worker-files/thread/testWorker.mjs', { - workerChoiceStrategyOptions: { measurement: 'invalidMeasurement' } + workerChoiceStrategyOptions: { measurement: 'invalidMeasurement' }, } ) ).toThrow( @@ -346,7 +346,7 @@ describe('Abstract pool test suite', () => { './tests/worker-files/thread/testWorker.mjs', { enableTasksQueue: true, - tasksQueueOptions: 'invalidTasksQueueOptions' + tasksQueueOptions: 'invalidTasksQueueOptions', } ) ).toThrow( @@ -359,7 +359,7 @@ describe('Abstract pool test suite', () => { './tests/worker-files/thread/testWorker.mjs', { enableTasksQueue: true, - tasksQueueOptions: { concurrency: 0 } + tasksQueueOptions: { concurrency: 0 }, } ) ).toThrow( @@ -374,7 +374,7 @@ describe('Abstract pool test suite', () => { './tests/worker-files/thread/testWorker.mjs', { enableTasksQueue: true, - tasksQueueOptions: { concurrency: -1 } + tasksQueueOptions: { concurrency: -1 }, } ) ).toThrow( @@ -389,7 +389,7 @@ describe('Abstract pool test suite', () => { './tests/worker-files/thread/testWorker.mjs', { enableTasksQueue: true, - tasksQueueOptions: { concurrency: 0.2 } + tasksQueueOptions: { concurrency: 0.2 }, } ) ).toThrow( @@ -402,7 +402,7 @@ describe('Abstract pool test suite', () => { './tests/worker-files/thread/testWorker.mjs', { enableTasksQueue: true, - tasksQueueOptions: { size: 0 } + tasksQueueOptions: { size: 0 }, } ) ).toThrow( @@ -417,7 +417,7 @@ describe('Abstract pool test suite', () => { './tests/worker-files/thread/testWorker.mjs', { enableTasksQueue: true, - tasksQueueOptions: { size: -1 } + tasksQueueOptions: { size: -1 }, } ) ).toThrow( @@ -432,7 +432,7 @@ describe('Abstract pool test suite', () => { './tests/worker-files/thread/testWorker.mjs', { enableTasksQueue: true, - tasksQueueOptions: { size: 0.2 } + tasksQueueOptions: { size: 0.2 }, } ) ).toThrow( @@ -455,8 +455,8 @@ describe('Abstract pool test suite', () => { elu: { median: false }, weights: expect.objectContaining({ 0: expect.any(Number), - [pool.info.maxSize - 1]: expect.any(Number) - }) + [pool.info.maxSize - 1]: expect.any(Number), + }), }) } expect( @@ -465,26 +465,26 @@ describe('Abstract pool test suite', () => { runTime: { aggregate: true, average: true, - median: false + median: false, }, waitTime: { aggregate: true, average: true, - median: false + median: false, }, elu: { aggregate: true, average: true, - median: false - } + median: false, + }, }) pool.setWorkerChoiceStrategyOptions({ runTime: { median: true }, - elu: { median: true } + elu: { median: true }, }) expect(pool.opts.workerChoiceStrategyOptions).toStrictEqual({ runTime: { median: true }, - elu: { median: true } + elu: { median: true }, }) for (const [, workerChoiceStrategy] of pool.workerChoiceStrategiesContext .workerChoiceStrategies) { @@ -494,8 +494,8 @@ describe('Abstract pool test suite', () => { elu: { median: true }, weights: expect.objectContaining({ 0: expect.any(Number), - [pool.info.maxSize - 1]: expect.any(Number) - }) + [pool.info.maxSize - 1]: expect.any(Number), + }), }) } expect( @@ -504,26 +504,26 @@ describe('Abstract pool test suite', () => { runTime: { aggregate: true, average: false, - median: true + median: true, }, waitTime: { aggregate: true, average: true, - median: false + median: false, }, elu: { aggregate: true, average: false, - median: true - } + median: true, + }, }) pool.setWorkerChoiceStrategyOptions({ runTime: { median: false }, - elu: { median: false } + elu: { median: false }, }) expect(pool.opts.workerChoiceStrategyOptions).toStrictEqual({ runTime: { median: false }, - elu: { median: false } + elu: { median: false }, }) for (const [, workerChoiceStrategy] of pool.workerChoiceStrategiesContext .workerChoiceStrategies) { @@ -533,8 +533,8 @@ describe('Abstract pool test suite', () => { elu: { median: false }, weights: expect.objectContaining({ 0: expect.any(Number), - [pool.info.maxSize - 1]: expect.any(Number) - }) + [pool.info.maxSize - 1]: expect.any(Number), + }), }) } expect( @@ -543,18 +543,18 @@ describe('Abstract pool test suite', () => { runTime: { aggregate: true, average: true, - median: false + median: false, }, waitTime: { aggregate: true, average: true, - median: false + median: false, }, elu: { aggregate: true, average: true, - median: false - } + median: false, + }, }) expect(() => pool.setWorkerChoiceStrategyOptions('invalidWorkerChoiceStrategyOptions') @@ -591,8 +591,8 @@ describe('Abstract pool test suite', () => { concurrency: 1, size: Math.pow(numberOfWorkers, 2), taskStealing: true, - tasksStealingOnBackPressure: true, - tasksFinishedTimeout: 2000 + tasksStealingOnBackPressure: false, + tasksFinishedTimeout: 2000, }) pool.enableTasksQueue(true, { concurrency: 2 }) expect(pool.opts.enableTasksQueue).toBe(true) @@ -600,8 +600,8 @@ describe('Abstract pool test suite', () => { concurrency: 2, size: Math.pow(numberOfWorkers, 2), taskStealing: true, - tasksStealingOnBackPressure: true, - tasksFinishedTimeout: 2000 + tasksStealingOnBackPressure: false, + tasksFinishedTimeout: 2000, }) pool.enableTasksQueue(false) expect(pool.opts.enableTasksQueue).toBe(false) @@ -619,8 +619,8 @@ describe('Abstract pool test suite', () => { concurrency: 1, size: Math.pow(numberOfWorkers, 2), taskStealing: true, - tasksStealingOnBackPressure: true, - tasksFinishedTimeout: 2000 + tasksStealingOnBackPressure: false, + tasksFinishedTimeout: 2000, }) for (const workerNode of pool.workerNodes) { expect(workerNode.tasksQueueBackPressureSize).toBe( @@ -632,14 +632,14 @@ describe('Abstract pool test suite', () => { size: 2, taskStealing: false, tasksStealingOnBackPressure: false, - tasksFinishedTimeout: 3000 + tasksFinishedTimeout: 3000, }) expect(pool.opts.tasksQueueOptions).toStrictEqual({ concurrency: 2, size: 2, taskStealing: false, tasksStealingOnBackPressure: false, - tasksFinishedTimeout: 3000 + tasksFinishedTimeout: 3000, }) for (const workerNode of pool.workerNodes) { expect(workerNode.tasksQueueBackPressureSize).toBe( @@ -649,14 +649,14 @@ describe('Abstract pool test suite', () => { pool.setTasksQueueOptions({ concurrency: 1, taskStealing: true, - tasksStealingOnBackPressure: true + tasksStealingOnBackPressure: true, }) expect(pool.opts.tasksQueueOptions).toStrictEqual({ concurrency: 1, size: Math.pow(numberOfWorkers, 2), taskStealing: true, tasksStealingOnBackPressure: true, - tasksFinishedTimeout: 2000 + tasksFinishedTimeout: 2000, }) for (const workerNode of pool.workerNodes) { expect(workerNode.tasksQueueBackPressureSize).toBe( @@ -715,7 +715,7 @@ describe('Abstract pool test suite', () => { busyWorkerNodes: 0, executedTasks: 0, executingTasks: 0, - failedTasks: 0 + failedTasks: 0, }) await pool.destroy() pool = new DynamicClusterPool( @@ -738,7 +738,7 @@ describe('Abstract pool test suite', () => { busyWorkerNodes: 0, executedTasks: 0, executingTasks: 0, - failedTasks: 0 + failedTasks: 0, }) await pool.destroy() }) @@ -758,22 +758,22 @@ describe('Abstract pool test suite', () => { maxQueued: 0, sequentiallyStolen: 0, stolen: 0, - failed: 0 + failed: 0, }, runTime: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, waitTime: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, elu: { idle: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, active: { - history: new CircularArray() - } - } + history: expect.any(CircularBuffer), + }, + }, }) } await pool.destroy() @@ -789,6 +789,8 @@ describe('Abstract pool test suite', () => { expect(workerNode.tasksQueue).toBeInstanceOf(PriorityQueue) expect(workerNode.tasksQueue.size).toBe(0) expect(workerNode.tasksQueue.maxSize).toBe(0) + expect(workerNode.tasksQueue.bucketSize).toBe(defaultBucketSize) + expect(workerNode.tasksQueue.enablePriority).toBe(false) } await pool.destroy() pool = new DynamicThreadPool( @@ -801,6 +803,8 @@ describe('Abstract pool test suite', () => { expect(workerNode.tasksQueue).toBeInstanceOf(PriorityQueue) expect(workerNode.tasksQueue.size).toBe(0) expect(workerNode.tasksQueue.maxSize).toBe(0) + expect(workerNode.tasksQueue.bucketSize).toBe(defaultBucketSize) + expect(workerNode.tasksQueue.enablePriority).toBe(false) } await pool.destroy() }) @@ -817,7 +821,8 @@ describe('Abstract pool test suite', () => { type: WorkerTypes.cluster, dynamic: false, ready: true, - stealing: false + stealing: false, + backPressure: false, }) } await pool.destroy() @@ -833,7 +838,8 @@ describe('Abstract pool test suite', () => { type: WorkerTypes.thread, dynamic: false, ready: true, - stealing: false + stealing: false, + backPressure: false, }) } await pool.destroy() @@ -862,7 +868,7 @@ describe('Abstract pool test suite', () => { numberOfWorkers, './tests/worker-files/cluster/testWorker.cjs', { - startWorkers: false + startWorkers: false, } ) expect(pool.info.started).toBe(false) @@ -926,22 +932,22 @@ describe('Abstract pool test suite', () => { maxQueued: 0, sequentiallyStolen: 0, stolen: 0, - failed: 0 + failed: 0, }, runTime: { - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }, waitTime: { - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }, elu: { idle: { - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }, active: { - history: expect.any(CircularArray) - } - } + history: expect.any(CircularBuffer), + }, + }, }) } await Promise.all(promises) @@ -954,22 +960,22 @@ describe('Abstract pool test suite', () => { maxQueued: 0, sequentiallyStolen: 0, stolen: 0, - failed: 0 + failed: 0, }, runTime: { - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }, waitTime: { - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }, elu: { idle: { - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }, active: { - history: expect.any(CircularArray) - } - } + history: expect.any(CircularBuffer), + }, + }, }) } await pool.destroy() @@ -996,31 +1002,27 @@ describe('Abstract pool test suite', () => { maxQueued: 0, sequentiallyStolen: 0, stolen: 0, - failed: 0 + failed: 0, }, runTime: { - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }, waitTime: { - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }, elu: { idle: { - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }, active: { - history: expect.any(CircularArray) - } - } + history: expect.any(CircularBuffer), + }, + }, }) expect(workerNode.usage.tasks.executed).toBeGreaterThan(0) expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual( numberOfWorkers * maxMultiplier ) - expect(workerNode.usage.runTime.history.length).toBe(0) - expect(workerNode.usage.waitTime.history.length).toBe(0) - expect(workerNode.usage.elu.idle.history.length).toBe(0) - expect(workerNode.usage.elu.active.history.length).toBe(0) } pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.FAIR_SHARE) for (const workerNode of pool.workerNodes) { @@ -1032,31 +1034,27 @@ describe('Abstract pool test suite', () => { maxQueued: 0, sequentiallyStolen: 0, stolen: 0, - failed: 0 + failed: 0, }, runTime: { - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }, waitTime: { - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }, elu: { idle: { - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }, active: { - history: expect.any(CircularArray) - } - } + history: expect.any(CircularBuffer), + }, + }, }) expect(workerNode.usage.tasks.executed).toBeGreaterThan(0) expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual( numberOfWorkers * maxMultiplier ) - expect(workerNode.usage.runTime.history.length).toBe(0) - expect(workerNode.usage.waitTime.history.length).toBe(0) - expect(workerNode.usage.elu.idle.history.length).toBe(0) - expect(workerNode.usage.elu.active.history.length).toBe(0) } await pool.destroy() }) @@ -1092,7 +1090,7 @@ describe('Abstract pool test suite', () => { busyWorkerNodes: expect.any(Number), executedTasks: expect.any(Number), executingTasks: expect.any(Number), - failedTasks: expect.any(Number) + failedTasks: expect.any(Number), }) await pool.destroy() }) @@ -1133,7 +1131,7 @@ describe('Abstract pool test suite', () => { busyWorkerNodes: expect.any(Number), executedTasks: expect.any(Number), executingTasks: expect.any(Number), - failedTasks: expect.any(Number) + failedTasks: expect.any(Number), }) await pool.destroy() }) @@ -1173,7 +1171,7 @@ describe('Abstract pool test suite', () => { busyWorkerNodes: expect.any(Number), executedTasks: expect.any(Number), executingTasks: expect.any(Number), - failedTasks: expect.any(Number) + failedTasks: expect.any(Number), }) await pool.destroy() }) @@ -1183,7 +1181,7 @@ describe('Abstract pool test suite', () => { numberOfWorkers, './tests/worker-files/thread/testWorker.mjs', { - enableTasksQueue: true + enableTasksQueue: true, } ) stub(pool, 'hasBackPressure').returns(true) @@ -1221,7 +1219,7 @@ describe('Abstract pool test suite', () => { queuedTasks: expect.any(Number), backPressure: true, stolenTasks: expect.any(Number), - failedTasks: expect.any(Number) + failedTasks: expect.any(Number), }) expect(pool.hasBackPressure.callCount).toBeGreaterThanOrEqual(7) await pool.destroy() @@ -1234,7 +1232,7 @@ describe('Abstract pool test suite', () => { './tests/worker-files/thread/asyncWorker.mjs', { enableTasksQueue: true, - tasksQueueOptions: { tasksFinishedTimeout } + tasksQueueOptions: { tasksFinishedTimeout }, } ) const maxMultiplier = 4 @@ -1263,7 +1261,7 @@ describe('Abstract pool test suite', () => { './tests/worker-files/thread/asyncWorker.mjs', { enableTasksQueue: true, - tasksQueueOptions: { tasksFinishedTimeout } + tasksQueueOptions: { tasksFinishedTimeout }, } ) const maxMultiplier = 4 @@ -1305,7 +1303,7 @@ describe('Abstract pool test suite', () => { }, promiseResolve () { if (executionAsyncId() === taskAsyncId) resolveCalls++ - } + }, }) const pool = new FixedThreadPool( numberOfWorkers, @@ -1381,7 +1379,7 @@ describe('Abstract pool test suite', () => { await expect( dynamicThreadPool.addTaskFunction('test', { taskFunction: () => {}, - priority: -21 + priority: -21, }) ).rejects.toThrow( new RangeError("Property 'priority' must be between -20 and 19") @@ -1389,7 +1387,7 @@ describe('Abstract pool test suite', () => { await expect( dynamicThreadPool.addTaskFunction('test', { taskFunction: () => {}, - priority: 20 + priority: 20, }) ).rejects.toThrow( new RangeError("Property 'priority' must be between -20 and 19") @@ -1397,17 +1395,17 @@ describe('Abstract pool test suite', () => { await expect( dynamicThreadPool.addTaskFunction('test', { taskFunction: () => {}, - strategy: 'invalidStrategy' + strategy: 'invalidStrategy', }) ).rejects.toThrow( new Error("Invalid worker choice strategy 'invalidStrategy'") ) expect(dynamicThreadPool.listTaskFunctionsProperties()).toStrictEqual([ { name: DEFAULT_TASK_NAME }, - { name: 'test' } + { name: 'test' }, ]) expect([ - ...dynamicThreadPool.workerChoiceStrategiesContext.workerChoiceStrategies.keys() + ...dynamicThreadPool.workerChoiceStrategiesContext.workerChoiceStrategies.keys(), ]).toStrictEqual([WorkerChoiceStrategies.ROUND_ROBIN]) const echoTaskFunction = data => { return data @@ -1415,24 +1413,24 @@ describe('Abstract pool test suite', () => { await expect( dynamicThreadPool.addTaskFunction('echo', { taskFunction: echoTaskFunction, - strategy: WorkerChoiceStrategies.LEAST_ELU + strategy: WorkerChoiceStrategies.LEAST_ELU, }) ).resolves.toBe(true) expect(dynamicThreadPool.taskFunctions.size).toBe(1) expect(dynamicThreadPool.taskFunctions.get('echo')).toStrictEqual({ taskFunction: echoTaskFunction, - strategy: WorkerChoiceStrategies.LEAST_ELU + strategy: WorkerChoiceStrategies.LEAST_ELU, }) expect([ - ...dynamicThreadPool.workerChoiceStrategiesContext.workerChoiceStrategies.keys() + ...dynamicThreadPool.workerChoiceStrategiesContext.workerChoiceStrategies.keys(), ]).toStrictEqual([ WorkerChoiceStrategies.ROUND_ROBIN, - WorkerChoiceStrategies.LEAST_ELU + WorkerChoiceStrategies.LEAST_ELU, ]) expect(dynamicThreadPool.listTaskFunctionsProperties()).toStrictEqual([ { name: DEFAULT_TASK_NAME }, { name: 'test' }, - { name: 'echo', strategy: WorkerChoiceStrategies.LEAST_ELU } + { name: 'echo', strategy: WorkerChoiceStrategies.LEAST_ELU }, ]) const taskFunctionData = { test: 'test' } const echoResult = await dynamicThreadPool.execute(taskFunctionData, 'echo') @@ -1445,29 +1443,63 @@ describe('Abstract pool test suite', () => { queued: 0, sequentiallyStolen: 0, stolen: 0, - failed: 0 + failed: 0, }, runTime: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, waitTime: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, - elu: { - idle: { - aggregate: 0, - maximum: 0, - minimum: 0, - history: new CircularArray() - }, - active: { - aggregate: 0, - maximum: 0, - minimum: 0, - history: new CircularArray() - } - } + elu: expect.objectContaining({ + idle: expect.objectContaining({ + history: expect.any(CircularBuffer), + }), + active: expect.objectContaining({ + history: expect.any(CircularBuffer), + }), + }), }) + expect( + workerNode.getTaskFunctionWorkerUsage('echo').tasks.executed + ).toBeGreaterThan(0) + if ( + workerNode.getTaskFunctionWorkerUsage('echo').elu.active.aggregate == + null + ) { + expect( + workerNode.getTaskFunctionWorkerUsage('echo').elu.active.aggregate + ).toBeUndefined() + } else { + expect( + workerNode.getTaskFunctionWorkerUsage('echo').elu.active.aggregate + ).toBeGreaterThan(0) + } + if ( + workerNode.getTaskFunctionWorkerUsage('echo').elu.idle.aggregate == null + ) { + expect( + workerNode.getTaskFunctionWorkerUsage('echo').elu.idle.aggregate + ).toBeUndefined() + } else { + expect( + workerNode.getTaskFunctionWorkerUsage('echo').elu.idle.aggregate + ).toBeGreaterThanOrEqual(0) + } + if ( + workerNode.getTaskFunctionWorkerUsage('echo').elu.utilization == null + ) { + expect( + workerNode.getTaskFunctionWorkerUsage('echo').elu.utilization + ).toBeUndefined() + } else { + expect( + workerNode.getTaskFunctionWorkerUsage('echo').elu.utilization + ).toBeGreaterThanOrEqual(0) + expect( + workerNode.getTaskFunctionWorkerUsage('echo').elu.utilization + ).toBeLessThanOrEqual(1) + } } await dynamicThreadPool.destroy() }) @@ -1481,7 +1513,7 @@ describe('Abstract pool test suite', () => { await waitPoolEvents(dynamicThreadPool, PoolEvents.ready, 1) expect(dynamicThreadPool.listTaskFunctionsProperties()).toStrictEqual([ { name: DEFAULT_TASK_NAME }, - { name: 'test' } + { name: 'test' }, ]) await expect(dynamicThreadPool.removeTaskFunction('test')).rejects.toThrow( new Error('Cannot remove a task function not handled on the pool side') @@ -1491,23 +1523,23 @@ describe('Abstract pool test suite', () => { } await dynamicThreadPool.addTaskFunction('echo', { taskFunction: echoTaskFunction, - strategy: WorkerChoiceStrategies.LEAST_ELU + strategy: WorkerChoiceStrategies.LEAST_ELU, }) expect(dynamicThreadPool.taskFunctions.size).toBe(1) expect(dynamicThreadPool.taskFunctions.get('echo')).toStrictEqual({ taskFunction: echoTaskFunction, - strategy: WorkerChoiceStrategies.LEAST_ELU + strategy: WorkerChoiceStrategies.LEAST_ELU, }) expect([ - ...dynamicThreadPool.workerChoiceStrategiesContext.workerChoiceStrategies.keys() + ...dynamicThreadPool.workerChoiceStrategiesContext.workerChoiceStrategies.keys(), ]).toStrictEqual([ WorkerChoiceStrategies.ROUND_ROBIN, - WorkerChoiceStrategies.LEAST_ELU + WorkerChoiceStrategies.LEAST_ELU, ]) expect(dynamicThreadPool.listTaskFunctionsProperties()).toStrictEqual([ { name: DEFAULT_TASK_NAME }, { name: 'test' }, - { name: 'echo', strategy: WorkerChoiceStrategies.LEAST_ELU } + { name: 'echo', strategy: WorkerChoiceStrategies.LEAST_ELU }, ]) await expect(dynamicThreadPool.removeTaskFunction('echo')).resolves.toBe( true @@ -1515,11 +1547,11 @@ describe('Abstract pool test suite', () => { expect(dynamicThreadPool.taskFunctions.size).toBe(0) expect(dynamicThreadPool.taskFunctions.get('echo')).toBeUndefined() expect([ - ...dynamicThreadPool.workerChoiceStrategiesContext.workerChoiceStrategies.keys() + ...dynamicThreadPool.workerChoiceStrategiesContext.workerChoiceStrategies.keys(), ]).toStrictEqual([WorkerChoiceStrategies.ROUND_ROBIN]) expect(dynamicThreadPool.listTaskFunctionsProperties()).toStrictEqual([ { name: DEFAULT_TASK_NAME }, - { name: 'test' } + { name: 'test' }, ]) await dynamicThreadPool.destroy() }) @@ -1535,7 +1567,7 @@ describe('Abstract pool test suite', () => { { name: DEFAULT_TASK_NAME }, { name: 'jsonIntegerSerialization' }, { name: 'factorial' }, - { name: 'fibonacci' } + { name: 'fibonacci' }, ]) await dynamicThreadPool.destroy() const fixedClusterPool = new FixedClusterPool( @@ -1547,7 +1579,7 @@ describe('Abstract pool test suite', () => { { name: DEFAULT_TASK_NAME }, { name: 'jsonIntegerSerialization' }, { name: 'factorial' }, - { name: 'fibonacci' } + { name: 'fibonacci' }, ]) await fixedClusterPool.destroy() }) @@ -1583,7 +1615,7 @@ describe('Abstract pool test suite', () => { { name: DEFAULT_TASK_NAME }, { name: 'jsonIntegerSerialization' }, { name: 'factorial' }, - { name: 'fibonacci' } + { name: 'fibonacci' }, ]) await expect( dynamicThreadPool.setDefaultTaskFunction('factorial') @@ -1592,7 +1624,7 @@ describe('Abstract pool test suite', () => { { name: DEFAULT_TASK_NAME }, { name: 'factorial' }, { name: 'jsonIntegerSerialization' }, - { name: 'fibonacci' } + { name: 'fibonacci' }, ]) await expect( dynamicThreadPool.setDefaultTaskFunction('fibonacci') @@ -1601,7 +1633,7 @@ describe('Abstract pool test suite', () => { { name: DEFAULT_TASK_NAME }, { name: 'fibonacci' }, { name: 'jsonIntegerSerialization' }, - { name: 'factorial' } + { name: 'factorial' }, ]) await dynamicThreadPool.destroy() }) @@ -1628,9 +1660,11 @@ describe('Abstract pool test suite', () => { { name: DEFAULT_TASK_NAME }, { name: 'jsonIntegerSerialization' }, { name: 'factorial' }, - { name: 'fibonacci' } + { name: 'fibonacci' }, ]) expect(workerNode.taskFunctionsUsage.size).toBe(3) + expect(workerNode.usage.tasks.executed).toBeGreaterThan(0) + expect(workerNode.tasksQueue.enablePriority).toBe(false) for (const taskFunctionProperties of pool.listTaskFunctionsProperties()) { expect( workerNode.getTaskFunctionWorkerUsage(taskFunctionProperties.name) @@ -1641,22 +1675,92 @@ describe('Abstract pool test suite', () => { failed: 0, queued: 0, sequentiallyStolen: 0, - stolen: 0 + stolen: 0, }, runTime: { - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }, waitTime: { - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }, elu: { idle: { - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }, active: { - history: expect.any(CircularArray) - } - } + history: expect.any(CircularBuffer), + }, + }, + }) + expect( + workerNode.getTaskFunctionWorkerUsage(taskFunctionProperties.name) + .tasks.executed + ).toBeGreaterThan(0) + } + expect( + workerNode.getTaskFunctionWorkerUsage(DEFAULT_TASK_NAME) + ).toStrictEqual( + workerNode.getTaskFunctionWorkerUsage( + workerNode.info.taskFunctionsProperties[1].name + ) + ) + } + await pool.destroy() + }) + + it('Verify that task function objects worker is working', async () => { + const pool = new DynamicThreadPool( + Math.floor(numberOfWorkers / 2), + numberOfWorkers, + './tests/worker-files/thread/testTaskFunctionObjectsWorker.mjs' + ) + const data = { n: 10 } + const result0 = await pool.execute(data) + expect(result0).toStrictEqual({ ok: 1 }) + const result1 = await pool.execute(data, 'jsonIntegerSerialization') + expect(result1).toStrictEqual({ ok: 1 }) + const result2 = await pool.execute(data, 'factorial') + expect(result2).toBe(3628800) + const result3 = await pool.execute(data, 'fibonacci') + expect(result3).toBe(55) + expect(pool.info.executingTasks).toBe(0) + expect(pool.info.executedTasks).toBe(4) + for (const workerNode of pool.workerNodes) { + expect(workerNode.info.taskFunctionsProperties).toStrictEqual([ + { name: DEFAULT_TASK_NAME }, + { name: 'jsonIntegerSerialization' }, + { name: 'factorial' }, + { name: 'fibonacci', priority: -5 }, + ]) + expect(workerNode.taskFunctionsUsage.size).toBe(3) + expect(workerNode.usage.tasks.executed).toBeGreaterThan(0) + expect(workerNode.tasksQueue.enablePriority).toBe(true) + for (const taskFunctionProperties of pool.listTaskFunctionsProperties()) { + expect( + workerNode.getTaskFunctionWorkerUsage(taskFunctionProperties.name) + ).toStrictEqual({ + tasks: { + executed: expect.any(Number), + executing: 0, + failed: 0, + queued: 0, + sequentiallyStolen: 0, + stolen: 0, + }, + runTime: { + history: expect.any(CircularBuffer), + }, + waitTime: { + history: expect.any(CircularBuffer), + }, + elu: { + idle: { + history: expect.any(CircularBuffer), + }, + active: { + history: expect.any(CircularBuffer), + }, + }, }) expect( workerNode.getTaskFunctionWorkerUsage(taskFunctionProperties.name) @@ -1698,7 +1802,7 @@ describe('Abstract pool test suite', () => { pool.sendTaskFunctionOperationToWorker(workerNodeKey, { taskFunctionOperation: 'add', taskFunctionProperties: { name: 'empty' }, - taskFunction: (() => {}).toString() + taskFunction: (() => {}).toString(), }) ).resolves.toBe(true) expect( @@ -1706,7 +1810,7 @@ describe('Abstract pool test suite', () => { ).toStrictEqual([ { name: DEFAULT_TASK_NAME }, { name: 'test' }, - { name: 'empty' } + { name: 'empty' }, ]) await pool.destroy() }) @@ -1721,14 +1825,14 @@ describe('Abstract pool test suite', () => { pool.sendTaskFunctionOperationToWorkers({ taskFunctionOperation: 'add', taskFunctionProperties: { name: 'empty' }, - taskFunction: (() => {}).toString() + taskFunction: (() => {}).toString(), }) ).resolves.toBe(true) for (const workerNode of pool.workerNodes) { expect(workerNode.info.taskFunctionsProperties).toStrictEqual([ { name: DEFAULT_TASK_NAME }, { name: 'test' }, - { name: 'empty' } + { name: 'empty' }, ]) } await pool.destroy() diff --git a/tests/pools/cluster/dynamic.test.mjs b/tests/pools/cluster/dynamic.test.mjs index 166498f9..f5094452 100644 --- a/tests/pools/cluster/dynamic.test.mjs +++ b/tests/pools/cluster/dynamic.test.mjs @@ -3,7 +3,7 @@ import { expect } from 'expect' import { DynamicClusterPool, PoolEvents, - WorkerChoiceStrategies + WorkerChoiceStrategies, } from '../../../lib/index.cjs' import { TaskFunctions } from '../../test-types.cjs' import { sleep, waitPoolEvents, waitWorkerEvents } from '../../test-utils.cjs' @@ -16,17 +16,17 @@ describe('Dynamic cluster pool test suite', () => { max, './tests/worker-files/cluster/testWorker.cjs', { - errorHandler: e => console.error(e) + errorHandler: e => console.error(e), } ) it('Verify that the function is executed in a worker cluster', async () => { let result = await pool.execute({ - function: TaskFunctions.fibonacci + function: TaskFunctions.fibonacci, }) expect(result).toBe(354224848179262000000) result = await pool.execute({ - function: TaskFunctions.factorial + function: TaskFunctions.factorial, }) expect(result).toBe(9.33262154439441e157) }) @@ -67,14 +67,14 @@ describe('Dynamic cluster pool test suite', () => { pool.emitter.on(PoolEvents.destroy, () => ++poolDestroy) expect(pool.emitter.eventNames()).toStrictEqual([ PoolEvents.busy, - PoolEvents.destroy + PoolEvents.destroy, ]) await pool.destroy() const numberOfExitEvents = await exitPromise expect(pool.started).toBe(false) expect(pool.emitter.eventNames()).toStrictEqual([ PoolEvents.busy, - PoolEvents.destroy + PoolEvents.destroy, ]) expect(pool.readyEventEmitted).toBe(false) expect(pool.workerNodes.length).toBe(0) @@ -108,7 +108,7 @@ describe('Dynamic cluster pool test suite', () => { { errorHandler: e => console.error(e), onlineHandler: () => console.info('long executing worker is online'), - exitHandler: () => console.info('long executing worker exited') + exitHandler: () => console.info('long executing worker exited'), } ) expect(longRunningPool.workerNodes.length).toBe(min) @@ -136,7 +136,7 @@ describe('Dynamic cluster pool test suite', () => { { errorHandler: e => console.error(e), onlineHandler: () => console.info('long executing worker is online'), - exitHandler: () => console.info('long executing worker exited') + exitHandler: () => console.info('long executing worker exited'), } ) expect(longRunningPool.workerNodes.length).toBe(min) @@ -169,12 +169,13 @@ describe('Dynamic cluster pool test suite', () => { max, './tests/worker-files/cluster/testWorker.cjs', { - workerChoiceStrategy + workerChoiceStrategy, } ) expect(pool.starting).toBe(false) expect(pool.readyEventEmitted).toBe(false) for (let run = 0; run < 2; run++) { + // eslint-disable-next-line @typescript-eslint/no-unused-expressions run % 2 !== 0 && pool.enableTasksQueue(true) const maxMultiplier = 4 const promises = new Set() diff --git a/tests/pools/cluster/fixed.test.mjs b/tests/pools/cluster/fixed.test.mjs index ad7c003a..a78a4509 100644 --- a/tests/pools/cluster/fixed.test.mjs +++ b/tests/pools/cluster/fixed.test.mjs @@ -1,3 +1,5 @@ +import cluster from 'node:cluster' + import { expect } from 'expect' import { FixedClusterPool, PoolEvents } from '../../../lib/index.cjs' @@ -12,7 +14,7 @@ describe('Fixed cluster pool test suite', () => { numberOfWorkers, './tests/worker-files/cluster/testWorker.cjs', { - errorHandler: e => console.error(e) + errorHandler: e => console.error(e), } ) const queuePool = new FixedClusterPool( @@ -21,9 +23,9 @@ describe('Fixed cluster pool test suite', () => { { enableTasksQueue: true, tasksQueueOptions: { - concurrency: tasksConcurrency + concurrency: tasksConcurrency, }, - errorHandler: e => console.error(e) + errorHandler: e => console.error(e), } ) const emptyPool = new FixedClusterPool( @@ -39,14 +41,14 @@ describe('Fixed cluster pool test suite', () => { numberOfWorkers, './tests/worker-files/cluster/errorWorker.cjs', { - errorHandler: e => console.error(e) + errorHandler: e => console.error(e), } ) const asyncErrorPool = new FixedClusterPool( numberOfWorkers, './tests/worker-files/cluster/asyncErrorWorker.cjs', { - errorHandler: e => console.error(e) + errorHandler: e => console.error(e), } ) const asyncPool = new FixedClusterPool( @@ -66,11 +68,11 @@ describe('Fixed cluster pool test suite', () => { it('Verify that the function is executed in a worker cluster', async () => { let result = await pool.execute({ - function: TaskFunctions.fibonacci + function: TaskFunctions.fibonacci, }) expect(result).toBe(354224848179262000000) result = await pool.execute({ - function: TaskFunctions.factorial + function: TaskFunctions.factorial, }) expect(result).toBe(9.33262154439441e157) }) @@ -85,7 +87,7 @@ describe('Fixed cluster pool test suite', () => { numberOfWorkers, './tests/worker-files/cluster/testWorker.cjs', { - errorHandler: e => console.error(e) + errorHandler: e => console.error(e), } ) expect(pool.emitter.eventNames()).toStrictEqual([]) @@ -209,7 +211,7 @@ describe('Fixed cluster pool test suite', () => { expect(taskError).toStrictEqual({ name: DEFAULT_TASK_NAME, message: 'Error Message from ClusterWorker', - data + data, }) expect( errorPool.workerNodes.some( @@ -226,7 +228,7 @@ describe('Fixed cluster pool test suite', () => { taskError = e }) expect(asyncErrorPool.emitter.eventNames()).toStrictEqual([ - PoolEvents.taskError + PoolEvents.taskError, ]) let inError try { @@ -240,7 +242,7 @@ describe('Fixed cluster pool test suite', () => { expect(taskError).toStrictEqual({ name: DEFAULT_TASK_NAME, message: 'Error Message from ClusterWorker:async', - data + data, }) expect( asyncErrorPool.workerNodes.some( @@ -265,14 +267,14 @@ describe('Fixed cluster pool test suite', () => { pool.emitter.on(PoolEvents.destroy, () => ++poolDestroy) expect(pool.emitter.eventNames()).toStrictEqual([ PoolEvents.busy, - PoolEvents.destroy + PoolEvents.destroy, ]) await pool.destroy() const numberOfExitEvents = await exitPromise expect(pool.started).toBe(false) expect(pool.emitter.eventNames()).toStrictEqual([ PoolEvents.busy, - PoolEvents.destroy + PoolEvents.destroy, ]) expect(pool.readyEventEmitted).toBe(false) expect(pool.workerNodes.length).toBe(0) @@ -285,20 +287,24 @@ describe('Fixed cluster pool test suite', () => { let pool = new FixedClusterPool(numberOfWorkers, workerFilePath) expect(pool.opts.env).toBeUndefined() expect(pool.opts.settings).toBeUndefined() + expect(cluster.settings).toMatchObject({ + exec: workerFilePath, + silent: false, + }) await pool.destroy() pool = new FixedClusterPool(numberOfWorkers, workerFilePath, { env: { TEST: 'test' }, - settings: { args: ['--use', 'http'], silent: true } + settings: { args: ['--use', 'http'], silent: true }, }) expect(pool.opts.env).toStrictEqual({ TEST: 'test' }) expect(pool.opts.settings).toStrictEqual({ args: ['--use', 'http'], - silent: true + silent: true, }) - expect({ ...pool.opts.settings, exec: workerFilePath }).toStrictEqual({ + expect(cluster.settings).toMatchObject({ args: ['--use', 'http'], silent: true, - exec: workerFilePath + exec: workerFilePath, }) await pool.destroy() }) diff --git a/tests/pools/selection-strategies/selection-strategies-utils.test.mjs b/tests/pools/selection-strategies/selection-strategies-utils.test.mjs index dc6fc71f..9b57e789 100644 --- a/tests/pools/selection-strategies/selection-strategies-utils.test.mjs +++ b/tests/pools/selection-strategies/selection-strategies-utils.test.mjs @@ -3,7 +3,7 @@ import { expect } from 'expect' import { FixedClusterPool, FixedThreadPool } from '../../../lib/index.cjs' import { buildWorkerChoiceStrategyOptions, - getWorkerChoiceStrategiesRetries + getWorkerChoiceStrategiesRetries, } from '../../../lib/pools/selection-strategies/selection-strategies-utils.cjs' describe('Selection strategies utils test suite', () => { @@ -19,8 +19,8 @@ describe('Selection strategies utils test suite', () => { elu: { median: false }, weights: expect.objectContaining({ 0: expect.any(Number), - [pool.info.maxSize - 1]: expect.any(Number) - }) + [pool.info.maxSize - 1]: expect.any(Number), + }), }) const workerChoiceStrategyOptions = { runTime: { median: true }, @@ -28,8 +28,8 @@ describe('Selection strategies utils test suite', () => { elu: { median: true }, weights: { 0: 100, - 1: 100 - } + 1: 100, + }, } expect( buildWorkerChoiceStrategyOptions(pool, workerChoiceStrategyOptions) @@ -50,8 +50,8 @@ describe('Selection strategies utils test suite', () => { elu: { median: true }, weights: { 0: 100, - 1: 100 - } + 1: 100, + }, } expect( getWorkerChoiceStrategiesRetries(pool, workerChoiceStrategyOptions) diff --git a/tests/pools/selection-strategies/selection-strategies.test.mjs b/tests/pools/selection-strategies/selection-strategies.test.mjs index e4d1dd07..e8df7e1a 100644 --- a/tests/pools/selection-strategies/selection-strategies.test.mjs +++ b/tests/pools/selection-strategies/selection-strategies.test.mjs @@ -2,13 +2,13 @@ import { randomInt } from 'node:crypto' import { expect } from 'expect' -import { CircularArray } from '../../../lib/circular-array.cjs' +import { CircularBuffer } from '../../../lib/circular-buffer.cjs' import { DynamicClusterPool, DynamicThreadPool, FixedClusterPool, FixedThreadPool, - WorkerChoiceStrategies + WorkerChoiceStrategies, } from '../../../lib/index.cjs' describe('Selection strategies test suite', () => { @@ -159,7 +159,7 @@ describe('Selection strategies test suite', () => { ) expect(pool.workerChoiceStrategiesContext.getPolicy()).toStrictEqual({ dynamicWorkerUsage: false, - dynamicWorkerReady: true + dynamicWorkerReady: true, }) await pool.destroy() pool = new DynamicThreadPool( @@ -170,7 +170,7 @@ describe('Selection strategies test suite', () => { ) expect(pool.workerChoiceStrategiesContext.getPolicy()).toStrictEqual({ dynamicWorkerUsage: false, - dynamicWorkerReady: true + dynamicWorkerReady: true, }) // We need to clean up the resources after our test await pool.destroy() @@ -189,18 +189,18 @@ describe('Selection strategies test suite', () => { runTime: { aggregate: false, average: false, - median: false + median: false, }, waitTime: { aggregate: false, average: false, - median: false + median: false, }, elu: { aggregate: false, average: false, - median: false - } + median: false, + }, }) await pool.destroy() pool = new DynamicThreadPool( @@ -215,18 +215,18 @@ describe('Selection strategies test suite', () => { runTime: { aggregate: false, average: false, - median: false + median: false, }, waitTime: { aggregate: false, average: false, - median: false + median: false, }, elu: { aggregate: false, average: false, - median: false - } + median: false, + }, }) // We need to clean up the resources after our test await pool.destroy() @@ -255,22 +255,22 @@ describe('Selection strategies test suite', () => { maxQueued: 0, sequentiallyStolen: 0, stolen: 0, - failed: 0 + failed: 0, }, runTime: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, waitTime: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, elu: { idle: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, active: { - history: new CircularArray() - } - } + history: expect.any(CircularBuffer), + }, + }, }) } expect( @@ -311,22 +311,22 @@ describe('Selection strategies test suite', () => { maxQueued: 0, sequentiallyStolen: 0, stolen: 0, - failed: 0 + failed: 0, }, runTime: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, waitTime: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, elu: { idle: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, active: { - history: new CircularArray() - } - } + history: expect.any(CircularBuffer), + }, + }, }) expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0) expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual( @@ -434,7 +434,7 @@ describe('Selection strategies test suite', () => { ) expect(pool.workerChoiceStrategiesContext.getPolicy()).toStrictEqual({ dynamicWorkerUsage: false, - dynamicWorkerReady: true + dynamicWorkerReady: true, }) await pool.destroy() pool = new DynamicThreadPool( @@ -445,7 +445,7 @@ describe('Selection strategies test suite', () => { ) expect(pool.workerChoiceStrategiesContext.getPolicy()).toStrictEqual({ dynamicWorkerUsage: false, - dynamicWorkerReady: true + dynamicWorkerReady: true, }) // We need to clean up the resources after our test await pool.destroy() @@ -464,18 +464,18 @@ describe('Selection strategies test suite', () => { runTime: { aggregate: false, average: false, - median: false + median: false, }, waitTime: { aggregate: false, average: false, - median: false + median: false, }, elu: { aggregate: false, average: false, - median: false - } + median: false, + }, }) await pool.destroy() pool = new DynamicThreadPool( @@ -490,18 +490,18 @@ describe('Selection strategies test suite', () => { runTime: { aggregate: false, average: false, - median: false + median: false, }, waitTime: { aggregate: false, average: false, - median: false + median: false, }, elu: { aggregate: false, average: false, - median: false - } + median: false, + }, }) // We need to clean up the resources after our test await pool.destroy() @@ -529,22 +529,22 @@ describe('Selection strategies test suite', () => { maxQueued: 0, sequentiallyStolen: 0, stolen: 0, - failed: 0 + failed: 0, }, runTime: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, waitTime: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, elu: { idle: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, active: { - history: new CircularArray() - } - } + history: expect.any(CircularBuffer), + }, + }, }) expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0) expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual( @@ -588,22 +588,22 @@ describe('Selection strategies test suite', () => { maxQueued: 0, sequentiallyStolen: 0, stolen: 0, - failed: 0 + failed: 0, }, runTime: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, waitTime: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, elu: { idle: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, active: { - history: new CircularArray() - } - } + history: expect.any(CircularBuffer), + }, + }, }) expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0) expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual( @@ -633,7 +633,7 @@ describe('Selection strategies test suite', () => { ) expect(pool.workerChoiceStrategiesContext.getPolicy()).toStrictEqual({ dynamicWorkerUsage: false, - dynamicWorkerReady: true + dynamicWorkerReady: true, }) await pool.destroy() pool = new DynamicThreadPool( @@ -644,7 +644,7 @@ describe('Selection strategies test suite', () => { ) expect(pool.workerChoiceStrategiesContext.getPolicy()).toStrictEqual({ dynamicWorkerUsage: false, - dynamicWorkerReady: true + dynamicWorkerReady: true, }) // We need to clean up the resources after our test await pool.destroy() @@ -663,18 +663,18 @@ describe('Selection strategies test suite', () => { runTime: { aggregate: true, average: false, - median: false + median: false, }, waitTime: { aggregate: true, average: false, - median: false + median: false, }, elu: { aggregate: false, average: false, - median: false - } + median: false, + }, }) await pool.destroy() pool = new DynamicThreadPool( @@ -689,18 +689,18 @@ describe('Selection strategies test suite', () => { runTime: { aggregate: true, average: false, - median: false + median: false, }, waitTime: { aggregate: true, average: false, - median: false + median: false, }, elu: { aggregate: false, average: false, - median: false - } + median: false, + }, }) // We need to clean up the resources after our test await pool.destroy() @@ -728,22 +728,22 @@ describe('Selection strategies test suite', () => { maxQueued: 0, sequentiallyStolen: 0, stolen: 0, - failed: 0 + failed: 0, }, runTime: expect.objectContaining({ - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }), waitTime: expect.objectContaining({ - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }), elu: { idle: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, active: { - history: new CircularArray() - } - } + history: expect.any(CircularBuffer), + }, + }, }) expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0) expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual( @@ -797,22 +797,22 @@ describe('Selection strategies test suite', () => { maxQueued: 0, sequentiallyStolen: 0, stolen: 0, - failed: 0 + failed: 0, }, runTime: expect.objectContaining({ - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }), waitTime: expect.objectContaining({ - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }), elu: { idle: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, active: { - history: new CircularArray() - } - } + history: expect.any(CircularBuffer), + }, + }, }) expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0) expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual( @@ -852,7 +852,7 @@ describe('Selection strategies test suite', () => { ) expect(pool.workerChoiceStrategiesContext.getPolicy()).toStrictEqual({ dynamicWorkerUsage: false, - dynamicWorkerReady: true + dynamicWorkerReady: true, }) await pool.destroy() pool = new DynamicThreadPool( @@ -863,7 +863,7 @@ describe('Selection strategies test suite', () => { ) expect(pool.workerChoiceStrategiesContext.getPolicy()).toStrictEqual({ dynamicWorkerUsage: false, - dynamicWorkerReady: true + dynamicWorkerReady: true, }) // We need to clean up the resources after our test await pool.destroy() @@ -882,18 +882,18 @@ describe('Selection strategies test suite', () => { runTime: { aggregate: false, average: false, - median: false + median: false, }, waitTime: { aggregate: false, average: false, - median: false + median: false, }, elu: { aggregate: true, average: false, - median: false - } + median: false, + }, }) await pool.destroy() pool = new DynamicThreadPool( @@ -908,18 +908,18 @@ describe('Selection strategies test suite', () => { runTime: { aggregate: false, average: false, - median: false + median: false, }, waitTime: { aggregate: false, average: false, - median: false + median: false, }, elu: { aggregate: true, average: false, - median: false - } + median: false, + }, }) // We need to clean up the resources after our test await pool.destroy() @@ -947,22 +947,22 @@ describe('Selection strategies test suite', () => { maxQueued: 0, sequentiallyStolen: 0, stolen: 0, - failed: 0 + failed: 0, }, runTime: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, waitTime: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, elu: expect.objectContaining({ idle: expect.objectContaining({ - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }), active: expect.objectContaining({ - history: expect.any(CircularArray) - }) - }) + history: expect.any(CircularBuffer), + }), + }), }) expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0) expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual( @@ -1022,22 +1022,22 @@ describe('Selection strategies test suite', () => { maxQueued: 0, sequentiallyStolen: 0, stolen: 0, - failed: 0 + failed: 0, }, runTime: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, waitTime: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, elu: expect.objectContaining({ idle: expect.objectContaining({ - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }), active: expect.objectContaining({ - history: expect.any(CircularArray) - }) - }) + history: expect.any(CircularBuffer), + }), + }), }) expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0) expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual( @@ -1083,7 +1083,7 @@ describe('Selection strategies test suite', () => { ) expect(pool.workerChoiceStrategiesContext.getPolicy()).toStrictEqual({ dynamicWorkerUsage: false, - dynamicWorkerReady: true + dynamicWorkerReady: true, }) await pool.destroy() pool = new DynamicThreadPool( @@ -1094,7 +1094,7 @@ describe('Selection strategies test suite', () => { ) expect(pool.workerChoiceStrategiesContext.getPolicy()).toStrictEqual({ dynamicWorkerUsage: false, - dynamicWorkerReady: true + dynamicWorkerReady: true, }) // We need to clean up the resources after our test await pool.destroy() @@ -1113,18 +1113,18 @@ describe('Selection strategies test suite', () => { runTime: { aggregate: true, average: true, - median: false + median: false, }, waitTime: { aggregate: true, average: true, - median: false + median: false, }, elu: { aggregate: true, average: true, - median: false - } + median: false, + }, }) await pool.destroy() pool = new DynamicThreadPool( @@ -1139,18 +1139,18 @@ describe('Selection strategies test suite', () => { runTime: { aggregate: true, average: true, - median: false + median: false, }, waitTime: { aggregate: true, average: true, - median: false + median: false, }, elu: { aggregate: true, average: true, - median: false - } + median: false, + }, }) // We need to clean up the resources after our test await pool.destroy() @@ -1178,22 +1178,22 @@ describe('Selection strategies test suite', () => { maxQueued: 0, sequentiallyStolen: 0, stolen: 0, - failed: 0 + failed: 0, }, runTime: expect.objectContaining({ - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }), waitTime: expect.objectContaining({ - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }), elu: expect.objectContaining({ idle: expect.objectContaining({ - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }), active: expect.objectContaining({ - history: expect.any(CircularArray) - }) - }) + history: expect.any(CircularBuffer), + }), + }), }) expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0) expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual( @@ -1274,22 +1274,22 @@ describe('Selection strategies test suite', () => { maxQueued: 0, sequentiallyStolen: 0, stolen: 0, - failed: 0 + failed: 0, }, runTime: expect.objectContaining({ - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }), waitTime: expect.objectContaining({ - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }), elu: expect.objectContaining({ idle: expect.objectContaining({ - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }), active: expect.objectContaining({ - history: expect.any(CircularArray) - }) - }) + history: expect.any(CircularBuffer), + }), + }), }) expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0) expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual( @@ -1355,8 +1355,8 @@ describe('Selection strategies test suite', () => { { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE, workerChoiceStrategyOptions: { - runTime: { median: true } - } + runTime: { median: true }, + }, } ) // TODO: Create a better test to cover `FairShareChoiceStrategy#choose` @@ -1375,22 +1375,22 @@ describe('Selection strategies test suite', () => { maxQueued: 0, sequentiallyStolen: 0, stolen: 0, - failed: 0 + failed: 0, }, runTime: expect.objectContaining({ - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }), waitTime: expect.objectContaining({ - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }), elu: expect.objectContaining({ idle: expect.objectContaining({ - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }), active: expect.objectContaining({ - history: expect.any(CircularArray) - }) - }) + history: expect.any(CircularBuffer), + }), + }), }) expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0) expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual( @@ -1456,7 +1456,7 @@ describe('Selection strategies test suite', () => { ) for (const workerNode of pool.workerNodes) { workerNode.strategyData = { - virtualTaskEndTimestamp: performance.now() + virtualTaskEndTimestamp: performance.now(), } } pool.setWorkerChoiceStrategy(workerChoiceStrategy) @@ -1471,7 +1471,7 @@ describe('Selection strategies test suite', () => { ) for (const workerNode of pool.workerNodes) { workerNode.strategyData = { - virtualTaskEndTimestamp: performance.now() + virtualTaskEndTimestamp: performance.now(), } } pool.setWorkerChoiceStrategy(workerChoiceStrategy) @@ -1491,7 +1491,7 @@ describe('Selection strategies test suite', () => { ) expect(pool.workerChoiceStrategiesContext.getPolicy()).toStrictEqual({ dynamicWorkerUsage: false, - dynamicWorkerReady: true + dynamicWorkerReady: true, }) await pool.destroy() pool = new DynamicThreadPool( @@ -1502,7 +1502,7 @@ describe('Selection strategies test suite', () => { ) expect(pool.workerChoiceStrategiesContext.getPolicy()).toStrictEqual({ dynamicWorkerUsage: false, - dynamicWorkerReady: true + dynamicWorkerReady: true, }) // We need to clean up the resources after our test await pool.destroy() @@ -1521,18 +1521,18 @@ describe('Selection strategies test suite', () => { runTime: { aggregate: true, average: true, - median: false + median: false, }, waitTime: { aggregate: true, average: true, - median: false + median: false, }, elu: { aggregate: false, average: false, - median: false - } + median: false, + }, }) await pool.destroy() pool = new DynamicThreadPool( @@ -1547,18 +1547,18 @@ describe('Selection strategies test suite', () => { runTime: { aggregate: true, average: true, - median: false + median: false, }, waitTime: { aggregate: true, average: true, - median: false + median: false, }, elu: { aggregate: false, average: false, - median: false - } + median: false, + }, }) // We need to clean up the resources after our test await pool.destroy() @@ -1586,22 +1586,22 @@ describe('Selection strategies test suite', () => { maxQueued: 0, sequentiallyStolen: 0, stolen: 0, - failed: 0 + failed: 0, }, runTime: expect.objectContaining({ - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }), waitTime: expect.objectContaining({ - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }), elu: { idle: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, active: { - history: new CircularArray() - } - } + history: expect.any(CircularBuffer), + }, + }, }) expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0) expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual( @@ -1670,22 +1670,22 @@ describe('Selection strategies test suite', () => { maxQueued: 0, sequentiallyStolen: 0, stolen: 0, - failed: 0 + failed: 0, }, runTime: expect.objectContaining({ - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }), waitTime: expect.objectContaining({ - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }), elu: { idle: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, active: { - history: new CircularArray() - } - } + history: expect.any(CircularBuffer), + }, + }, }) expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0) expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual( @@ -1739,8 +1739,8 @@ describe('Selection strategies test suite', () => { { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN, workerChoiceStrategyOptions: { - runTime: { median: true } - } + runTime: { median: true }, + }, } ) // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose` @@ -1759,22 +1759,22 @@ describe('Selection strategies test suite', () => { maxQueued: 0, sequentiallyStolen: 0, stolen: 0, - failed: 0 + failed: 0, }, runTime: expect.objectContaining({ - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }), waitTime: expect.objectContaining({ - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }), elu: { idle: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, active: { - history: new CircularArray() - } - } + history: expect.any(CircularBuffer), + }, + }, }) expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0) expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual( @@ -1898,7 +1898,7 @@ describe('Selection strategies test suite', () => { ) expect(pool.workerChoiceStrategiesContext.getPolicy()).toStrictEqual({ dynamicWorkerUsage: false, - dynamicWorkerReady: true + dynamicWorkerReady: true, }) await pool.destroy() pool = new DynamicThreadPool( @@ -1909,7 +1909,7 @@ describe('Selection strategies test suite', () => { ) expect(pool.workerChoiceStrategiesContext.getPolicy()).toStrictEqual({ dynamicWorkerUsage: false, - dynamicWorkerReady: true + dynamicWorkerReady: true, }) // We need to clean up the resources after our test await pool.destroy() @@ -1929,18 +1929,18 @@ describe('Selection strategies test suite', () => { runTime: { aggregate: true, average: true, - median: false + median: false, }, waitTime: { aggregate: true, average: true, - median: false + median: false, }, elu: { aggregate: false, average: false, - median: false - } + median: false, + }, }) await pool.destroy() pool = new DynamicThreadPool( @@ -1955,18 +1955,18 @@ describe('Selection strategies test suite', () => { runTime: { aggregate: true, average: true, - median: false + median: false, }, waitTime: { aggregate: true, average: true, - median: false + median: false, }, elu: { aggregate: false, average: false, - median: false - } + median: false, + }, }) // We need to clean up the resources after our test await pool.destroy() @@ -1978,7 +1978,7 @@ describe('Selection strategies test suite', () => { './tests/worker-files/thread/testWorker.mjs', { workerChoiceStrategy: - WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN + WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN, } ) // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose` @@ -1997,22 +1997,22 @@ describe('Selection strategies test suite', () => { maxQueued: 0, sequentiallyStolen: 0, stolen: 0, - failed: 0 + failed: 0, }, runTime: expect.objectContaining({ - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }), waitTime: expect.objectContaining({ - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }), elu: { idle: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, active: { - history: new CircularArray() - } - } + history: expect.any(CircularBuffer), + }, + }, }) expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0) expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual( @@ -2082,7 +2082,7 @@ describe('Selection strategies test suite', () => { './tests/worker-files/thread/testWorker.mjs', { workerChoiceStrategy: - WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN + WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN, } ) // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose` @@ -2101,22 +2101,22 @@ describe('Selection strategies test suite', () => { maxQueued: 0, sequentiallyStolen: 0, stolen: 0, - failed: 0 + failed: 0, }, runTime: expect.objectContaining({ - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }), waitTime: expect.objectContaining({ - history: expect.any(CircularArray) + history: expect.any(CircularBuffer), }), elu: { idle: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, active: { - history: new CircularArray() - } - } + history: expect.any(CircularBuffer), + }, + }, }) expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0) expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual( diff --git a/tests/pools/selection-strategies/worker-choice-strategies-context.test.mjs b/tests/pools/selection-strategies/worker-choice-strategies-context.test.mjs index 8fcd90b2..e046af55 100644 --- a/tests/pools/selection-strategies/worker-choice-strategies-context.test.mjs +++ b/tests/pools/selection-strategies/worker-choice-strategies-context.test.mjs @@ -4,7 +4,7 @@ import { createStubInstance, restore, stub } from 'sinon' import { DynamicThreadPool, FixedThreadPool, - WorkerChoiceStrategies + WorkerChoiceStrategies, } from '../../../lib/index.cjs' import { FairShareWorkerChoiceStrategy } from '../../../lib/pools/selection-strategies/fair-share-worker-choice-strategy.cjs' import { InterleavedWeightedRoundRobinWorkerChoiceStrategy } from '../../../lib/pools/selection-strategies/interleaved-weighted-round-robin-worker-choice-strategy.cjs' @@ -87,7 +87,7 @@ describe('Worker choice strategies context test suite', () => { const workerChoiceStrategyUndefinedStub = createStubInstance( RoundRobinWorkerChoiceStrategy, { - choose: stub().returns(undefined) + choose: stub().returns(undefined), } ) workerChoiceStrategiesContext.workerChoiceStrategies.set( @@ -102,7 +102,7 @@ describe('Worker choice strategies context test suite', () => { const workerChoiceStrategyNullStub = createStubInstance( RoundRobinWorkerChoiceStrategy, { - choose: stub().returns(null) + choose: stub().returns(null), } ) workerChoiceStrategiesContext.workerChoiceStrategies.set( @@ -134,7 +134,7 @@ describe('Worker choice strategies context test suite', () => { .returns(undefined) .onCall(4) .returns(undefined) - .returns(1) + .returns(1), } ) expect(workerChoiceStrategiesContext.defaultWorkerChoiceStrategy).toBe( @@ -160,7 +160,7 @@ describe('Worker choice strategies context test suite', () => { const workerChoiceStrategyStub = createStubInstance( RoundRobinWorkerChoiceStrategy, { - choose: stub().returns(0) + choose: stub().returns(0), } ) expect(workerChoiceStrategiesContext.defaultWorkerChoiceStrategy).toBe( @@ -186,7 +186,7 @@ describe('Worker choice strategies context test suite', () => { const workerChoiceStrategyStub = createStubInstance( RoundRobinWorkerChoiceStrategy, { - choose: stub().returns(0) + choose: stub().returns(0), } ) expect(workerChoiceStrategiesContext.defaultWorkerChoiceStrategy).toBe( @@ -417,7 +417,8 @@ describe('Worker choice strategies context test suite', () => { fixedPool, [wwrWorkerChoiceStrategy], { - runTime: { median: true } + runTime: { median: true }, + waitTime: { median: true }, } ) expect( @@ -428,11 +429,20 @@ describe('Worker choice strategies context test suite', () => { workerChoiceStrategiesContext.getTaskStatisticsRequirements().runTime .median ).toBe(true) + expect( + workerChoiceStrategiesContext.getTaskStatisticsRequirements().waitTime + .average + ).toBe(false) + expect( + workerChoiceStrategiesContext.getTaskStatisticsRequirements().waitTime + .median + ).toBe(true) workerChoiceStrategiesContext = new WorkerChoiceStrategiesContext( dynamicPool, [wwrWorkerChoiceStrategy], { - runTime: { median: true } + runTime: { median: true }, + waitTime: { median: true }, } ) expect( @@ -443,12 +453,21 @@ describe('Worker choice strategies context test suite', () => { workerChoiceStrategiesContext.getTaskStatisticsRequirements().runTime .median ).toBe(true) + expect( + workerChoiceStrategiesContext.getTaskStatisticsRequirements().waitTime + .average + ).toBe(false) + expect( + workerChoiceStrategiesContext.getTaskStatisticsRequirements().waitTime + .median + ).toBe(true) const fsWorkerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE workerChoiceStrategiesContext = new WorkerChoiceStrategiesContext( fixedPool, [fsWorkerChoiceStrategy], { - runTime: { median: true } + runTime: { median: true }, + waitTime: { median: true }, } ) expect( @@ -459,11 +478,20 @@ describe('Worker choice strategies context test suite', () => { workerChoiceStrategiesContext.getTaskStatisticsRequirements().runTime .median ).toBe(true) + expect( + workerChoiceStrategiesContext.getTaskStatisticsRequirements().waitTime + .average + ).toBe(false) + expect( + workerChoiceStrategiesContext.getTaskStatisticsRequirements().waitTime + .median + ).toBe(true) workerChoiceStrategiesContext = new WorkerChoiceStrategiesContext( dynamicPool, [fsWorkerChoiceStrategy], { - runTime: { median: true } + runTime: { median: true }, + waitTime: { median: true }, } ) expect( @@ -474,5 +502,13 @@ describe('Worker choice strategies context test suite', () => { workerChoiceStrategiesContext.getTaskStatisticsRequirements().runTime .median ).toBe(true) + expect( + workerChoiceStrategiesContext.getTaskStatisticsRequirements().waitTime + .average + ).toBe(false) + expect( + workerChoiceStrategiesContext.getTaskStatisticsRequirements().waitTime + .median + ).toBe(true) }) }) diff --git a/tests/pools/thread/dynamic.test.mjs b/tests/pools/thread/dynamic.test.mjs index 22d89223..97bfbbfc 100644 --- a/tests/pools/thread/dynamic.test.mjs +++ b/tests/pools/thread/dynamic.test.mjs @@ -3,7 +3,7 @@ import { expect } from 'expect' import { DynamicThreadPool, PoolEvents, - WorkerChoiceStrategies + WorkerChoiceStrategies, } from '../../../lib/index.cjs' import { TaskFunctions } from '../../test-types.cjs' import { sleep, waitPoolEvents, waitWorkerEvents } from '../../test-utils.cjs' @@ -16,17 +16,17 @@ describe('Dynamic thread pool test suite', () => { max, './tests/worker-files/thread/testWorker.mjs', { - errorHandler: e => console.error(e) + errorHandler: e => console.error(e), } ) it('Verify that the function is executed in a worker thread', async () => { let result = await pool.execute({ - function: TaskFunctions.fibonacci + function: TaskFunctions.fibonacci, }) expect(result).toBe(354224848179262000000) result = await pool.execute({ - function: TaskFunctions.factorial + function: TaskFunctions.factorial, }) expect(result).toBe(9.33262154439441e157) }) @@ -67,14 +67,14 @@ describe('Dynamic thread pool test suite', () => { pool.emitter.on(PoolEvents.destroy, () => ++poolDestroy) expect(pool.emitter.eventNames()).toStrictEqual([ PoolEvents.busy, - PoolEvents.destroy + PoolEvents.destroy, ]) await pool.destroy() const numberOfExitEvents = await exitPromise expect(pool.started).toBe(false) expect(pool.emitter.eventNames()).toStrictEqual([ PoolEvents.busy, - PoolEvents.destroy + PoolEvents.destroy, ]) expect(pool.readyEventEmitted).toBe(false) expect(pool.workerNodes.length).toBe(0) @@ -108,7 +108,7 @@ describe('Dynamic thread pool test suite', () => { { errorHandler: e => console.error(e), onlineHandler: () => console.info('long executing worker is online'), - exitHandler: () => console.info('long executing worker exited') + exitHandler: () => console.info('long executing worker exited'), } ) expect(longRunningPool.workerNodes.length).toBe(min) @@ -136,7 +136,7 @@ describe('Dynamic thread pool test suite', () => { { errorHandler: e => console.error(e), onlineHandler: () => console.info('long executing worker is online'), - exitHandler: () => console.info('long executing worker exited') + exitHandler: () => console.info('long executing worker exited'), } ) expect(longRunningPool.workerNodes.length).toBe(min) @@ -169,12 +169,13 @@ describe('Dynamic thread pool test suite', () => { max, './tests/worker-files/thread/testWorker.mjs', { - workerChoiceStrategy + workerChoiceStrategy, } ) expect(pool.starting).toBe(false) expect(pool.readyEventEmitted).toBe(false) for (let run = 0; run < 2; run++) { + // eslint-disable-next-line @typescript-eslint/no-unused-expressions run % 2 !== 0 && pool.enableTasksQueue(true) const maxMultiplier = 4 const promises = new Set() diff --git a/tests/pools/thread/fixed.test.mjs b/tests/pools/thread/fixed.test.mjs index 3da05735..044eb808 100644 --- a/tests/pools/thread/fixed.test.mjs +++ b/tests/pools/thread/fixed.test.mjs @@ -12,7 +12,7 @@ describe('Fixed thread pool test suite', () => { numberOfThreads, './tests/worker-files/thread/testWorker.mjs', { - errorHandler: e => console.error(e) + errorHandler: e => console.error(e), } ) const queuePool = new FixedThreadPool( @@ -21,9 +21,9 @@ describe('Fixed thread pool test suite', () => { { enableTasksQueue: true, tasksQueueOptions: { - concurrency: tasksConcurrency + concurrency: tasksConcurrency, }, - errorHandler: e => console.error(e) + errorHandler: e => console.error(e), } ) const emptyPool = new FixedThreadPool( @@ -39,14 +39,14 @@ describe('Fixed thread pool test suite', () => { numberOfThreads, './tests/worker-files/thread/errorWorker.mjs', { - errorHandler: e => console.error(e) + errorHandler: e => console.error(e), } ) const asyncErrorPool = new FixedThreadPool( numberOfThreads, './tests/worker-files/thread/asyncErrorWorker.mjs', { - errorHandler: e => console.error(e) + errorHandler: e => console.error(e), } ) const asyncPool = new FixedThreadPool( @@ -66,11 +66,11 @@ describe('Fixed thread pool test suite', () => { it('Verify that the function is executed in a worker thread', async () => { let result = await pool.execute({ - function: TaskFunctions.fibonacci + function: TaskFunctions.fibonacci, }) expect(result).toBe(354224848179262000000) result = await pool.execute({ - function: TaskFunctions.factorial + function: TaskFunctions.factorial, }) expect(result).toBe(9.33262154439441e157) }) @@ -85,7 +85,7 @@ describe('Fixed thread pool test suite', () => { numberOfThreads, './tests/worker-files/thread/testWorker.mjs', { - errorHandler: e => console.error(e) + errorHandler: e => console.error(e), } ) expect(pool.emitter.eventNames()).toStrictEqual([]) @@ -195,7 +195,7 @@ describe('Fixed thread pool test suite', () => { try { result = await pool.execute(undefined, undefined, [ new ArrayBuffer(16), - new MessageChannel().port1 + new MessageChannel().port1, ]) } catch (e) { error = e @@ -204,7 +204,7 @@ describe('Fixed thread pool test suite', () => { expect(error).toBeUndefined() try { result = await pool.execute(undefined, undefined, [ - new SharedArrayBuffer(16) + new SharedArrayBuffer(16), ]) } catch (e) { error = e @@ -238,7 +238,7 @@ describe('Fixed thread pool test suite', () => { expect(taskError).toStrictEqual({ name: DEFAULT_TASK_NAME, message: new Error('Error Message from ThreadWorker'), - data + data, }) expect( errorPool.workerNodes.some( @@ -255,7 +255,7 @@ describe('Fixed thread pool test suite', () => { taskError = e }) expect(asyncErrorPool.emitter.eventNames()).toStrictEqual([ - PoolEvents.taskError + PoolEvents.taskError, ]) let inError try { @@ -271,7 +271,7 @@ describe('Fixed thread pool test suite', () => { expect(taskError).toStrictEqual({ name: DEFAULT_TASK_NAME, message: new Error('Error Message from ThreadWorker:async'), - data + data, }) expect( asyncErrorPool.workerNodes.some( @@ -296,14 +296,14 @@ describe('Fixed thread pool test suite', () => { pool.emitter.on(PoolEvents.destroy, () => ++poolDestroy) expect(pool.emitter.eventNames()).toStrictEqual([ PoolEvents.busy, - PoolEvents.destroy + PoolEvents.destroy, ]) await pool.destroy() const numberOfExitEvents = await exitPromise expect(pool.started).toBe(false) expect(pool.emitter.eventNames()).toStrictEqual([ PoolEvents.busy, - PoolEvents.destroy + PoolEvents.destroy, ]) expect(pool.readyEventEmitted).toBe(false) expect(pool.workerNodes.length).toBe(0) @@ -319,12 +319,12 @@ describe('Fixed thread pool test suite', () => { pool = new FixedThreadPool(numberOfThreads, workerFilePath, { workerOptions: { env: { TEST: 'test' }, - name: 'test' - } + name: 'test', + }, }) expect(pool.opts.workerOptions).toStrictEqual({ env: { TEST: 'test' }, - name: 'test' + name: 'test', }) await pool.destroy() }) diff --git a/tests/pools/utils.test.mjs b/tests/pools/utils.test.mjs index cfa378e1..21ddaa77 100644 --- a/tests/pools/utils.test.mjs +++ b/tests/pools/utils.test.mjs @@ -3,10 +3,7 @@ import { Worker as ThreadWorker } from 'node:worker_threads' import { expect } from 'expect' -import { - CircularArray, - DEFAULT_CIRCULAR_ARRAY_SIZE -} from '../../lib/circular-array.cjs' +import { CircularBuffer } from '../../lib/circular-buffer.cjs' import { WorkerTypes } from '../../lib/index.cjs' import { createWorker, @@ -14,15 +11,16 @@ import { getDefaultTasksQueueOptions, getWorkerId, getWorkerType, - updateMeasurementStatistics + updateMeasurementStatistics, } from '../../lib/pools/utils.cjs' +import { MeasurementHistorySize } from '../../lib/pools/worker.cjs' describe('Pool utils test suite', () => { it('Verify DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS values', () => { expect(DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS).toStrictEqual({ aggregate: false, average: false, - median: false + median: false, }) }) @@ -32,95 +30,78 @@ describe('Pool utils test suite', () => { concurrency: 1, size: Math.pow(poolMaxSize, 2), taskStealing: true, - tasksStealingOnBackPressure: true, - tasksFinishedTimeout: 2000 + tasksStealingOnBackPressure: false, + tasksFinishedTimeout: 2000, }) }) it('Verify updateMeasurementStatistics() behavior', () => { const measurementStatistics = { - history: new CircularArray() + history: new CircularBuffer(MeasurementHistorySize), } updateMeasurementStatistics( measurementStatistics, { aggregate: true, average: false, median: false }, 0.01 ) - expect(measurementStatistics).toStrictEqual({ + expect(measurementStatistics).toMatchObject({ aggregate: 0.01, maximum: 0.01, minimum: 0.01, - history: new CircularArray() }) updateMeasurementStatistics( measurementStatistics, { aggregate: true, average: false, median: false }, 0.02 ) - expect(measurementStatistics).toStrictEqual({ + expect(measurementStatistics).toMatchObject({ aggregate: 0.03, maximum: 0.02, minimum: 0.01, - history: new CircularArray() }) updateMeasurementStatistics( measurementStatistics, { aggregate: true, average: true, median: false }, 0.001 ) - expect(measurementStatistics).toStrictEqual({ + expect(measurementStatistics).toMatchObject({ aggregate: 0.031, maximum: 0.02, minimum: 0.001, - average: 0.001, - history: new CircularArray(DEFAULT_CIRCULAR_ARRAY_SIZE, 0.001) + average: 0.0010000000474974513, }) updateMeasurementStatistics( measurementStatistics, { aggregate: true, average: true, median: false }, 0.003 ) - expect(measurementStatistics).toStrictEqual({ + expect(measurementStatistics).toMatchObject({ aggregate: 0.034, maximum: 0.02, minimum: 0.001, - average: 0.002, - history: new CircularArray(DEFAULT_CIRCULAR_ARRAY_SIZE, 0.001, 0.003) + average: 0.0020000000367872417, }) updateMeasurementStatistics( measurementStatistics, { aggregate: true, average: false, median: true }, 0.006 ) - expect(measurementStatistics).toStrictEqual({ + expect(measurementStatistics).toMatchObject({ aggregate: 0.04, maximum: 0.02, minimum: 0.001, - median: 0.003, - history: new CircularArray( - DEFAULT_CIRCULAR_ARRAY_SIZE, - 0.001, - 0.003, - 0.006 - ) + median: 0.003000000026077032, }) updateMeasurementStatistics( measurementStatistics, { aggregate: true, average: true, median: false }, 0.01 ) - expect(measurementStatistics).toStrictEqual({ + expect(measurementStatistics).toMatchObject({ aggregate: 0.05, maximum: 0.02, minimum: 0.001, - average: 0.005, - history: new CircularArray( - DEFAULT_CIRCULAR_ARRAY_SIZE, - 0.001, - 0.003, - 0.006, - 0.01 - ) + average: 0.004999999975552782, }) }) diff --git a/tests/pools/worker-node.test.mjs b/tests/pools/worker-node.test.mjs index b77af2fd..f00b8061 100644 --- a/tests/pools/worker-node.test.mjs +++ b/tests/pools/worker-node.test.mjs @@ -3,7 +3,7 @@ import { MessageChannel, Worker as ThreadWorker } from 'node:worker_threads' import { expect } from 'expect' -import { CircularArray } from '../../lib/circular-array.cjs' +import { CircularBuffer } from '../../lib/circular-buffer.cjs' import { WorkerTypes } from '../../lib/index.cjs' import { WorkerNode } from '../../lib/pools/worker-node.cjs' import { PriorityQueue } from '../../lib/priority-queue.cjs' @@ -13,12 +13,20 @@ describe('Worker node test suite', () => { const threadWorkerNode = new WorkerNode( WorkerTypes.thread, './tests/worker-files/thread/testWorker.mjs', - { tasksQueueBackPressureSize: 12 } + { + tasksQueueBackPressureSize: 12, + tasksQueueBucketSize: 6, + tasksQueuePriority: true, + } ) const clusterWorkerNode = new WorkerNode( WorkerTypes.cluster, './tests/worker-files/cluster/testWorker.cjs', - { tasksQueueBackPressureSize: 12 } + { + tasksQueueBackPressureSize: 12, + tasksQueueBucketSize: 6, + tasksQueuePriority: true, + } ) it('Worker node instantiation', () => { @@ -29,8 +37,7 @@ describe('Worker node test suite', () => { () => new WorkerNode( 'invalidWorkerType', - './tests/worker-files/thread/testWorker.mjs', - { tasksQueueBackPressureSize: 12 } + './tests/worker-files/thread/testWorker.mjs' ) ).toThrow( new TypeError( @@ -57,7 +64,7 @@ describe('Worker node test suite', () => { ) ).toThrow( new TypeError( - 'Cannot construct a worker node with invalid options: must be a plain object' + 'Cannot construct a worker node with invalid worker node options: must be a plain object' ) ) expect( @@ -120,6 +127,102 @@ describe('Worker node test suite', () => { 'Cannot construct a worker node with a tasks queue back pressure size option that is not a positive integer' ) ) + expect( + () => + new WorkerNode( + WorkerTypes.thread, + './tests/worker-files/thread/testWorker.mjs', + { + tasksQueueBackPressureSize: 12, + } + ) + ).toThrow( + new TypeError( + 'Cannot construct a worker node without a tasks queue bucket size option' + ) + ) + expect( + () => + new WorkerNode( + WorkerTypes.thread, + './tests/worker-files/thread/testWorker.mjs', + { + tasksQueueBackPressureSize: 12, + tasksQueueBucketSize: 'invalidTasksQueueBucketSize', + } + ) + ).toThrow( + new TypeError( + 'Cannot construct a worker node with a tasks queue bucket size option that is not an integer' + ) + ) + expect( + () => + new WorkerNode( + WorkerTypes.thread, + './tests/worker-files/thread/testWorker.mjs', + { tasksQueueBackPressureSize: 12, tasksQueueBucketSize: 0.2 } + ) + ).toThrow( + new TypeError( + 'Cannot construct a worker node with a tasks queue bucket size option that is not an integer' + ) + ) + expect( + () => + new WorkerNode( + WorkerTypes.thread, + './tests/worker-files/thread/testWorker.mjs', + { tasksQueueBackPressureSize: 12, tasksQueueBucketSize: 0 } + ) + ).toThrow( + new RangeError( + 'Cannot construct a worker node with a tasks queue bucket size option that is not a positive integer' + ) + ) + expect( + () => + new WorkerNode( + WorkerTypes.thread, + './tests/worker-files/thread/testWorker.mjs', + { tasksQueueBackPressureSize: 12, tasksQueueBucketSize: -1 } + ) + ).toThrow( + new RangeError( + 'Cannot construct a worker node with a tasks queue bucket size option that is not a positive integer' + ) + ) + expect( + () => + new WorkerNode( + WorkerTypes.thread, + './tests/worker-files/thread/testWorker.mjs', + { + tasksQueueBackPressureSize: 12, + tasksQueueBucketSize: 6, + } + ) + ).toThrow( + new RangeError( + 'Cannot construct a worker node without a tasks queue priority option' + ) + ) + expect( + () => + new WorkerNode( + WorkerTypes.thread, + './tests/worker-files/thread/testWorker.mjs', + { + tasksQueueBackPressureSize: 12, + tasksQueueBucketSize: 6, + tasksQueuePriority: 'invalidTasksQueuePriority', + } + ) + ).toThrow( + new RangeError( + 'Cannot construct a worker node with a tasks queue priority option that is not a boolean' + ) + ) expect(threadWorkerNode).toBeInstanceOf(WorkerNode) expect(threadWorkerNode.worker).toBeInstanceOf(ThreadWorker) expect(threadWorkerNode.info).toStrictEqual({ @@ -127,7 +230,8 @@ describe('Worker node test suite', () => { type: WorkerTypes.thread, dynamic: false, ready: false, - stealing: false + stealing: false, + backPressure: false, }) expect(threadWorkerNode.usage).toStrictEqual({ tasks: { @@ -137,31 +241,33 @@ describe('Worker node test suite', () => { maxQueued: 0, sequentiallyStolen: 0, stolen: 0, - failed: 0 + failed: 0, }, runTime: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, waitTime: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, elu: { idle: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, active: { - history: new CircularArray() - } - } + history: expect.any(CircularBuffer), + }, + }, }) expect(threadWorkerNode.messageChannel).toBeInstanceOf(MessageChannel) expect(threadWorkerNode.tasksQueueBackPressureSize).toBe(12) expect(threadWorkerNode.tasksQueue).toBeInstanceOf(PriorityQueue) expect(threadWorkerNode.tasksQueue.size).toBe(0) + expect(threadWorkerNode.tasksQueue.bucketSize).toBe(6) + expect(threadWorkerNode.tasksQueue.enablePriority).toBe(true) expect(threadWorkerNode.tasksQueueSize()).toBe( threadWorkerNode.tasksQueue.size ) - expect(threadWorkerNode.onBackPressureStarted).toBe(false) + expect(threadWorkerNode.setBackPressureFlag).toBe(false) expect(threadWorkerNode.taskFunctionsUsage).toBeInstanceOf(Map) expect(clusterWorkerNode).toBeInstanceOf(WorkerNode) @@ -171,7 +277,8 @@ describe('Worker node test suite', () => { type: WorkerTypes.cluster, dynamic: false, ready: false, - stealing: false + stealing: false, + backPressure: false, }) expect(clusterWorkerNode.usage).toStrictEqual({ tasks: { @@ -181,31 +288,33 @@ describe('Worker node test suite', () => { maxQueued: 0, sequentiallyStolen: 0, stolen: 0, - failed: 0 + failed: 0, }, runTime: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, waitTime: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, elu: { idle: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, active: { - history: new CircularArray() - } - } + history: expect.any(CircularBuffer), + }, + }, }) expect(clusterWorkerNode.messageChannel).toBeUndefined() expect(clusterWorkerNode.tasksQueueBackPressureSize).toBe(12) expect(clusterWorkerNode.tasksQueue).toBeInstanceOf(PriorityQueue) expect(clusterWorkerNode.tasksQueue.size).toBe(0) + expect(clusterWorkerNode.tasksQueue.bucketSize).toBe(6) + expect(clusterWorkerNode.tasksQueue.enablePriority).toBe(true) expect(clusterWorkerNode.tasksQueueSize()).toBe( clusterWorkerNode.tasksQueue.size ) - expect(clusterWorkerNode.onBackPressureStarted).toBe(false) + expect(clusterWorkerNode.setBackPressureFlag).toBe(false) expect(clusterWorkerNode.taskFunctionsUsage).toBeInstanceOf(Map) }) @@ -219,7 +328,7 @@ describe('Worker node test suite', () => { ) threadWorkerNode.info.taskFunctionsProperties = [ { name: DEFAULT_TASK_NAME }, - { name: 'fn1' } + { name: 'fn1' }, ] expect(() => threadWorkerNode.getTaskFunctionWorkerUsage('invalidTaskFunction') @@ -231,7 +340,7 @@ describe('Worker node test suite', () => { threadWorkerNode.info.taskFunctionsProperties = [ { name: DEFAULT_TASK_NAME }, { name: 'fn1' }, - { name: 'fn2' } + { name: 'fn2' }, ] expect( threadWorkerNode.getTaskFunctionWorkerUsage(DEFAULT_TASK_NAME) @@ -242,22 +351,22 @@ describe('Worker node test suite', () => { queued: 0, sequentiallyStolen: 0, stolen: 0, - failed: 0 + failed: 0, }, runTime: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, waitTime: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, elu: { idle: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, active: { - history: new CircularArray() - } - } + history: expect.any(CircularBuffer), + }, + }, }) expect(threadWorkerNode.getTaskFunctionWorkerUsage('fn1')).toStrictEqual({ tasks: { @@ -266,22 +375,22 @@ describe('Worker node test suite', () => { queued: 0, sequentiallyStolen: 0, stolen: 0, - failed: 0 + failed: 0, }, runTime: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, waitTime: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, elu: { idle: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, active: { - history: new CircularArray() - } - } + history: expect.any(CircularBuffer), + }, + }, }) expect(threadWorkerNode.getTaskFunctionWorkerUsage('fn2')).toStrictEqual({ tasks: { @@ -290,22 +399,22 @@ describe('Worker node test suite', () => { queued: 0, sequentiallyStolen: 0, stolen: 0, - failed: 0 + failed: 0, }, runTime: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, waitTime: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, elu: { idle: { - history: new CircularArray() + history: expect.any(CircularBuffer), }, active: { - history: new CircularArray() - } - } + history: expect.any(CircularBuffer), + }, + }, }) expect(threadWorkerNode.taskFunctionsUsage.size).toBe(2) }) @@ -314,7 +423,7 @@ describe('Worker node test suite', () => { expect(threadWorkerNode.info.taskFunctionsProperties).toStrictEqual([ { name: DEFAULT_TASK_NAME }, { name: 'fn1' }, - { name: 'fn2' } + { name: 'fn2' }, ]) expect(threadWorkerNode.taskFunctionsUsage.size).toBe(2) expect( diff --git a/tests/priority-queue.test.mjs b/tests/priority-queue.test.mjs index 58931859..839b6057 100644 --- a/tests/priority-queue.test.mjs +++ b/tests/priority-queue.test.mjs @@ -1,241 +1,312 @@ import { expect } from 'expect' -import { PriorityQueue } from '../lib/priority-queue.cjs' +import { FixedPriorityQueue } from '../lib/fixed-priority-queue.cjs' +import { defaultBucketSize, PriorityQueue } from '../lib/priority-queue.cjs' describe('Priority queue test suite', () => { it('Verify constructor() behavior', () => { expect(() => new PriorityQueue('')).toThrow( - new TypeError('k must be an integer') + new TypeError("Invalid bucket size: '' is not an integer") ) expect(() => new PriorityQueue(-1)).toThrow( - new RangeError('k must be greater than or equal to 1') - ) - expect(() => new PriorityQueue(0)).toThrow( - new RangeError('k must be greater than or equal to 1') + new RangeError('Invalid bucket size: -1 < 0') ) let priorityQueue = new PriorityQueue() - expect(priorityQueue.k).toBe(Infinity) + expect(priorityQueue.bucketSize).toBe(defaultBucketSize) + expect(priorityQueue.buckets).toBe(0) expect(priorityQueue.size).toBe(0) expect(priorityQueue.maxSize).toBe(0) - expect(priorityQueue.nodeArray).toStrictEqual([]) - priorityQueue = new PriorityQueue(2) - expect(priorityQueue.k).toBe(2) + expect(priorityQueue.enablePriority).toBe(false) + expect(priorityQueue.head).toBeInstanceOf(FixedPriorityQueue) + expect(priorityQueue.head.next).toBe(undefined) + expect(priorityQueue.head.capacity).toBe(defaultBucketSize) + expect(priorityQueue.tail).toBeInstanceOf(FixedPriorityQueue) + expect(priorityQueue.tail).toStrictEqual(priorityQueue.head) + const bucketSize = 2 + priorityQueue = new PriorityQueue(bucketSize, true) + expect(priorityQueue.bucketSize).toBe(bucketSize) + expect(priorityQueue.buckets).toBe(0) expect(priorityQueue.size).toBe(0) expect(priorityQueue.maxSize).toBe(0) - expect(priorityQueue.nodeArray).toStrictEqual([]) + expect(priorityQueue.enablePriority).toBe(true) + expect(priorityQueue.head).toBeInstanceOf(FixedPriorityQueue) + expect(priorityQueue.head.next).toBe(undefined) + expect(priorityQueue.head.capacity).toBe(bucketSize) + expect(priorityQueue.tail).toBeInstanceOf(FixedPriorityQueue) + expect(priorityQueue.tail).toStrictEqual(priorityQueue.head) }) - it('Verify default k enqueue() behavior', () => { - const priorityQueue = new PriorityQueue() + it('Verify default bucket size enqueue() behavior', () => { + const priorityQueue = new PriorityQueue(defaultBucketSize, true) let rtSize = priorityQueue.enqueue(1) + expect(priorityQueue.buckets).toBe(0) expect(priorityQueue.size).toBe(1) expect(priorityQueue.maxSize).toBe(1) expect(rtSize).toBe(priorityQueue.size) - expect(priorityQueue.nodeArray).toStrictEqual([{ data: 1, priority: 0 }]) + expect(priorityQueue.head.nodeArray).toMatchObject([ + { data: 1, priority: 0 }, + ]) + expect(priorityQueue.head.next).toBe(undefined) + expect(priorityQueue.tail).toStrictEqual(priorityQueue.head) rtSize = priorityQueue.enqueue(2) + expect(priorityQueue.buckets).toBe(0) expect(priorityQueue.size).toBe(2) expect(priorityQueue.maxSize).toBe(2) expect(rtSize).toBe(priorityQueue.size) - expect(priorityQueue.nodeArray).toStrictEqual([ + expect(priorityQueue.head.nodeArray).toMatchObject([ { data: 1, priority: 0 }, - { data: 2, priority: 0 } + { data: 2, priority: 0 }, ]) + expect(priorityQueue.head.next).toBe(undefined) + expect(priorityQueue.tail).toStrictEqual(priorityQueue.head) rtSize = priorityQueue.enqueue(3) + expect(priorityQueue.buckets).toBe(0) expect(priorityQueue.size).toBe(3) expect(priorityQueue.maxSize).toBe(3) expect(rtSize).toBe(priorityQueue.size) - expect(priorityQueue.nodeArray).toStrictEqual([ + expect(priorityQueue.head.nodeArray).toMatchObject([ { data: 1, priority: 0 }, { data: 2, priority: 0 }, - { data: 3, priority: 0 } + { data: 3, priority: 0 }, ]) + expect(priorityQueue.head.next).toBe(undefined) + expect(priorityQueue.tail).toStrictEqual(priorityQueue.head) rtSize = priorityQueue.enqueue(3, -1) + expect(priorityQueue.buckets).toBe(0) expect(priorityQueue.size).toBe(4) expect(priorityQueue.maxSize).toBe(4) expect(rtSize).toBe(priorityQueue.size) - expect(priorityQueue.nodeArray).toStrictEqual([ + expect(priorityQueue.head.nodeArray).toMatchObject([ { data: 3, priority: -1 }, { data: 1, priority: 0 }, { data: 2, priority: 0 }, - { data: 3, priority: 0 } + { data: 3, priority: 0 }, ]) + expect(priorityQueue.head.next).toBe(undefined) + expect(priorityQueue.tail).toStrictEqual(priorityQueue.head) rtSize = priorityQueue.enqueue(1, 1) + expect(priorityQueue.buckets).toBe(0) expect(priorityQueue.size).toBe(5) expect(priorityQueue.maxSize).toBe(5) expect(rtSize).toBe(priorityQueue.size) - expect(priorityQueue.nodeArray).toStrictEqual([ + expect(priorityQueue.head.nodeArray).toMatchObject([ { data: 3, priority: -1 }, { data: 1, priority: 0 }, { data: 2, priority: 0 }, { data: 3, priority: 0 }, - { data: 1, priority: 1 } + { data: 1, priority: 1 }, ]) + expect(priorityQueue.head.next).toBe(undefined) + expect(priorityQueue.tail).toStrictEqual(priorityQueue.head) }) - it('Verify k=2 enqueue() behavior', () => { - const priorityQueue = new PriorityQueue(2) + it('Verify bucketSize=2 enqueue() behavior', () => { + const priorityQueue = new PriorityQueue(2, true) let rtSize = priorityQueue.enqueue(1) + expect(priorityQueue.buckets).toBe(0) expect(priorityQueue.size).toBe(1) expect(priorityQueue.maxSize).toBe(1) expect(rtSize).toBe(priorityQueue.size) - expect(priorityQueue.nodeArray).toStrictEqual([{ data: 1, priority: 0 }]) + expect(priorityQueue.head.nodeArray).toMatchObject([ + { data: 1, priority: 0 }, + ]) + expect(priorityQueue.head.next).toBe(undefined) + expect(priorityQueue.tail).toStrictEqual(priorityQueue.head) rtSize = priorityQueue.enqueue(2) + expect(priorityQueue.buckets).toBe(1) expect(priorityQueue.size).toBe(2) expect(priorityQueue.maxSize).toBe(2) expect(rtSize).toBe(priorityQueue.size) - expect(priorityQueue.nodeArray).toStrictEqual([ + expect(priorityQueue.head.nodeArray).toMatchObject([ { data: 1, priority: 0 }, - { data: 2, priority: 0 } + { data: 2, priority: 0 }, ]) + expect(priorityQueue.head.next).toBe(undefined) + expect(priorityQueue.tail).toStrictEqual(priorityQueue.head) rtSize = priorityQueue.enqueue(3) + expect(priorityQueue.buckets).toBe(1) expect(priorityQueue.size).toBe(3) expect(priorityQueue.maxSize).toBe(3) expect(rtSize).toBe(priorityQueue.size) - expect(priorityQueue.nodeArray).toStrictEqual([ + expect(priorityQueue.head.nodeArray).toMatchObject([ + { data: 3, priority: 0 }, + ]) + expect(priorityQueue.head.next).toBe(undefined) + expect(priorityQueue.tail.nodeArray).toMatchObject([ { data: 1, priority: 0 }, { data: 2, priority: 0 }, - { data: 3, priority: 0 } ]) + expect(priorityQueue.tail.next).toStrictEqual(priorityQueue.head) rtSize = priorityQueue.enqueue(3, -1) + expect(priorityQueue.buckets).toBe(2) expect(priorityQueue.size).toBe(4) expect(priorityQueue.maxSize).toBe(4) expect(rtSize).toBe(priorityQueue.size) - expect(priorityQueue.nodeArray).toStrictEqual([ + expect(priorityQueue.head.nodeArray).toMatchObject([ + { data: 3, priority: -1 }, + { data: 3, priority: 0 }, + ]) + expect(priorityQueue.head.next).toBe(undefined) + expect(priorityQueue.tail.nodeArray).toMatchObject([ { data: 1, priority: 0 }, { data: 2, priority: 0 }, - { data: 3, priority: -1 }, - { data: 3, priority: 0 } ]) + expect(priorityQueue.tail.next).toStrictEqual(priorityQueue.head) rtSize = priorityQueue.enqueue(1, 1) + expect(priorityQueue.buckets).toBe(2) expect(priorityQueue.size).toBe(5) expect(priorityQueue.maxSize).toBe(5) expect(rtSize).toBe(priorityQueue.size) - expect(priorityQueue.nodeArray).toStrictEqual([ + expect(priorityQueue.head.nodeArray).toMatchObject([ + { data: 1, priority: 1 }, + ]) + expect(priorityQueue.head.next).toBe(undefined) + expect(priorityQueue.tail.nodeArray).toMatchObject([ { data: 1, priority: 0 }, { data: 2, priority: 0 }, + ]) + expect(priorityQueue.tail.next).not.toStrictEqual(priorityQueue.head) + expect(priorityQueue.tail.next.nodeArray).toMatchObject([ { data: 3, priority: -1 }, { data: 3, priority: 0 }, - { data: 1, priority: 1 } ]) rtSize = priorityQueue.enqueue(3, -2) + expect(priorityQueue.buckets).toBe(3) expect(priorityQueue.size).toBe(6) expect(priorityQueue.maxSize).toBe(6) expect(rtSize).toBe(priorityQueue.size) - expect(priorityQueue.nodeArray).toStrictEqual([ + expect(priorityQueue.head.nodeArray).toMatchObject([ + { data: 3, priority: -2 }, + { data: 1, priority: 1 }, + ]) + expect(priorityQueue.head.next).toBe(undefined) + expect(priorityQueue.tail.nodeArray).toMatchObject([ { data: 1, priority: 0 }, { data: 2, priority: 0 }, + ]) + expect(priorityQueue.tail.next).not.toStrictEqual(priorityQueue.head) + expect(priorityQueue.tail.next.nodeArray).toMatchObject([ { data: 3, priority: -1 }, { data: 3, priority: 0 }, - { data: 3, priority: -2 }, - { data: 1, priority: 1 } ]) }) - it('Verify default k dequeue() behavior', () => { - const priorityQueue = new PriorityQueue() + it('Verify default bucket size dequeue() behavior', () => { + const priorityQueue = new PriorityQueue(defaultBucketSize, true) priorityQueue.enqueue(1) priorityQueue.enqueue(2, -1) priorityQueue.enqueue(3) + expect(priorityQueue.buckets).toBe(0) + expect(priorityQueue.size).toBe(3) + expect(priorityQueue.maxSize).toBe(3) + expect(priorityQueue.tail.empty()).toBe(false) + expect(priorityQueue.tail.next).toBe(undefined) let rtItem = priorityQueue.dequeue() + expect(priorityQueue.buckets).toBe(0) expect(priorityQueue.size).toBe(2) expect(priorityQueue.maxSize).toBe(3) expect(rtItem).toBe(2) - expect(priorityQueue.nodeArray).toStrictEqual([ - { data: 1, priority: 0 }, - { data: 3, priority: 0 } - ]) + expect(priorityQueue.tail.empty()).toBe(false) + expect(priorityQueue.tail.next).toBe(undefined) rtItem = priorityQueue.dequeue() + expect(priorityQueue.buckets).toBe(0) expect(priorityQueue.size).toBe(1) expect(priorityQueue.maxSize).toBe(3) expect(rtItem).toBe(1) - expect(priorityQueue.nodeArray).toStrictEqual([{ data: 3, priority: 0 }]) + expect(priorityQueue.tail.empty()).toBe(false) + expect(priorityQueue.tail.next).toBe(undefined) rtItem = priorityQueue.dequeue() + expect(priorityQueue.buckets).toBe(0) expect(priorityQueue.size).toBe(0) expect(priorityQueue.maxSize).toBe(3) expect(rtItem).toBe(3) - expect(priorityQueue.nodeArray).toStrictEqual([]) + expect(priorityQueue.tail.empty()).toBe(true) + expect(priorityQueue.tail.next).toBe(undefined) }) - it('Verify k=2 dequeue() behavior', () => { - const priorityQueue = new PriorityQueue(2) + it('Verify bucketSize=2 dequeue() behavior', () => { + const priorityQueue = new PriorityQueue(2, true) priorityQueue.enqueue(1) priorityQueue.enqueue(2) priorityQueue.enqueue(3) priorityQueue.enqueue(3, -1) priorityQueue.enqueue(1, 1) priorityQueue.enqueue(3, -2) + expect(priorityQueue.buckets).toBe(3) + expect(priorityQueue.size).toBe(6) + expect(priorityQueue.maxSize).toBe(6) + expect(priorityQueue.tail.empty()).toBe(false) + expect(priorityQueue.tail.next).toBeInstanceOf(FixedPriorityQueue) let rtItem = priorityQueue.dequeue(3) + expect(priorityQueue.buckets).toBe(2) expect(priorityQueue.size).toBe(5) expect(priorityQueue.maxSize).toBe(6) expect(rtItem).toBe(3) - expect(priorityQueue.nodeArray).toStrictEqual([ - { data: 1, priority: 0 }, - { data: 2, priority: 0 }, - { data: 3, priority: -1 }, - { data: 3, priority: 0 }, - { data: 1, priority: 1 } - ]) + expect(priorityQueue.tail.empty()).toBe(false) + expect(priorityQueue.tail.next).toBeInstanceOf(FixedPriorityQueue) rtItem = priorityQueue.dequeue() + expect(priorityQueue.buckets).toBe(2) expect(priorityQueue.size).toBe(4) expect(priorityQueue.maxSize).toBe(6) expect(rtItem).toBe(1) - expect(priorityQueue.nodeArray).toStrictEqual([ - { data: 2, priority: 0 }, - { data: 3, priority: -1 }, - { data: 3, priority: 0 }, - { data: 1, priority: 1 } - ]) + expect(priorityQueue.tail.empty()).toBe(false) + expect(priorityQueue.tail.next).toBeInstanceOf(FixedPriorityQueue) rtItem = priorityQueue.dequeue(2) + expect(priorityQueue.buckets).toBe(1) expect(priorityQueue.size).toBe(3) expect(priorityQueue.maxSize).toBe(6) expect(rtItem).toBe(3) - expect(priorityQueue.nodeArray).toStrictEqual([ - { data: 2, priority: 0 }, - { data: 3, priority: -1 }, - { data: 1, priority: 1 } - ]) + expect(priorityQueue.tail.empty()).toBe(false) + expect(priorityQueue.tail.next).toBeInstanceOf(FixedPriorityQueue) rtItem = priorityQueue.dequeue(2) + expect(priorityQueue.buckets).toBe(1) expect(priorityQueue.size).toBe(2) expect(priorityQueue.maxSize).toBe(6) - expect(rtItem).toBe(1) - expect(priorityQueue.nodeArray).toStrictEqual([ - { data: 2, priority: 0 }, - { data: 3, priority: -1 } - ]) + expect(rtItem).toBe(3) + expect(priorityQueue.tail.empty()).toBe(false) + expect(priorityQueue.tail.next).toBeInstanceOf(FixedPriorityQueue) rtItem = priorityQueue.dequeue(2) + expect(priorityQueue.buckets).toBe(0) expect(priorityQueue.size).toBe(1) expect(priorityQueue.maxSize).toBe(6) - expect(rtItem).toBe(2) - expect(priorityQueue.nodeArray).toStrictEqual([{ data: 3, priority: -1 }]) + expect(rtItem).toBe(1) + expect(priorityQueue.tail.empty()).toBe(false) + expect(priorityQueue.tail.next).toBeInstanceOf(FixedPriorityQueue) rtItem = priorityQueue.dequeue() + expect(priorityQueue.buckets).toBe(0) expect(priorityQueue.size).toBe(0) expect(priorityQueue.maxSize).toBe(6) - expect(rtItem).toBe(3) - expect(priorityQueue.nodeArray).toStrictEqual([]) - }) - - it('Verify peekFirst() behavior', () => { - const priorityQueue = new PriorityQueue() - priorityQueue.enqueue(1) - priorityQueue.enqueue(2) - priorityQueue.enqueue(3) - expect(priorityQueue.size).toBe(3) - expect(priorityQueue.peekFirst()).toBe(1) - expect(priorityQueue.size).toBe(3) + expect(rtItem).toBe(2) + expect(priorityQueue.tail.empty()).toBe(true) + expect(priorityQueue.tail.next).toBe(undefined) }) - it('Verify peekLast() behavior', () => { - const priorityQueue = new PriorityQueue() + it('Verify enablePriority setter behavior', () => { + const priorityQueue = new PriorityQueue(2) + expect(priorityQueue.enablePriority).toBe(false) priorityQueue.enqueue(1) priorityQueue.enqueue(2) priorityQueue.enqueue(3) - expect(priorityQueue.size).toBe(3) - expect(priorityQueue.peekLast()).toBe(3) - expect(priorityQueue.size).toBe(3) + priorityQueue.enqueue(4) + let buckets = 0 + let node = priorityQueue.tail + while (node != null) { + expect(node.enablePriority).toBe(false) + node = node.next + ++buckets + } + expect(buckets).toBe(2) + priorityQueue.enablePriority = true + expect(priorityQueue.enablePriority).toBe(true) + node = priorityQueue.tail + while (node != null) { + expect(node.enablePriority).toBe(true) + node = node.next + } }) it('Verify iterator behavior', () => { - const priorityQueue = new PriorityQueue() + const priorityQueue = new PriorityQueue(2) priorityQueue.enqueue(1) priorityQueue.enqueue(2) priorityQueue.enqueue(3) @@ -247,20 +318,21 @@ describe('Priority queue test suite', () => { }) it('Verify clear() behavior', () => { - const priorityQueue = new PriorityQueue() + const priorityQueue = new PriorityQueue(2) priorityQueue.enqueue(1) priorityQueue.enqueue(2) priorityQueue.enqueue(3) + expect(priorityQueue.buckets).toBe(1) expect(priorityQueue.size).toBe(3) expect(priorityQueue.maxSize).toBe(3) - expect(priorityQueue.nodeArray).toStrictEqual([ - { data: 1, priority: 0 }, - { data: 2, priority: 0 }, - { data: 3, priority: 0 } - ]) + expect(priorityQueue.head.empty()).toBe(false) + expect(priorityQueue.tail.empty()).toBe(false) + expect(priorityQueue.tail).not.toStrictEqual(priorityQueue.head) priorityQueue.clear() + expect(priorityQueue.buckets).toBe(0) expect(priorityQueue.size).toBe(0) expect(priorityQueue.maxSize).toBe(0) - expect(priorityQueue.nodeArray).toStrictEqual([]) + expect(priorityQueue.head.empty()).toBe(true) + expect(priorityQueue.tail).toStrictEqual(priorityQueue.head) }) }) diff --git a/tests/test-types.cjs b/tests/test-types.cjs index 402aa305..707bb160 100644 --- a/tests/test-types.cjs +++ b/tests/test-types.cjs @@ -1,7 +1,7 @@ const TaskFunctions = { jsonIntegerSerialization: 'jsonIntegerSerialization', fibonacci: 'fibonacci', - factorial: 'factorial' + factorial: 'factorial', } module.exports = { TaskFunctions } diff --git a/tests/test-utils.cjs b/tests/test-utils.cjs index 4448eaf6..5006df6e 100644 --- a/tests/test-utils.cjs +++ b/tests/test-utils.cjs @@ -58,7 +58,7 @@ const sleepTaskFunction = async ( const jsonIntegerSerialization = n => { for (let i = 0; i < n; i++) { const o = { - a: i + a: i, } JSON.stringify(o) } @@ -66,8 +66,8 @@ const jsonIntegerSerialization = n => { } /** - * @param {number} n - The number of fibonacci numbers to generate. - * @returns {number} - The nth fibonacci number. + * @param n - The number of fibonacci numbers to generate. + * @returns - The nth fibonacci number. */ const fibonacci = n => { let current = 1 @@ -81,8 +81,8 @@ const fibonacci = n => { } /** - * @param {number} n - The number to calculate the factorial of. - * @returns {number} - The factorial of n. + * @param n - The number to calculate the factorial of. + * @returns - The factorial of n. */ const factorial = n => { if (n === 0 || n === 1) { @@ -117,5 +117,5 @@ module.exports = { sleep, sleepTaskFunction, waitPoolEvents, - waitWorkerEvents + waitWorkerEvents, } diff --git a/tests/utils.test.mjs b/tests/utils.test.mjs index b3c79d9c..25b4e5ae 100644 --- a/tests/utils.test.mjs +++ b/tests/utils.test.mjs @@ -19,7 +19,7 @@ import { // once, round, secureRandom, - sleep + sleep, } from '../lib/utils.cjs' describe('Utils test suite', () => { @@ -150,8 +150,7 @@ describe('Utils test suite', () => { expect(isAsyncFunction('')).toBe(false) expect(isAsyncFunction([])).toBe(false) expect(isAsyncFunction(new Date())).toBe(false) - // eslint-disable-next-line prefer-regex-literals - expect(isAsyncFunction(new RegExp('[a-z]', 'i'))).toBe(false) + expect(isAsyncFunction(/[a-z]/i)).toBe(false) expect(isAsyncFunction(new Error())).toBe(false) expect(isAsyncFunction(new Map())).toBe(false) expect(isAsyncFunction(new Set())).toBe(false) @@ -207,14 +206,14 @@ describe('Utils test suite', () => { }) it('Verify min() behavior', () => { - expect(min()).toBe(Infinity) + expect(min()).toBe(Number.POSITIVE_INFINITY) expect(min(1, 2)).toBe(1) expect(min(2, 1)).toBe(1) expect(min(1, 1)).toBe(1) }) it('Verify max() behavior', () => { - expect(max()).toBe(-Infinity) + expect(max()).toBe(Number.NEGATIVE_INFINITY) expect(max(1, 2)).toBe(2) expect(max(2, 1)).toBe(2) expect(max(1, 1)).toBe(1) diff --git a/tests/worker-files/cluster/asyncErrorWorker.cjs b/tests/worker-files/cluster/asyncErrorWorker.cjs index 022b4536..06797611 100644 --- a/tests/worker-files/cluster/asyncErrorWorker.cjs +++ b/tests/worker-files/cluster/asyncErrorWorker.cjs @@ -2,6 +2,10 @@ const { ClusterWorker, KillBehaviors } = require('../../../lib/index.cjs') const { sleepTaskFunction } = require('../../test-utils.cjs') +/** + * + * @param data + */ async function error (data) { return sleepTaskFunction( data, @@ -13,5 +17,5 @@ async function error (data) { module.exports = new ClusterWorker(error, { killBehavior: KillBehaviors.HARD, - maxInactiveTime: 500 + maxInactiveTime: 500, }) diff --git a/tests/worker-files/cluster/asyncWorker.cjs b/tests/worker-files/cluster/asyncWorker.cjs index d6806891..12897f7d 100644 --- a/tests/worker-files/cluster/asyncWorker.cjs +++ b/tests/worker-files/cluster/asyncWorker.cjs @@ -2,11 +2,15 @@ const { ClusterWorker, KillBehaviors } = require('../../../lib/index.cjs') const { sleepTaskFunction } = require('../../test-utils.cjs') +/** + * + * @param data + */ async function sleep (data) { return sleepTaskFunction(data, 2000) } module.exports = new ClusterWorker(sleep, { killBehavior: KillBehaviors.HARD, - maxInactiveTime: 500 + maxInactiveTime: 500, }) diff --git a/tests/worker-files/cluster/echoWorker.cjs b/tests/worker-files/cluster/echoWorker.cjs index 4534d985..5052e18c 100644 --- a/tests/worker-files/cluster/echoWorker.cjs +++ b/tests/worker-files/cluster/echoWorker.cjs @@ -1,10 +1,14 @@ 'use strict' const { ClusterWorker, KillBehaviors } = require('../../../lib/index.cjs') +/** + * + * @param data + */ function echo (data) { return data } module.exports = new ClusterWorker(echo, { - killBehavior: KillBehaviors.HARD + killBehavior: KillBehaviors.HARD, }) diff --git a/tests/worker-files/cluster/emptyWorker.cjs b/tests/worker-files/cluster/emptyWorker.cjs index 9c6072af..78f534ab 100644 --- a/tests/worker-files/cluster/emptyWorker.cjs +++ b/tests/worker-files/cluster/emptyWorker.cjs @@ -1,9 +1,12 @@ 'use strict' const { ClusterWorker, KillBehaviors } = require('../../../lib/index.cjs') +/** + * + */ function test () {} module.exports = new ClusterWorker(test, { killBehavior: KillBehaviors.HARD, - maxInactiveTime: 500 + maxInactiveTime: 500, }) diff --git a/tests/worker-files/cluster/errorWorker.cjs b/tests/worker-files/cluster/errorWorker.cjs index 2dcfe625..9a2695b2 100644 --- a/tests/worker-files/cluster/errorWorker.cjs +++ b/tests/worker-files/cluster/errorWorker.cjs @@ -1,11 +1,14 @@ 'use strict' const { ClusterWorker, KillBehaviors } = require('../../../lib/index.cjs') +/** + * + */ function error () { throw new Error('Error Message from ClusterWorker') } module.exports = new ClusterWorker(error, { killBehavior: KillBehaviors.HARD, - maxInactiveTime: 500 + maxInactiveTime: 500, }) diff --git a/tests/worker-files/cluster/longRunningWorkerHardBehavior.cjs b/tests/worker-files/cluster/longRunningWorkerHardBehavior.cjs index 2d7de52e..2dfaaafb 100644 --- a/tests/worker-files/cluster/longRunningWorkerHardBehavior.cjs +++ b/tests/worker-files/cluster/longRunningWorkerHardBehavior.cjs @@ -2,11 +2,15 @@ const { ClusterWorker, KillBehaviors } = require('../../../lib/index.cjs') const { sleepTaskFunction } = require('../../test-utils.cjs') +/** + * + * @param data + */ async function sleep (data) { return sleepTaskFunction(data, 50000) } module.exports = new ClusterWorker(sleep, { killBehavior: KillBehaviors.HARD, - maxInactiveTime: 500 + maxInactiveTime: 500, }) diff --git a/tests/worker-files/cluster/longRunningWorkerSoftBehavior.cjs b/tests/worker-files/cluster/longRunningWorkerSoftBehavior.cjs index 91eb2b35..4a5bf10f 100644 --- a/tests/worker-files/cluster/longRunningWorkerSoftBehavior.cjs +++ b/tests/worker-files/cluster/longRunningWorkerSoftBehavior.cjs @@ -2,10 +2,14 @@ const { ClusterWorker } = require('../../../lib/index.cjs') const { sleepTaskFunction } = require('../../test-utils.cjs') +/** + * + * @param data + */ async function sleep (data) { return sleepTaskFunction(data, 50000) } module.exports = new ClusterWorker(sleep, { - maxInactiveTime: 500 + maxInactiveTime: 500, }) diff --git a/tests/worker-files/cluster/testMultipleTaskFunctionsWorker.cjs b/tests/worker-files/cluster/testMultipleTaskFunctionsWorker.cjs index ef785aa1..0f8286a5 100644 --- a/tests/worker-files/cluster/testMultipleTaskFunctionsWorker.cjs +++ b/tests/worker-files/cluster/testMultipleTaskFunctionsWorker.cjs @@ -3,17 +3,17 @@ const { ClusterWorker, KillBehaviors } = require('../../../lib/index.cjs') const { jsonIntegerSerialization, factorial, - fibonacci + fibonacci, } = require('../../test-utils.cjs') module.exports = new ClusterWorker( { jsonIntegerSerialization: data => jsonIntegerSerialization(data.n), factorial: data => factorial(data.n), - fibonacci: data => fibonacci(data.n) + fibonacci: data => fibonacci(data.n), }, { killBehavior: KillBehaviors.HARD, - maxInactiveTime: 500 + maxInactiveTime: 500, } ) diff --git a/tests/worker-files/cluster/testTaskFunctionObjectsWorker.cjs b/tests/worker-files/cluster/testTaskFunctionObjectsWorker.cjs new file mode 100644 index 00000000..9f4f4b4f --- /dev/null +++ b/tests/worker-files/cluster/testTaskFunctionObjectsWorker.cjs @@ -0,0 +1,21 @@ +'use strict' +const { KillBehaviors, ClusterWorker } = require('../../../lib/index.cjs') +const { + factorial, + fibonacci, + jsonIntegerSerialization, +} = require('../../test-utils.cjs') + +module.exports = new ClusterWorker( + { + jsonIntegerSerialization: { + taskFunction: data => jsonIntegerSerialization(data.n), + }, + factorial: { taskFunction: data => factorial(data.n) }, + fibonacci: { taskFunction: data => fibonacci(data.n), priority: -5 }, + }, + { + killBehavior: KillBehaviors.HARD, + maxInactiveTime: 500, + } +) diff --git a/tests/worker-files/cluster/testWorker.cjs b/tests/worker-files/cluster/testWorker.cjs index fd6b2eb2..418afd7c 100644 --- a/tests/worker-files/cluster/testWorker.cjs +++ b/tests/worker-files/cluster/testWorker.cjs @@ -3,6 +3,10 @@ const { ClusterWorker, KillBehaviors } = require('../../../lib/index.cjs') const { executeTaskFunction } = require('../../test-utils.cjs') const { TaskFunctions } = require('../../test-types.cjs') +/** + * + * @param data + */ function test (data) { data = data || {} data.function = data.function || TaskFunctions.jsonIntegerSerialization @@ -11,5 +15,5 @@ function test (data) { module.exports = new ClusterWorker(test, { killBehavior: KillBehaviors.HARD, - maxInactiveTime: 500 + maxInactiveTime: 500, }) diff --git a/tests/worker-files/thread/asyncErrorWorker.mjs b/tests/worker-files/thread/asyncErrorWorker.mjs index 9624b6d8..c6fa8910 100644 --- a/tests/worker-files/thread/asyncErrorWorker.mjs +++ b/tests/worker-files/thread/asyncErrorWorker.mjs @@ -17,5 +17,5 @@ async function error (data) { export default new ThreadWorker(error, { killBehavior: KillBehaviors.HARD, - maxInactiveTime: 500 + maxInactiveTime: 500, }) diff --git a/tests/worker-files/thread/asyncWorker.mjs b/tests/worker-files/thread/asyncWorker.mjs index 623d517d..63db364a 100644 --- a/tests/worker-files/thread/asyncWorker.mjs +++ b/tests/worker-files/thread/asyncWorker.mjs @@ -12,5 +12,5 @@ async function sleep (data) { export default new ThreadWorker(sleep, { killBehavior: KillBehaviors.HARD, - maxInactiveTime: 500 + maxInactiveTime: 500, }) diff --git a/tests/worker-files/thread/echoWorker.mjs b/tests/worker-files/thread/echoWorker.mjs index 9a8ae66e..e1ac41ee 100644 --- a/tests/worker-files/thread/echoWorker.mjs +++ b/tests/worker-files/thread/echoWorker.mjs @@ -10,5 +10,5 @@ function echo (data) { } export default new ThreadWorker(echo, { - killBehavior: KillBehaviors.HARD + killBehavior: KillBehaviors.HARD, }) diff --git a/tests/worker-files/thread/emptyWorker.mjs b/tests/worker-files/thread/emptyWorker.mjs index ad4d52bc..7d37eb95 100644 --- a/tests/worker-files/thread/emptyWorker.mjs +++ b/tests/worker-files/thread/emptyWorker.mjs @@ -7,5 +7,5 @@ function test () {} export default new ThreadWorker(test, { killBehavior: KillBehaviors.HARD, - maxInactiveTime: 500 + maxInactiveTime: 500, }) diff --git a/tests/worker-files/thread/errorWorker.mjs b/tests/worker-files/thread/errorWorker.mjs index ec866743..582d094e 100644 --- a/tests/worker-files/thread/errorWorker.mjs +++ b/tests/worker-files/thread/errorWorker.mjs @@ -9,5 +9,5 @@ function error () { export default new ThreadWorker(error, { killBehavior: KillBehaviors.HARD, - maxInactiveTime: 500 + maxInactiveTime: 500, }) diff --git a/tests/worker-files/thread/longRunningWorkerHardBehavior.mjs b/tests/worker-files/thread/longRunningWorkerHardBehavior.mjs index 3d58ab45..1762947a 100644 --- a/tests/worker-files/thread/longRunningWorkerHardBehavior.mjs +++ b/tests/worker-files/thread/longRunningWorkerHardBehavior.mjs @@ -12,5 +12,5 @@ async function sleep (data) { export default new ThreadWorker(sleep, { killBehavior: KillBehaviors.HARD, - maxInactiveTime: 500 + maxInactiveTime: 500, }) diff --git a/tests/worker-files/thread/longRunningWorkerSoftBehavior.mjs b/tests/worker-files/thread/longRunningWorkerSoftBehavior.mjs index 4b7c1500..ae98f767 100644 --- a/tests/worker-files/thread/longRunningWorkerSoftBehavior.mjs +++ b/tests/worker-files/thread/longRunningWorkerSoftBehavior.mjs @@ -11,5 +11,5 @@ async function sleep (data) { } export default new ThreadWorker(sleep, { - maxInactiveTime: 500 + maxInactiveTime: 500, }) diff --git a/tests/worker-files/thread/testMultipleTaskFunctionsWorker.mjs b/tests/worker-files/thread/testMultipleTaskFunctionsWorker.mjs index 94e548ef..7928ab02 100644 --- a/tests/worker-files/thread/testMultipleTaskFunctionsWorker.mjs +++ b/tests/worker-files/thread/testMultipleTaskFunctionsWorker.mjs @@ -2,17 +2,17 @@ import { KillBehaviors, ThreadWorker } from '../../../lib/index.cjs' import { factorial, fibonacci, - jsonIntegerSerialization + jsonIntegerSerialization, } from '../../test-utils.cjs' export default new ThreadWorker( { jsonIntegerSerialization: data => jsonIntegerSerialization(data.n), factorial: data => factorial(data.n), - fibonacci: data => fibonacci(data.n) + fibonacci: data => fibonacci(data.n), }, { killBehavior: KillBehaviors.HARD, - maxInactiveTime: 500 + maxInactiveTime: 500, } ) diff --git a/tests/worker-files/thread/testTaskFunctionObjectsWorker.mjs b/tests/worker-files/thread/testTaskFunctionObjectsWorker.mjs new file mode 100644 index 00000000..35cd6daf --- /dev/null +++ b/tests/worker-files/thread/testTaskFunctionObjectsWorker.mjs @@ -0,0 +1,20 @@ +import { KillBehaviors, ThreadWorker } from '../../../lib/index.cjs' +import { + factorial, + fibonacci, + jsonIntegerSerialization, +} from '../../test-utils.cjs' + +export default new ThreadWorker( + { + jsonIntegerSerialization: { + taskFunction: data => jsonIntegerSerialization(data.n), + }, + factorial: { taskFunction: data => factorial(data.n) }, + fibonacci: { taskFunction: data => fibonacci(data.n), priority: -5 }, + }, + { + killBehavior: KillBehaviors.HARD, + maxInactiveTime: 500, + } +) diff --git a/tests/worker-files/thread/testWorker.mjs b/tests/worker-files/thread/testWorker.mjs index f4840e53..67959837 100644 --- a/tests/worker-files/thread/testWorker.mjs +++ b/tests/worker-files/thread/testWorker.mjs @@ -15,5 +15,5 @@ function test (data) { export default new ThreadWorker(test, { killBehavior: KillBehaviors.HARD, - maxInactiveTime: 500 + maxInactiveTime: 500, }) diff --git a/tests/worker/abstract-worker.test.mjs b/tests/worker/abstract-worker.test.mjs index 79f85cdb..ed4fcbdb 100644 --- a/tests/worker/abstract-worker.test.mjs +++ b/tests/worker/abstract-worker.test.mjs @@ -5,7 +5,7 @@ import { ClusterWorker, KillBehaviors, ThreadWorker, - WorkerChoiceStrategies + WorkerChoiceStrategies, } from '../../lib/index.cjs' import { DEFAULT_TASK_NAME, EMPTY_FUNCTION } from '../../lib/utils.cjs' @@ -26,7 +26,7 @@ describe('Abstract worker test suite', () => { expect(worker.opts).toStrictEqual({ killBehavior: KillBehaviors.SOFT, maxInactiveTime: 60000, - killHandler: EMPTY_FUNCTION + killHandler: EMPTY_FUNCTION, }) }) @@ -71,12 +71,12 @@ describe('Abstract worker test suite', () => { const worker = new ClusterWorker(() => {}, { killBehavior: KillBehaviors.HARD, maxInactiveTime: 6000, - killHandler + killHandler, }) expect(worker.opts).toStrictEqual({ killBehavior: KillBehaviors.HARD, maxInactiveTime: 6000, - killHandler + killHandler, }) }) @@ -138,10 +138,10 @@ describe('Abstract worker test suite', () => { it('Verify that taskFunctions parameter with unique function is taken', () => { const worker = new ThreadWorker(() => {}) expect(worker.taskFunctions.get(DEFAULT_TASK_NAME)).toStrictEqual({ - taskFunction: expect.any(Function) + taskFunction: expect.any(Function), }) expect(worker.taskFunctions.get('fn1')).toStrictEqual({ - taskFunction: expect.any(Function) + taskFunction: expect.any(Function), }) expect(worker.taskFunctions.size).toBe(2) expect(worker.taskFunctions.get(DEFAULT_TASK_NAME)).toStrictEqual( @@ -184,7 +184,7 @@ describe('Abstract worker test suite', () => { expect( () => new ThreadWorker({ - fn1: { taskFunction: fn1, strategy: 'invalidStrategy' } + fn1: { taskFunction: fn1, strategy: 'invalidStrategy' }, }) ).toThrow(new Error("Invalid worker choice strategy 'invalidStrategy'")) }) @@ -198,13 +198,13 @@ describe('Abstract worker test suite', () => { } const worker = new ClusterWorker({ fn1, fn2 }) expect(worker.taskFunctions.get(DEFAULT_TASK_NAME)).toStrictEqual({ - taskFunction: expect.any(Function) + taskFunction: expect.any(Function), }) expect(worker.taskFunctions.get('fn1')).toStrictEqual({ - taskFunction: expect.any(Function) + taskFunction: expect.any(Function), }) expect(worker.taskFunctions.get('fn2')).toStrictEqual({ - taskFunction: expect.any(Function) + taskFunction: expect.any(Function), }) expect(worker.taskFunctions.size).toBe(3) expect(worker.taskFunctions.get(DEFAULT_TASK_NAME)).toStrictEqual( @@ -217,18 +217,18 @@ describe('Abstract worker test suite', () => { taskFunction: () => { return 1 }, - priority: 5 + priority: 5, } const fn2Obj = { taskFunction: () => { return 2 }, priority: 6, - strategy: WorkerChoiceStrategies.LESS_BUSY + strategy: WorkerChoiceStrategies.LESS_BUSY, } const worker = new ThreadWorker({ fn1: fn1Obj, - fn2: fn2Obj + fn2: fn2Obj, }) expect(worker.taskFunctions.get(DEFAULT_TASK_NAME)).toStrictEqual(fn1Obj) expect(worker.taskFunctions.get('fn1')).toStrictEqual(fn1Obj) @@ -242,7 +242,7 @@ describe('Abstract worker test suite', () => { it('Verify that async kill handler is called when worker is killed', () => { const killHandlerStub = stub().returns() const worker = new ClusterWorker(() => {}, { - killHandler: async () => await Promise.resolve(killHandlerStub()) + killHandler: async () => await Promise.resolve(killHandlerStub()), }) worker.isMain = false worker.handleKillMessage() @@ -265,14 +265,14 @@ describe('Abstract worker test suite', () => { const worker = new ClusterWorker({ fn1, fn2 }) expect(worker.hasTaskFunction(0)).toStrictEqual({ status: false, - error: new TypeError('name parameter is not a string') + error: new TypeError('name parameter is not a string'), }) expect(worker.hasTaskFunction('')).toStrictEqual({ status: false, - error: new TypeError('name parameter is an empty string') + error: new TypeError('name parameter is an empty string'), }) expect(worker.hasTaskFunction(DEFAULT_TASK_NAME)).toStrictEqual({ - status: true + status: true, }) expect(worker.hasTaskFunction('fn1')).toStrictEqual({ status: true }) expect(worker.hasTaskFunction('fn2')).toStrictEqual({ status: true }) @@ -292,62 +292,62 @@ describe('Abstract worker test suite', () => { const worker = new ThreadWorker(fn1) expect(worker.addTaskFunction(0, fn1)).toStrictEqual({ status: false, - error: new TypeError('name parameter is not a string') + error: new TypeError('name parameter is not a string'), }) expect(worker.addTaskFunction('', fn1)).toStrictEqual({ status: false, - error: new TypeError('name parameter is an empty string') + error: new TypeError('name parameter is an empty string'), }) expect(worker.addTaskFunction('fn2', 0)).toStrictEqual({ status: false, error: new TypeError( "taskFunction object 'taskFunction' property 'undefined' is not a function" - ) + ), }) expect(worker.addTaskFunction('fn3', '')).toStrictEqual({ status: false, error: new TypeError( "taskFunction object 'taskFunction' property 'undefined' is not a function" - ) + ), }) expect(worker.addTaskFunction('fn2', { taskFunction: 0 })).toStrictEqual({ status: false, error: new TypeError( "taskFunction object 'taskFunction' property '0' is not a function" - ) + ), }) expect(worker.addTaskFunction('fn3', { taskFunction: '' })).toStrictEqual({ status: false, error: new TypeError( "taskFunction object 'taskFunction' property '' is not a function" - ) + ), }) expect( worker.addTaskFunction('fn2', { taskFunction: () => {}, priority: -21 }) ).toStrictEqual({ status: false, - error: new RangeError("Property 'priority' must be between -20 and 19") + error: new RangeError("Property 'priority' must be between -20 and 19"), }) expect( worker.addTaskFunction('fn3', { taskFunction: () => {}, priority: 20 }) ).toStrictEqual({ status: false, - error: new RangeError("Property 'priority' must be between -20 and 19") + error: new RangeError("Property 'priority' must be between -20 and 19"), }) expect( worker.addTaskFunction('fn2', { taskFunction: () => {}, - strategy: 'invalidStrategy' + strategy: 'invalidStrategy', }) ).toStrictEqual({ status: false, - error: new Error("Invalid worker choice strategy 'invalidStrategy'") + error: new Error("Invalid worker choice strategy 'invalidStrategy'"), }) expect(worker.taskFunctions.get(DEFAULT_TASK_NAME)).toStrictEqual({ - taskFunction: expect.any(Function) + taskFunction: expect.any(Function), }) expect(worker.taskFunctions.get('fn1')).toStrictEqual({ - taskFunction: expect.any(Function) + taskFunction: expect.any(Function), }) expect(worker.taskFunctions.size).toBe(2) expect(worker.taskFunctions.get(DEFAULT_TASK_NAME)).toStrictEqual( @@ -357,17 +357,17 @@ describe('Abstract worker test suite', () => { status: false, error: new Error( 'Cannot add a task function with the default reserved name' - ) + ), }) worker.addTaskFunction('fn2', fn2) expect(worker.taskFunctions.get(DEFAULT_TASK_NAME)).toStrictEqual({ - taskFunction: expect.any(Function) + taskFunction: expect.any(Function), }) expect(worker.taskFunctions.get('fn1')).toStrictEqual({ - taskFunction: expect.any(Function) + taskFunction: expect.any(Function), }) expect(worker.taskFunctions.get('fn2')).toStrictEqual({ - taskFunction: expect.any(Function) + taskFunction: expect.any(Function), }) expect(worker.taskFunctions.size).toBe(3) expect(worker.taskFunctions.get(DEFAULT_TASK_NAME)).toStrictEqual( @@ -375,13 +375,13 @@ describe('Abstract worker test suite', () => { ) worker.addTaskFunction('fn1', fn1Replacement) expect(worker.taskFunctions.get(DEFAULT_TASK_NAME)).toStrictEqual({ - taskFunction: expect.any(Function) + taskFunction: expect.any(Function), }) expect(worker.taskFunctions.get('fn1')).toStrictEqual({ - taskFunction: expect.any(Function) + taskFunction: expect.any(Function), }) expect(worker.taskFunctions.get('fn2')).toStrictEqual({ - taskFunction: expect.any(Function) + taskFunction: expect.any(Function), }) expect(worker.taskFunctions.size).toBe(3) expect(worker.taskFunctions.get(DEFAULT_TASK_NAME)).toStrictEqual( @@ -400,7 +400,7 @@ describe('Abstract worker test suite', () => { expect(worker.listTaskFunctionsProperties()).toStrictEqual([ { name: DEFAULT_TASK_NAME }, { name: 'fn1' }, - { name: 'fn2' } + { name: 'fn2' }, ]) }) @@ -414,20 +414,20 @@ describe('Abstract worker test suite', () => { const worker = new ThreadWorker({ fn1, fn2 }) expect(worker.setDefaultTaskFunction(0, fn1)).toStrictEqual({ status: false, - error: new TypeError('name parameter is not a string') + error: new TypeError('name parameter is not a string'), }) expect(worker.setDefaultTaskFunction('', fn1)).toStrictEqual({ status: false, - error: new TypeError('name parameter is an empty string') + error: new TypeError('name parameter is an empty string'), }) expect(worker.taskFunctions.get(DEFAULT_TASK_NAME)).toStrictEqual({ - taskFunction: expect.any(Function) + taskFunction: expect.any(Function), }) expect(worker.taskFunctions.get('fn1')).toStrictEqual({ - taskFunction: expect.any(Function) + taskFunction: expect.any(Function), }) expect(worker.taskFunctions.get('fn2')).toStrictEqual({ - taskFunction: expect.any(Function) + taskFunction: expect.any(Function), }) expect(worker.taskFunctions.size).toBe(3) expect(worker.taskFunctions.get(DEFAULT_TASK_NAME)).toStrictEqual( @@ -437,13 +437,13 @@ describe('Abstract worker test suite', () => { status: false, error: new Error( 'Cannot set the default task function reserved name as the default task function' - ) + ), }) expect(worker.setDefaultTaskFunction('fn3')).toStrictEqual({ status: false, error: new Error( 'Cannot set the default task function to a non-existing task function' - ) + ), }) worker.setDefaultTaskFunction('fn1') expect(worker.taskFunctions.get(DEFAULT_TASK_NAME)).toStrictEqual( diff --git a/tests/worker/cluster-worker.test.mjs b/tests/worker/cluster-worker.test.mjs index 70d63639..2ad79113 100644 --- a/tests/worker/cluster-worker.test.mjs +++ b/tests/worker/cluster-worker.test.mjs @@ -19,12 +19,12 @@ describe('Cluster worker test suite', () => { it('Verify that sync kill handler is called when worker is killed', () => { const worker = new ClusterWorker(() => {}, { - killHandler: stub().returns() + killHandler: stub().returns(), }) worker.isMain = false worker.getMainWorker = stub().returns({ id: 1, - send: stub().returns() + send: stub().returns(), }) worker.handleKillMessage() expect(worker.getMainWorker.calledTwice).toBe(true) @@ -42,24 +42,24 @@ describe('Cluster worker test suite', () => { const worker = new ClusterWorker({ fn1, fn2 }) worker.getMainWorker = stub().returns({ id: 1, - send: stub().returns() + send: stub().returns(), }) expect(worker.removeTaskFunction(0, fn1)).toStrictEqual({ status: false, - error: new TypeError('name parameter is not a string') + error: new TypeError('name parameter is not a string'), }) expect(worker.removeTaskFunction('', fn1)).toStrictEqual({ status: false, - error: new TypeError('name parameter is an empty string') + error: new TypeError('name parameter is an empty string'), }) expect(worker.taskFunctions.get(DEFAULT_TASK_NAME)).toStrictEqual({ - taskFunction: expect.any(Function) + taskFunction: expect.any(Function), }) expect(worker.taskFunctions.get('fn1')).toStrictEqual({ - taskFunction: expect.any(Function) + taskFunction: expect.any(Function), }) expect(worker.taskFunctions.get('fn2')).toStrictEqual({ - taskFunction: expect.any(Function) + taskFunction: expect.any(Function), }) expect(worker.taskFunctions.size).toBe(3) expect(worker.taskFunctions.get(DEFAULT_TASK_NAME)).toStrictEqual( @@ -69,20 +69,20 @@ describe('Cluster worker test suite', () => { status: false, error: new Error( 'Cannot remove the task function with the default reserved name' - ) + ), }) expect(worker.removeTaskFunction('fn1')).toStrictEqual({ status: false, error: new Error( 'Cannot remove the task function used as the default task function' - ) + ), }) worker.removeTaskFunction('fn2') expect(worker.taskFunctions.get(DEFAULT_TASK_NAME)).toStrictEqual({ - taskFunction: expect.any(Function) + taskFunction: expect.any(Function), }) expect(worker.taskFunctions.get('fn1')).toStrictEqual({ - taskFunction: expect.any(Function) + taskFunction: expect.any(Function), }) expect(worker.taskFunctions.get('fn2')).toBeUndefined() expect(worker.taskFunctions.size).toBe(2) @@ -102,7 +102,7 @@ describe('Cluster worker test suite', () => { it('Verify that sendToMainWorker() method invokes the getMainWorker() and send() methods', () => { const worker = new ClusterWorker(() => {}) worker.getMainWorker = stub().returns({ - send: stub().returns() + send: stub().returns(), }) worker.sendToMainWorker({ ok: 1 }) expect(worker.getMainWorker.calledTwice).toBe(true) diff --git a/tests/worker/thread-worker.test.mjs b/tests/worker/thread-worker.test.mjs index 3151b90a..f78451f7 100644 --- a/tests/worker/thread-worker.test.mjs +++ b/tests/worker/thread-worker.test.mjs @@ -19,13 +19,13 @@ describe('Thread worker test suite', () => { it('Verify that sync kill handler is called when worker is killed', () => { const worker = new ThreadWorker(() => {}, { - killHandler: stub().returns() + killHandler: stub().returns(), }) worker.isMain = false worker.port = { postMessage: stub().returns(), unref: stub().returns(), - close: stub().returns() + close: stub().returns(), } worker.handleKillMessage() expect(worker.port.postMessage.calledOnce).toBe(true) @@ -43,24 +43,24 @@ describe('Thread worker test suite', () => { } const worker = new ThreadWorker({ fn1, fn2 }) worker.port = { - postMessage: stub().returns() + postMessage: stub().returns(), } expect(worker.removeTaskFunction(0, fn1)).toStrictEqual({ status: false, - error: new TypeError('name parameter is not a string') + error: new TypeError('name parameter is not a string'), }) expect(worker.removeTaskFunction('', fn1)).toStrictEqual({ status: false, - error: new TypeError('name parameter is an empty string') + error: new TypeError('name parameter is an empty string'), }) expect(worker.taskFunctions.get(DEFAULT_TASK_NAME)).toStrictEqual({ - taskFunction: expect.any(Function) + taskFunction: expect.any(Function), }) expect(worker.taskFunctions.get('fn1')).toStrictEqual({ - taskFunction: expect.any(Function) + taskFunction: expect.any(Function), }) expect(worker.taskFunctions.get('fn2')).toStrictEqual({ - taskFunction: expect.any(Function) + taskFunction: expect.any(Function), }) expect(worker.taskFunctions.size).toBe(3) expect(worker.taskFunctions.get(DEFAULT_TASK_NAME)).toStrictEqual( @@ -70,20 +70,20 @@ describe('Thread worker test suite', () => { status: false, error: new Error( 'Cannot remove the task function with the default reserved name' - ) + ), }) expect(worker.removeTaskFunction('fn1')).toStrictEqual({ status: false, error: new Error( 'Cannot remove the task function used as the default task function' - ) + ), }) worker.removeTaskFunction('fn2') expect(worker.taskFunctions.get(DEFAULT_TASK_NAME)).toStrictEqual({ - taskFunction: expect.any(Function) + taskFunction: expect.any(Function), }) expect(worker.taskFunctions.get('fn1')).toStrictEqual({ - taskFunction: expect.any(Function) + taskFunction: expect.any(Function), }) expect(worker.taskFunctions.get('fn2')).toBeUndefined() expect(worker.taskFunctions.size).toBe(2) diff --git a/tsdoc.json b/tsdoc.json deleted file mode 100644 index 8fcf56d9..00000000 --- a/tsdoc.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", - "extends": ["typedoc/tsdoc.json"], - "tagDefinitions": [ - { - "tagName": "@author", - "syntaxKind": "block" - }, - { - "tagName": "@since", - "syntaxKind": "block" - } - ] -} diff --git a/typedoc.mjs b/typedoc.mjs index 86f160da..cc33cb68 100644 --- a/typedoc.mjs +++ b/typedoc.mjs @@ -5,7 +5,7 @@ import { fileURLToPath } from 'node:url' try { mkdirSync(join(dirname(fileURLToPath(import.meta.url)), 'tmp'), { - recursive: true + recursive: true, }) const markdownFiles = readdirSync( join(dirname(fileURLToPath(import.meta.url)), 'docs') @@ -25,7 +25,7 @@ try { } rmSync(join(dirname(fileURLToPath(import.meta.url)), 'tmp'), { recursive: true, - force: true + force: true, }) } catch (e) { console.error(e)