refactor: factor out pool helpers
authorJérôme Benoit <jerome.benoit@piment-noir.org>
Tue, 19 Sep 2023 20:18:58 +0000 (22:18 +0200)
committerJérôme Benoit <jerome.benoit@piment-noir.org>
Tue, 19 Sep 2023 20:18:58 +0000 (22:18 +0200)
Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
src/pools/abstract-pool.ts
src/pools/cluster/dynamic.ts
src/pools/thread/dynamic.ts
src/pools/utils.ts [new file with mode: 0644]

index 9aeeebed772b37234c2a8f0e88c5cb45c65f0dce..ce59c992f81a08d52ba2e42c2f1b1443c9979b72 100644 (file)
@@ -1,6 +1,5 @@
 import { randomUUID } from 'node:crypto'
 import { performance } from 'node:perf_hooks'
-import { existsSync } from 'node:fs'
 import { type TransferListItem } from 'node:worker_threads'
 import type {
   MessageValue,
@@ -49,6 +48,11 @@ import {
 import { WorkerChoiceStrategyContext } from './selection-strategies/worker-choice-strategy-context'
 import { version } from './version'
 import { WorkerNode } from './worker-node'
+import {
+  checkFilePath,
+  checkValidTasksQueueOptions,
+  checkValidWorkerChoiceStrategy
+} from './utils'
 
 /**
  * Base class that implements some shared logic for all poolifier pools.
@@ -130,7 +134,7 @@ export abstract class AbstractPool<
       )
     }
     this.checkNumberOfWorkers(this.numberOfWorkers)
-    this.checkFilePath(this.filePath)
+    checkFilePath(this.filePath)
     this.checkPoolOptions(this.opts)
 
     this.chooseWorkerNode = this.chooseWorkerNode.bind(this)
@@ -163,19 +167,6 @@ export abstract class AbstractPool<
     this.startTimestamp = performance.now()
   }
 
-  private checkFilePath (filePath: string): void {
-    if (
-      filePath == null ||
-      typeof filePath !== 'string' ||
-      (typeof filePath === 'string' && filePath.trim().length === 0)
-    ) {
-      throw new Error('Please specify a file with a worker implementation')
-    }
-    if (!existsSync(filePath)) {
-      throw new Error(`Cannot find the worker file '${filePath}'`)
-    }
-  }
-
   private checkNumberOfWorkers (numberOfWorkers: number): void {
     if (numberOfWorkers == null) {
       throw new Error(
@@ -194,36 +185,10 @@ export abstract class AbstractPool<
     }
   }
 
-  protected checkDynamicPoolSize (min: number, max: number): void {
-    if (this.type === PoolTypes.dynamic) {
-      if (max == null) {
-        throw new TypeError(
-          'Cannot instantiate a dynamic pool without specifying the maximum pool size'
-        )
-      } else if (!Number.isSafeInteger(max)) {
-        throw new TypeError(
-          'Cannot instantiate a dynamic pool with a non safe integer maximum pool size'
-        )
-      } else if (min > max) {
-        throw new RangeError(
-          'Cannot instantiate a dynamic pool with a maximum pool size inferior to the minimum pool size'
-        )
-      } else if (max === 0) {
-        throw new RangeError(
-          'Cannot instantiate a dynamic pool with a maximum pool size equal to zero'
-        )
-      } else if (min === max) {
-        throw new RangeError(
-          'Cannot instantiate a dynamic pool with a minimum pool size equal to the maximum pool size. Use a fixed pool instead'
-        )
-      }
-    }
-  }
-
   private checkPoolOptions (opts: PoolOptions<Worker>): void {
     if (isPlainObject(opts)) {
       this.opts.startWorkers = opts.startWorkers ?? true
-      this.checkValidWorkerChoiceStrategy(
+      checkValidWorkerChoiceStrategy(
         opts.workerChoiceStrategy as WorkerChoiceStrategy
       )
       this.opts.workerChoiceStrategy =
@@ -239,9 +204,7 @@ export abstract class AbstractPool<
       this.opts.enableEvents = opts.enableEvents ?? true
       this.opts.enableTasksQueue = opts.enableTasksQueue ?? false
       if (this.opts.enableTasksQueue) {
-        this.checkValidTasksQueueOptions(
-          opts.tasksQueueOptions as TasksQueueOptions
-        )
+        checkValidTasksQueueOptions(opts.tasksQueueOptions as TasksQueueOptions)
         this.opts.tasksQueueOptions = this.buildTasksQueueOptions(
           opts.tasksQueueOptions as TasksQueueOptions
         )
@@ -251,19 +214,6 @@ export abstract class AbstractPool<
     }
   }
 
-  private checkValidWorkerChoiceStrategy (
-    workerChoiceStrategy: WorkerChoiceStrategy
-  ): void {
-    if (
-      workerChoiceStrategy != null &&
-      !Object.values(WorkerChoiceStrategies).includes(workerChoiceStrategy)
-    ) {
-      throw new Error(
-        `Invalid worker choice strategy '${workerChoiceStrategy}'`
-      )
-    }
-  }
-
   private checkValidWorkerChoiceStrategyOptions (
     workerChoiceStrategyOptions: WorkerChoiceStrategyOptions
   ): void {
@@ -311,43 +261,6 @@ export abstract class AbstractPool<
     }
   }
 
-  private checkValidTasksQueueOptions (
-    tasksQueueOptions: TasksQueueOptions
-  ): void {
-    if (tasksQueueOptions != null && !isPlainObject(tasksQueueOptions)) {
-      throw new TypeError('Invalid tasks queue options: must be a plain object')
-    }
-    if (
-      tasksQueueOptions?.concurrency != null &&
-      !Number.isSafeInteger(tasksQueueOptions.concurrency)
-    ) {
-      throw new TypeError(
-        'Invalid worker node tasks concurrency: must be an integer'
-      )
-    }
-    if (
-      tasksQueueOptions?.concurrency != null &&
-      tasksQueueOptions.concurrency <= 0
-    ) {
-      throw new RangeError(
-        `Invalid worker node tasks concurrency: ${tasksQueueOptions.concurrency} is a negative integer or zero`
-      )
-    }
-    if (
-      tasksQueueOptions?.size != null &&
-      !Number.isSafeInteger(tasksQueueOptions.size)
-    ) {
-      throw new TypeError(
-        'Invalid worker node tasks queue size: must be an integer'
-      )
-    }
-    if (tasksQueueOptions?.size != null && tasksQueueOptions.size <= 0) {
-      throw new RangeError(
-        `Invalid worker node tasks queue size: ${tasksQueueOptions.size} is a negative integer or zero`
-      )
-    }
-  }
-
   /** @inheritDoc */
   public get info (): PoolInfo {
     return {
@@ -614,7 +527,7 @@ export abstract class AbstractPool<
     workerChoiceStrategy: WorkerChoiceStrategy,
     workerChoiceStrategyOptions?: WorkerChoiceStrategyOptions
   ): void {
-    this.checkValidWorkerChoiceStrategy(workerChoiceStrategy)
+    checkValidWorkerChoiceStrategy(workerChoiceStrategy)
     this.opts.workerChoiceStrategy = workerChoiceStrategy
     this.workerChoiceStrategyContext.setWorkerChoiceStrategy(
       this.opts.workerChoiceStrategy
@@ -659,7 +572,7 @@ export abstract class AbstractPool<
   /** @inheritDoc */
   public setTasksQueueOptions (tasksQueueOptions: TasksQueueOptions): void {
     if (this.opts.enableTasksQueue === true) {
-      this.checkValidTasksQueueOptions(tasksQueueOptions)
+      checkValidTasksQueueOptions(tasksQueueOptions)
       this.opts.tasksQueueOptions =
         this.buildTasksQueueOptions(tasksQueueOptions)
       this.setTasksQueueSize(this.opts.tasksQueueOptions.size as number)
index b93d7e87c4290a21b8a9b8f7c2845647d05592da..99a89966e914507fa6868883a0f67c751c8b29c6 100644 (file)
@@ -1,4 +1,5 @@
 import { type PoolType, PoolTypes } from '../pool'
+import { checkDynamicPoolSize } from '../utils'
 import { type ClusterPoolOptions, FixedClusterPool } from './fixed'
 
 /**
@@ -31,7 +32,7 @@ export class DynamicClusterPool<
     opts: ClusterPoolOptions = {}
   ) {
     super(min, filePath, opts)
-    this.checkDynamicPoolSize(this.numberOfWorkers, this.max)
+    checkDynamicPoolSize(this.numberOfWorkers, this.max)
   }
 
   /** @inheritDoc */
index a34f0c25f78b1da3a306c9c07edb5c5d43f0f21b..119e556dd2ccb454fec3ed9c89c20df5d76199c2 100644 (file)
@@ -1,4 +1,5 @@
 import { type PoolType, PoolTypes } from '../pool'
+import { checkDynamicPoolSize } from '../utils'
 import { FixedThreadPool, type ThreadPoolOptions } from './fixed'
 
 /**
@@ -31,7 +32,7 @@ export class DynamicThreadPool<
     opts: ThreadPoolOptions = {}
   ) {
     super(min, filePath, opts)
-    this.checkDynamicPoolSize(this.numberOfWorkers, this.max)
+    checkDynamicPoolSize(this.numberOfWorkers, this.max)
   }
 
   /** @inheritDoc */
diff --git a/src/pools/utils.ts b/src/pools/utils.ts
new file mode 100644 (file)
index 0000000..4aac5cd
--- /dev/null
@@ -0,0 +1,92 @@
+import { existsSync } from 'node:fs'
+import { isPlainObject } from '../utils'
+import {
+  WorkerChoiceStrategies,
+  type WorkerChoiceStrategy
+} from './selection-strategies/selection-strategies-types'
+import type { TasksQueueOptions } from './pool'
+
+export const checkFilePath = (filePath: string): void => {
+  if (
+    filePath == null ||
+    typeof filePath !== 'string' ||
+    (typeof filePath === 'string' && filePath.trim().length === 0)
+  ) {
+    throw new Error('Please specify a file with a worker implementation')
+  }
+  if (!existsSync(filePath)) {
+    throw new Error(`Cannot find the worker file '${filePath}'`)
+  }
+}
+
+export const checkDynamicPoolSize = (min: number, max: number): void => {
+  if (max == null) {
+    throw new TypeError(
+      'Cannot instantiate a dynamic pool without specifying the maximum pool size'
+    )
+  } else if (!Number.isSafeInteger(max)) {
+    throw new TypeError(
+      'Cannot instantiate a dynamic pool with a non safe integer maximum pool size'
+    )
+  } else if (min > max) {
+    throw new RangeError(
+      'Cannot instantiate a dynamic pool with a maximum pool size inferior to the minimum pool size'
+    )
+  } else if (max === 0) {
+    throw new RangeError(
+      'Cannot instantiate a dynamic pool with a maximum pool size equal to zero'
+    )
+  } else if (min === max) {
+    throw new RangeError(
+      'Cannot instantiate a dynamic pool with a minimum pool size equal to the maximum pool size. Use a fixed pool instead'
+    )
+  }
+}
+
+export const checkValidWorkerChoiceStrategy = (
+  workerChoiceStrategy: WorkerChoiceStrategy
+): void => {
+  if (
+    workerChoiceStrategy != null &&
+    !Object.values(WorkerChoiceStrategies).includes(workerChoiceStrategy)
+  ) {
+    throw new Error(`Invalid worker choice strategy '${workerChoiceStrategy}'`)
+  }
+}
+
+export const checkValidTasksQueueOptions = (
+  tasksQueueOptions: TasksQueueOptions
+): void => {
+  if (tasksQueueOptions != null && !isPlainObject(tasksQueueOptions)) {
+    throw new TypeError('Invalid tasks queue options: must be a plain object')
+  }
+  if (
+    tasksQueueOptions?.concurrency != null &&
+    !Number.isSafeInteger(tasksQueueOptions.concurrency)
+  ) {
+    throw new TypeError(
+      'Invalid worker node tasks concurrency: must be an integer'
+    )
+  }
+  if (
+    tasksQueueOptions?.concurrency != null &&
+    tasksQueueOptions.concurrency <= 0
+  ) {
+    throw new RangeError(
+      `Invalid worker node tasks concurrency: ${tasksQueueOptions.concurrency} is a negative integer or zero`
+    )
+  }
+  if (
+    tasksQueueOptions?.size != null &&
+    !Number.isSafeInteger(tasksQueueOptions.size)
+  ) {
+    throw new TypeError(
+      'Invalid worker node tasks queue size: must be an integer'
+    )
+  }
+  if (tasksQueueOptions?.size != null && tasksQueueOptions.size <= 0) {
+    throw new RangeError(
+      `Invalid worker node tasks queue size: ${tasksQueueOptions.size} is a negative integer or zero`
+    )
+  }
+}