From 23ff945ac0bc3b9bcf98c6491872cffaac805b73 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Sun, 9 Oct 2022 23:07:33 +0200 Subject: [PATCH] Add fair sharing worker choice strategy MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Close #339 Signed-off-by: Jérôme Benoit --- .eslintrc.js | 3 + CHANGELOG.md | 8 +++ README.md | 2 + benchmarks/internal/bench.js | 16 +++++ benchmarks/internal/benchmark-utils.js | 5 +- benchmarks/internal/cluster/dynamic.js | 14 ++++ benchmarks/internal/cluster/fixed.js | 18 ++++- benchmarks/internal/cluster/worker.js | 5 +- benchmarks/internal/thread/dynamic.js | 14 ++++ benchmarks/internal/thread/fixed.js | 18 ++++- benchmarks/internal/thread/worker.js | 5 +- rollup.config.mjs | 2 +- .../fair-share-worker-choice-strategy.ts | 69 +++++++++++++++++++ .../selection-strategies-types.ts | 4 ++ .../selection-strategies-utils.ts | 3 + .../weighted-round-robin-choice-strategy.ts | 2 +- .../selection-strategies-utils.test.js | 22 ++++++ .../selection-strategies.test.js | 65 +++++++++++++++++ .../worker-choice-strategy-context.test.js | 62 +++++++++++++++-- 19 files changed, 326 insertions(+), 11 deletions(-) create mode 100644 src/pools/selection-strategies/fair-share-worker-choice-strategy.ts diff --git a/.eslintrc.js b/.eslintrc.js index ff5c0f76..a3f07936 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -37,11 +37,14 @@ module.exports = defineConfig({ skipWords: [ 'christopher', 'comparator', + 'cpu', + 'cpus', 'ecma', 'enum', 'fibonacci', 'inheritDoc', 'jsdoc', + 'os', 'poolifier', 'readonly', 'serializable', diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f55d134..ee9377d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.3.0] - 2022-dd-mm + +### Added + +- Pool worker choice strategies: + - `WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN` strategy based on weighted round robin scheduling algorithm using tasks execution time for now. + - `WorkerChoiceStrategies.FAIR_SHARE` strategy based on fair share scheduling algorithm using tasks execution time for now. + ## [2.2.2] - 2022-09-10 ### Fixed diff --git a/README.md b/README.md index f0f8fc04..9c67d340 100644 --- a/README.md +++ b/README.md @@ -163,6 +163,8 @@ You can use node versions >= 12.x for thread pool, and node versions >= 16.x for - `WorkerChoiceStrategies.ROUND_ROBIN`: Submit tasks to worker in this pool in a round robbin fashion - `WorkerChoiceStrategies.LESS_RECENTLY_USED`: Submit tasks to the less recently used worker in the pool + - `WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN` Submit tasks to worker using a weighted round robin scheduling algorithm based on tasks execution time for now + - `WorkerChoiceStrategies.FAIR_SHARE`: Submit tasks to worker using a fair share tasks scheduling algorithm Default: `WorkerChoiceStrategies.ROUND_ROBIN` diff --git a/benchmarks/internal/bench.js b/benchmarks/internal/bench.js index bdb2f614..e965574c 100644 --- a/benchmarks/internal/bench.js +++ b/benchmarks/internal/bench.js @@ -1,18 +1,22 @@ const Benchmark = require('benchmark') const { dynamicClusterTest, + dynamicClusterTestFairShare, dynamicClusterTestLessRecentlyUsed } = require('./cluster/dynamic') const { fixedClusterTest, + fixedClusterTestFairShare, fixedClusterTestLessRecentlyUsed } = require('./cluster/fixed') const { dynamicThreadTest, + dynamicThreadTestFairShare, dynamicThreadTestLessRecentlyUsed } = require('./thread/dynamic') const { fixedThreadTest, + fixedThreadTestFairShare, fixedThreadTestLessRecentlyUsed } = require('./thread/fixed') const { LIST_FORMATTER } = require('./benchmark-utils') @@ -33,24 +37,36 @@ async function test () { .add('Poolifier:Fixed:ThreadPool:LessRecentlyUsed', async function () { await fixedThreadTestLessRecentlyUsed() }) + .add('Poolifier:Fixed:ThreadPool:FairShare', async function () { + await fixedThreadTestFairShare() + }) .add('Poolifier:Dynamic:ThreadPool', async function () { await dynamicThreadTest() }) .add('Poolifier:Dynamic:ThreadPool:LessRecentlyUsed', async function () { await dynamicThreadTestLessRecentlyUsed() }) + .add('Poolifier:Dynamic:ThreadPool:FairShare', async function () { + await dynamicThreadTestFairShare() + }) .add('Poolifier:Fixed:ClusterPool', async function () { await fixedClusterTest() }) .add('Poolifier:Fixed:ClusterPool:LessRecentlyUsed', async function () { await fixedClusterTestLessRecentlyUsed() }) + .add('Poolifier:Fixed:ClusterPool:FairShare', async function () { + await fixedClusterTestFairShare() + }) .add('Poolifier:Dynamic:ClusterPool', async function () { await dynamicClusterTest() }) .add('Poolifier:Dynamic:ClusterPool:LessRecentlyUsed', async function () { await dynamicClusterTestLessRecentlyUsed() }) + .add('Poolifier:Dynamic:ClusterPool:FairShare', async function () { + await dynamicClusterTestFairShare() + }) // Add listeners .on('cycle', function (event) { console.log(event.target.toString()) diff --git a/benchmarks/internal/benchmark-utils.js b/benchmarks/internal/benchmark-utils.js index debe0b1c..6c9e23aa 100644 --- a/benchmarks/internal/benchmark-utils.js +++ b/benchmarks/internal/benchmark-utils.js @@ -11,7 +11,10 @@ async function runPoolifierTest (pool, { tasks, workerData }) { } return null }) - .catch(err => console.error(err)) + .catch(err => { + console.error(err) + return reject(err) + }) } }) } diff --git a/benchmarks/internal/cluster/dynamic.js b/benchmarks/internal/cluster/dynamic.js index 3c00c50b..581bf4ac 100644 --- a/benchmarks/internal/cluster/dynamic.js +++ b/benchmarks/internal/cluster/dynamic.js @@ -20,6 +20,13 @@ const dynamicPoolLessRecentlyUsed = new DynamicClusterPool( { workerChoiceStrategy: WorkerChoiceStrategies.LESS_RECENTLY_USED } ) +const dynamicPoolFairShare = new DynamicClusterPool( + size / 2, + size * 3, + './benchmarks/internal/cluster/worker.js', + { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE } +) + async function dynamicClusterTest ( { tasks, workerData } = { tasks: numberOfTasks, workerData: { proof: 'ok' } } ) { @@ -32,7 +39,14 @@ async function dynamicClusterTestLessRecentlyUsed ( return runPoolifierTest(dynamicPoolLessRecentlyUsed, { tasks, workerData }) } +async function dynamicClusterTestFairShare ( + { tasks, workerData } = { tasks: numberOfTasks, workerData: { proof: 'ok' } } +) { + return runPoolifierTest(dynamicPoolFairShare, { tasks, workerData }) +} + module.exports = { dynamicClusterTest, + dynamicClusterTestFairShare, dynamicClusterTestLessRecentlyUsed } diff --git a/benchmarks/internal/cluster/fixed.js b/benchmarks/internal/cluster/fixed.js index fc4cc3ac..548ed9f9 100644 --- a/benchmarks/internal/cluster/fixed.js +++ b/benchmarks/internal/cluster/fixed.js @@ -18,6 +18,12 @@ const fixedPoolLessRecentlyUsed = new FixedClusterPool( { workerChoiceStrategy: WorkerChoiceStrategies.LESS_RECENTLY_USED } ) +const fixedPoolFairShare = new FixedClusterPool( + size, + './benchmarks/internal/cluster/worker.js', + { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE } +) + async function fixedClusterTest ( { tasks, workerData } = { tasks: numberOfTasks, workerData: { proof: 'ok' } } ) { @@ -30,4 +36,14 @@ async function fixedClusterTestLessRecentlyUsed ( return runPoolifierTest(fixedPoolLessRecentlyUsed, { tasks, workerData }) } -module.exports = { fixedClusterTest, fixedClusterTestLessRecentlyUsed } +async function fixedClusterTestFairShare ( + { tasks, workerData } = { tasks: numberOfTasks, workerData: { proof: 'ok' } } +) { + return runPoolifierTest(fixedPoolFairShare, { tasks, workerData }) +} + +module.exports = { + fixedClusterTest, + fixedClusterTestFairShare, + fixedClusterTestLessRecentlyUsed +} diff --git a/benchmarks/internal/cluster/worker.js b/benchmarks/internal/cluster/worker.js index 9817322c..0235affa 100644 --- a/benchmarks/internal/cluster/worker.js +++ b/benchmarks/internal/cluster/worker.js @@ -1,10 +1,13 @@ 'use strict' +const { isMaster } = require('cluster') const { ClusterWorker } = require('../../../lib/index') const { jsonIntegerSerialization } = require('../benchmark-utils') +const debug = false + function yourFunction (data) { jsonIntegerSerialization(1000) - // console.log('This is the main thread ' + isMaster) + debug === true && console.debug('This is the main thread ' + isMaster) return { ok: 1 } } diff --git a/benchmarks/internal/thread/dynamic.js b/benchmarks/internal/thread/dynamic.js index 29082077..24740f27 100644 --- a/benchmarks/internal/thread/dynamic.js +++ b/benchmarks/internal/thread/dynamic.js @@ -20,6 +20,13 @@ const dynamicPoolLessRecentlyUsed = new DynamicThreadPool( { workerChoiceStrategy: WorkerChoiceStrategies.LESS_RECENTLY_USED } ) +const dynamicPoolFairShare = new DynamicThreadPool( + size / 2, + size * 3, + './benchmarks/internal/thread/worker.js', + { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE } +) + async function dynamicThreadTest ( { tasks, workerData } = { tasks: numberOfTasks, workerData: { proof: 'ok' } } ) { @@ -32,7 +39,14 @@ async function dynamicThreadTestLessRecentlyUsed ( return runPoolifierTest(dynamicPoolLessRecentlyUsed, { tasks, workerData }) } +async function dynamicThreadTestFairShare ( + { tasks, workerData } = { tasks: numberOfTasks, workerData: { proof: 'ok' } } +) { + return runPoolifierTest(dynamicPoolFairShare, { tasks, workerData }) +} + module.exports = { dynamicThreadTest, + dynamicThreadTestFairShare, dynamicThreadTestLessRecentlyUsed } diff --git a/benchmarks/internal/thread/fixed.js b/benchmarks/internal/thread/fixed.js index 617aa7e5..1db9c0b6 100644 --- a/benchmarks/internal/thread/fixed.js +++ b/benchmarks/internal/thread/fixed.js @@ -18,6 +18,12 @@ const fixedPoolLessRecentlyUsed = new FixedThreadPool( { workerChoiceStrategy: WorkerChoiceStrategies.LESS_RECENTLY_USED } ) +const fixedPoolFairShare = new FixedThreadPool( + size, + './benchmarks/internal/thread/worker.js', + { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE } +) + async function fixedThreadTest ( { tasks, workerData } = { tasks: numberOfTasks, workerData: { proof: 'ok' } } ) { @@ -30,4 +36,14 @@ async function fixedThreadTestLessRecentlyUsed ( return runPoolifierTest(fixedPoolLessRecentlyUsed, { tasks, workerData }) } -module.exports = { fixedThreadTest, fixedThreadTestLessRecentlyUsed } +async function fixedThreadTestFairShare ( + { tasks, workerData } = { tasks: numberOfTasks, workerData: { proof: 'ok' } } +) { + return runPoolifierTest(fixedPoolFairShare, { tasks, workerData }) +} + +module.exports = { + fixedThreadTest, + fixedThreadTestFairShare, + fixedThreadTestLessRecentlyUsed +} diff --git a/benchmarks/internal/thread/worker.js b/benchmarks/internal/thread/worker.js index 6437c0af..5196ca38 100644 --- a/benchmarks/internal/thread/worker.js +++ b/benchmarks/internal/thread/worker.js @@ -1,10 +1,13 @@ 'use strict' +const { isMainThread } = require('worker_threads') const { ThreadWorker } = require('../../../lib/index') const { jsonIntegerSerialization } = require('../benchmark-utils') +const debug = false + function yourFunction (data) { jsonIntegerSerialization(1000) - // console.log('This is the main thread ' + isMainThread) + debug === true && console.debug('This is the main thread ' + isMainThread) return { ok: 1 } } diff --git a/rollup.config.mjs b/rollup.config.mjs index bf168560..46c1a17f 100644 --- a/rollup.config.mjs +++ b/rollup.config.mjs @@ -19,7 +19,7 @@ export default { ...(isDevelopmentBuild && { preserveModulesRoot: 'src' }), ...(!isDevelopmentBuild && { plugins: [terser({ numWorkers: 2 })] }) }, - external: ['async_hooks', 'cluster', 'events', 'worker_threads'], + external: ['async_hooks', 'cluster', 'events', 'os', 'worker_threads'], plugins: [ ts({ tsconfig: isDevelopmentBuild diff --git a/src/pools/selection-strategies/fair-share-worker-choice-strategy.ts b/src/pools/selection-strategies/fair-share-worker-choice-strategy.ts new file mode 100644 index 00000000..f500343f --- /dev/null +++ b/src/pools/selection-strategies/fair-share-worker-choice-strategy.ts @@ -0,0 +1,69 @@ +import type { AbstractPoolWorker } from '../abstract-pool-worker' +import { AbstractWorkerChoiceStrategy } from './abstract-worker-choice-strategy' + +/** + * Worker virtual task timestamp. + */ +type WorkerVirtualTaskTimestamp = { + start: number + end: number +} + +/** + * Selects the next worker with a fair share scheduling algorithm. + * Loosely modeled after the fair queueing algorithm: https://en.wikipedia.org/wiki/Fair_queuing. + * + * @template Worker Type of worker which manages the strategy. + * @template Data Type of data sent to the worker. This can only be serializable data. + * @template Response Type of response of execution. This can only be serializable data. + */ +export class FairShareWorkerChoiceStrategy< + Worker extends AbstractPoolWorker, + Data, + Response +> extends AbstractWorkerChoiceStrategy { + /** + * Worker last virtual task execution timestamp. + */ + private workerLastVirtualTaskTimestamp: Map< + Worker, + WorkerVirtualTaskTimestamp + > = new Map() + + /** @inheritDoc */ + public choose (): Worker { + this.updateWorkerLastVirtualTaskTimestamp() + let minWorkerVirtualTaskEndTimestamp = Infinity + let chosenWorker!: Worker + for (const worker of this.pool.workers) { + const workerLastVirtualTaskEndTimestamp = + this.workerLastVirtualTaskTimestamp.get(worker)?.end ?? 0 + if ( + workerLastVirtualTaskEndTimestamp < minWorkerVirtualTaskEndTimestamp + ) { + minWorkerVirtualTaskEndTimestamp = workerLastVirtualTaskEndTimestamp + chosenWorker = worker + } + } + return chosenWorker + } + + /** + * Compute workers last virtual task timestamp. + */ + private updateWorkerLastVirtualTaskTimestamp () { + for (const worker of this.pool.workers) { + const workerVirtualTaskStartTimestamp = Math.max( + Date.now(), + this.workerLastVirtualTaskTimestamp.get(worker)?.end ?? 0 + ) + const workerVirtualTaskEndTimestamp = + workerVirtualTaskStartTimestamp + + (this.pool.getWorkerAverageTasksRunTime(worker) ?? 0) + this.workerLastVirtualTaskTimestamp.set(worker, { + start: workerVirtualTaskStartTimestamp, + end: workerVirtualTaskEndTimestamp + }) + } + } +} diff --git a/src/pools/selection-strategies/selection-strategies-types.ts b/src/pools/selection-strategies/selection-strategies-types.ts index 359cfb94..dd545d41 100644 --- a/src/pools/selection-strategies/selection-strategies-types.ts +++ b/src/pools/selection-strategies/selection-strategies-types.ts @@ -12,6 +12,10 @@ export const WorkerChoiceStrategies = Object.freeze({ * Less recently used worker selection strategy. */ LESS_RECENTLY_USED: 'LESS_RECENTLY_USED', + /** + * Fair share worker selection strategy. + */ + FAIR_SHARE: 'FAIR_SHARE', /** * Weighted round robin worker selection strategy. */ diff --git a/src/pools/selection-strategies/selection-strategies-utils.ts b/src/pools/selection-strategies/selection-strategies-utils.ts index 34c425b3..a44ba6c6 100644 --- a/src/pools/selection-strategies/selection-strategies-utils.ts +++ b/src/pools/selection-strategies/selection-strategies-utils.ts @@ -1,5 +1,6 @@ import type { AbstractPoolWorker } from '../abstract-pool-worker' import type { IPoolInternal } from '../pool-internal' +import { FairShareWorkerChoiceStrategy } from './fair-share-worker-choice-strategy' import { LessRecentlyUsedWorkerChoiceStrategy } from './less-recently-used-worker-choice-strategy' import { RoundRobinWorkerChoiceStrategy } from './round-robin-worker-choice-strategy' import type { @@ -33,6 +34,8 @@ export class SelectionStrategiesUtils { return new RoundRobinWorkerChoiceStrategy(pool) case WorkerChoiceStrategies.LESS_RECENTLY_USED: return new LessRecentlyUsedWorkerChoiceStrategy(pool) + case WorkerChoiceStrategies.FAIR_SHARE: + return new FairShareWorkerChoiceStrategy(pool) case WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN: return new WeightedRoundRobinWorkerChoiceStrategy(pool) default: diff --git a/src/pools/selection-strategies/weighted-round-robin-choice-strategy.ts b/src/pools/selection-strategies/weighted-round-robin-choice-strategy.ts index cdb88016..0adc4ed4 100644 --- a/src/pools/selection-strategies/weighted-round-robin-choice-strategy.ts +++ b/src/pools/selection-strategies/weighted-round-robin-choice-strategy.ts @@ -45,7 +45,7 @@ export class WeightedRoundRobinWorkerChoiceStrategy< >() /** - * Constructs a worker choice strategy that selects based a weighted round robin scheduling algorithm. + * Constructs a worker choice strategy that selects with a weighted round robin scheduling algorithm. * * @param pool The pool instance. */ diff --git a/tests/pools/selection-strategies/selection-strategies-utils.test.js b/tests/pools/selection-strategies/selection-strategies-utils.test.js index dd240126..1a60d119 100644 --- a/tests/pools/selection-strategies/selection-strategies-utils.test.js +++ b/tests/pools/selection-strategies/selection-strategies-utils.test.js @@ -13,6 +13,12 @@ const { const { LessRecentlyUsedWorkerChoiceStrategy } = require('../../../lib/pools/selection-strategies/less-recently-used-worker-choice-strategy') +const { + FairShareWorkerChoiceStrategy +} = require('../../../lib/pools/selection-strategies/fair-share-worker-choice-strategy') +// const { +// WeightedRoundRobinWorkerChoiceStrategy +// } = require('../../../lib/pools/selection-strategies/weighted-round-robin-choice-strategy') describe('Selection strategies utils test suite', () => { let pool @@ -45,6 +51,22 @@ describe('Selection strategies utils test suite', () => { expect(strategy).toBeInstanceOf(LessRecentlyUsedWorkerChoiceStrategy) }) + it('Verify that getWorkerChoiceStrategy() can return FAIR_SHARE strategy', () => { + const strategy = SelectionStrategiesUtils.getWorkerChoiceStrategy( + pool, + WorkerChoiceStrategies.FAIR_SHARE + ) + expect(strategy).toBeInstanceOf(FairShareWorkerChoiceStrategy) + }) + + // it('Verify that getWorkerChoiceStrategy() can return WEIGHTED_ROUND_ROBIN strategy', () => { + // const strategy = SelectionStrategiesUtils.getWorkerChoiceStrategy( + // pool, + // WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN + // ) + // expect(strategy).toBeInstanceOf(WeightedRoundRobinWorkerChoiceStrategy) + // }) + it('Verify that getWorkerChoiceStrategy() throw error on unknown strategy', () => { expect(() => { SelectionStrategiesUtils.getWorkerChoiceStrategy(pool, 'UNKNOWN_STRATEGY') diff --git a/tests/pools/selection-strategies/selection-strategies.test.js b/tests/pools/selection-strategies/selection-strategies.test.js index 93649c39..b12a8df4 100644 --- a/tests/pools/selection-strategies/selection-strategies.test.js +++ b/tests/pools/selection-strategies/selection-strategies.test.js @@ -9,6 +9,7 @@ describe('Selection strategies test suite', () => { it('Verify that WorkerChoiceStrategies enumeration provides string values', () => { expect(WorkerChoiceStrategies.ROUND_ROBIN).toBe('ROUND_ROBIN') expect(WorkerChoiceStrategies.LESS_RECENTLY_USED).toBe('LESS_RECENTLY_USED') + expect(WorkerChoiceStrategies.FAIR_SHARE).toBe('FAIR_SHARE') expect(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN).toBe( 'WEIGHTED_ROUND_ROBIN' ) @@ -151,6 +152,70 @@ describe('Selection strategies test suite', () => { await pool.destroy() }) + it('Verify FAIR_SHARE strategy is taken at pool creation', async () => { + const max = 3 + const pool = new FixedThreadPool( + max, + './tests/worker-files/thread/testWorker.js', + { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE } + ) + expect(pool.opts.workerChoiceStrategy).toBe( + WorkerChoiceStrategies.FAIR_SHARE + ) + // We need to clean up the resources after our test + await pool.destroy() + }) + + it('Verify FAIR_SHARE strategy can be set after pool creation', async () => { + const max = 3 + const pool = new FixedThreadPool( + max, + './tests/worker-files/thread/testWorker.js' + ) + pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.FAIR_SHARE) + expect(pool.opts.workerChoiceStrategy).toBe( + WorkerChoiceStrategies.FAIR_SHARE + ) + // We need to clean up the resources after our test + await pool.destroy() + }) + + it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => { + const max = 3 + const pool = new FixedThreadPool( + max, + './tests/worker-files/thread/testWorker.js', + { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE } + ) + // TODO: Create a better test to cover `FairShareChoiceStrategy#choose` + const promises = [] + for (let i = 0; i < max * 2; i++) { + promises.push(pool.execute({ test: 'test' })) + } + await Promise.all(promises) + // We need to clean up the resources after our test + await pool.destroy() + }) + + it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => { + const min = 0 + const max = 3 + const pool = new DynamicThreadPool( + min, + max, + './tests/worker-files/thread/testWorker.js', + { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE } + ) + // TODO: Create a better test to cover `FairShareChoiceStrategy#choose` + const promises = [] + for (let i = 0; i < max * 2; i++) { + promises.push(pool.execute({ test: 'test' })) + } + await Promise.all(promises) + // We need to clean up the resources after our test + await pool.destroy() + }) + it('Verify WEIGHTED_ROUND_ROBIN strategy is taken at pool creation', async () => { const max = 3 const pool = new FixedThreadPool( diff --git a/tests/pools/selection-strategies/worker-choice-strategy-context.test.js b/tests/pools/selection-strategies/worker-choice-strategy-context.test.js index 75fcb9f2..017d7db2 100644 --- a/tests/pools/selection-strategies/worker-choice-strategy-context.test.js +++ b/tests/pools/selection-strategies/worker-choice-strategy-context.test.js @@ -5,6 +5,9 @@ const { DynamicThreadPool, WorkerChoiceStrategies } = require('../../../lib/index') +const { + WorkerChoiceStrategyContext +} = require('../../../lib/pools/selection-strategies/worker-choice-strategy-context') const { RoundRobinWorkerChoiceStrategy } = require('../../../lib/pools/selection-strategies/round-robin-worker-choice-strategy') @@ -12,8 +15,11 @@ const { LessRecentlyUsedWorkerChoiceStrategy } = require('../../../lib/pools/selection-strategies/less-recently-used-worker-choice-strategy') const { - WorkerChoiceStrategyContext -} = require('../../../lib/pools/selection-strategies/worker-choice-strategy-context') + FairShareWorkerChoiceStrategy +} = require('../../../lib/pools/selection-strategies/fair-share-worker-choice-strategy') +// const { +// WeightedRoundRobinWorkerChoiceStrategy +// } = require('../../../lib/pools/selection-strategies/weighted-round-robin-choice-strategy') const { DynamicPoolWorkerChoiceStrategy } = require('../../../lib/pools/selection-strategies/dynamic-pool-worker-choice-strategy') @@ -77,7 +83,7 @@ describe('Worker choice strategy context test suite', () => { ) }) - it('Verify that setWorkerChoiceStrategy() works with ROUND_ROBIN and fixed pool', () => { + it('Verify that setWorkerChoiceStrategy() works with ROUND_ROBIN and dynamic pool', () => { const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( dynamicPool ) @@ -101,7 +107,7 @@ describe('Worker choice strategy context test suite', () => { ) }) - it('Verify that setWorkerChoiceStrategy() works with LESS_RECENTLY_USED and fixed pool', () => { + it('Verify that setWorkerChoiceStrategy() works with LESS_RECENTLY_USED and dynamic pool', () => { const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( dynamicPool ) @@ -112,4 +118,52 @@ describe('Worker choice strategy context test suite', () => { DynamicPoolWorkerChoiceStrategy ) }) + + it('Verify that setWorkerChoiceStrategy() works with FAIR_SHARE and fixed pool', () => { + const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( + fixedPool + ) + workerChoiceStrategyContext.setWorkerChoiceStrategy( + WorkerChoiceStrategies.FAIR_SHARE + ) + expect(workerChoiceStrategyContext.workerChoiceStrategy).toBeInstanceOf( + FairShareWorkerChoiceStrategy + ) + }) + + it('Verify that setWorkerChoiceStrategy() works with FAIR_SHARE and dynamic pool', () => { + const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( + dynamicPool + ) + workerChoiceStrategyContext.setWorkerChoiceStrategy( + WorkerChoiceStrategies.FAIR_SHARE + ) + expect(workerChoiceStrategyContext.workerChoiceStrategy).toBeInstanceOf( + DynamicPoolWorkerChoiceStrategy + ) + }) + + // it('Verify that setWorkerChoiceStrategy() works with WEIGHTED_ROUND_ROBIN and fixed pool', () => { + // const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( + // fixedPool + // ) + // workerChoiceStrategyContext.setWorkerChoiceStrategy( + // WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN + // ) + // expect(workerChoiceStrategyContext.workerChoiceStrategy).toBeInstanceOf( + // WeightedRoundRobinWorkerChoiceStrategy + // ) + // }) + + // it('Verify that setWorkerChoiceStrategy() works with WEIGHTED_ROUND_ROBIN and dynamic pool', () => { + // const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( + // dynamicPool + // ) + // workerChoiceStrategyContext.setWorkerChoiceStrategy( + // WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN + // ) + // expect(workerChoiceStrategyContext.workerChoiceStrategy).toBeInstanceOf( + // DynamicPoolWorkerChoiceStrategy + // ) + // }) }) -- 2.34.1