Add fair sharing worker choice strategy
authorJérôme Benoit <jerome.benoit@sap.com>
Sun, 9 Oct 2022 21:07:33 +0000 (23:07 +0200)
committerJérôme Benoit <jerome.benoit@sap.com>
Sun, 9 Oct 2022 21:07:33 +0000 (23:07 +0200)
Close #339

Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
19 files changed:
.eslintrc.js
CHANGELOG.md
README.md
benchmarks/internal/bench.js
benchmarks/internal/benchmark-utils.js
benchmarks/internal/cluster/dynamic.js
benchmarks/internal/cluster/fixed.js
benchmarks/internal/cluster/worker.js
benchmarks/internal/thread/dynamic.js
benchmarks/internal/thread/fixed.js
benchmarks/internal/thread/worker.js
rollup.config.mjs
src/pools/selection-strategies/fair-share-worker-choice-strategy.ts [new file with mode: 0644]
src/pools/selection-strategies/selection-strategies-types.ts
src/pools/selection-strategies/selection-strategies-utils.ts
src/pools/selection-strategies/weighted-round-robin-choice-strategy.ts
tests/pools/selection-strategies/selection-strategies-utils.test.js
tests/pools/selection-strategies/selection-strategies.test.js
tests/pools/selection-strategies/worker-choice-strategy-context.test.js

index ff5c0f762a27a0eca3a9e12489bdb32d5aede4fe..a3f0793611f69d3c9127a29e1e9ad97452a4a494 100644 (file)
@@ -37,11 +37,14 @@ module.exports = defineConfig({
         skipWords: [
           'christopher',
           'comparator',
+          'cpu',
+          'cpus',
           'ecma',
           'enum',
           'fibonacci',
           'inheritDoc',
           'jsdoc',
+          'os',
           'poolifier',
           'readonly',
           'serializable',
index 6f55d1343b25992ce8f43349da61e69b37878139..ee9377d8b4cebb77c6be0d318b9fc151477d6261 100644 (file)
@@ -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
index f0f8fc0466d4fe6ee04a672cd16c1f0f16bcc231..9c67d340c2dca6f057a3ce7c31b00d1f44630609 100644 (file)
--- 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`
 
index bdb2f614a780e0f78f86b4ff2a2063c65ce283b7..e965574c10b32a71753a2eb260d202651a52b823 100644 (file)
@@ -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())
index debe0b1cea518fd43a53295322a314e6736c5999..6c9e23aab93f8b239d2e4505f7e30aa9bf81a16a 100644 (file)
@@ -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)
+        })
     }
   })
 }
index 3c00c50b8c7af84ebfc45f5f6cb4a2c814104c41..581bf4acf086073ed459ea6f30b65af0249ab021 100644 (file)
@@ -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
 }
index fc4cc3ac8dc545ba4b8d530401b19ac396f1f02c..548ed9f9eb1518a697069ee8d5cd68a6a2f61830 100644 (file)
@@ -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
+}
index 9817322c2870864d3b18537eae6952e50afe43e1..0235afface236f2e2492e669636d74df37770c81 100644 (file)
@@ -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 }
 }
 
index 290820778e44ec7df7d2b2f2101b9dafeef4cb8c..24740f270aafecf647825227b8bf05117eb4da54 100644 (file)
@@ -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
 }
index 617aa7e5950952c241c2c98a091e2cf8965553b6..1db9c0b6f56428ea7216d60ce448891d22b7ffa7 100644 (file)
@@ -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
+}
index 6437c0afe6e1f6a06a9383b9855e6b3cb0fb2a8d..5196ca38c9758e24120a2ac45576cbdc49d26d12 100644 (file)
@@ -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 }
 }
 
index bf1685605be7cac3593cf1c7561e4e0ce93216bd..46c1a17fd3dc78e170014ba333ca8a71fe760306 100644 (file)
@@ -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 (file)
index 0000000..f500343
--- /dev/null
@@ -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, Data, Response> {
+  /**
+   *  Worker last virtual task execution timestamp.
+   */
+  private workerLastVirtualTaskTimestamp: Map<
+    Worker,
+    WorkerVirtualTaskTimestamp
+  > = new Map<Worker, WorkerVirtualTaskTimestamp>()
+
+  /** @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
+      })
+    }
+  }
+}
index 359cfb948c6334dc507a3d0894149790aef584f9..dd545d41f590acdeada321782ee23fc51606168f 100644 (file)
@@ -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.
    */
index 34c425b3541e806b770e1693e0aee6da7217e4f8..a44ba6c6efc01cf591040c38015fc3bd8ba4d2ef 100644 (file)
@@ -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:
index cdb88016b1934f69abeff8c30aff378f8fa643d7..0adc4ed430232604e43a29aed4ef7dd5657cf2d3 100644 (file)
@@ -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.
    */
index dd240126392feb462f3f063bc272d942477b9886..1a60d119ecb763e2f6bed8aa6c6af8500c6fac18 100644 (file)
@@ -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')
index 93649c39c2c667c8b5b518e9e1067abc8ad8b2cd..b12a8df4b726438ba173f867ea59e19123f00fb1 100644 (file)
@@ -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(
index 75fcb9f25741e52d78f5b1ebcb11f65112233522..017d7db2cdb5ce2d04f6d2da48a5308ab60b8605 100644 (file)
@@ -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
+  //   )
+  // })
 })