-import { isKillBehavior, KillBehaviors } from '../worker/worker-options'
import type { IWorker } from './abstract-pool'
import type { IPoolInternal } from './pool-internal'
+import { PoolType } from './pool-internal'
/**
* Enumeration of worker choice strategies.
public choose (): Worker {
const chosenWorker = this.pool.workers[this.nextWorkerIndex]
this.nextWorkerIndex =
- this.pool.workers.length - 1 === this.nextWorkerIndex
+ this.nextWorkerIndex === this.pool.workers.length - 1
? 0
: this.nextWorkerIndex + 1
return chosenWorker
/** @inheritdoc */
public choose (): Worker {
- const isPoolDynamic = this.pool.dynamic
+ const isPoolDynamic = this.pool.type === PoolType.DYNAMIC
let minNumberOfTasks = Infinity
// A worker is always found because it picks the one with fewer tasks
let lessRecentlyUsedWorker!: Worker
if (!isPoolDynamic && numberOfTasks === 0) {
return worker
} else if (numberOfTasks < minNumberOfTasks) {
- minNumberOfTasks = numberOfTasks
lessRecentlyUsedWorker = worker
+ minNumberOfTasks = numberOfTasks
}
}
return lessRecentlyUsedWorker
* Constructs a worker choice strategy for dynamical pools.
*
* @param pool The pool instance.
- * @param workerChoiceStrategy The worker choice strategy when the pull is full.
+ * @param createDynamicallyWorkerCallback The worker creation callback for dynamic pool.
+ * @param workerChoiceStrategy The worker choice strategy when the pull is busy.
*/
public constructor (
private readonly pool: IPoolInternal<Worker, Data, Response>,
+ private createDynamicallyWorkerCallback: () => Worker,
workerChoiceStrategy: WorkerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
) {
this.workerChoiceStrategy = SelectionStrategiesUtils.getWorkerChoiceStrategy(
/** @inheritdoc */
public choose (): Worker {
- const freeWorker = SelectionStrategiesUtils.findFreeWorkerBasedOnTasks(
- this.pool
- )
- if (freeWorker) {
- return freeWorker
+ const freeTaskMapEntry = this.pool.findFreeTasksMapEntry()
+ if (freeTaskMapEntry) {
+ return freeTaskMapEntry[0]
}
- if (this.pool.workers.length === this.pool.max) {
- this.pool.emitter.emit('FullPool')
+ if (this.pool.busy) {
return this.workerChoiceStrategy.choose()
}
// All workers are busy, create a new worker
- const workerCreated = this.pool.createAndSetupWorker()
- this.pool.registerWorkerMessageListener(workerCreated, message => {
- const tasksInProgress = this.pool.tasks.get(workerCreated)
- if (
- isKillBehavior(KillBehaviors.HARD, message.kill) ||
- tasksInProgress === 0
- ) {
- // Kill received from the worker, means that no new tasks are submitted to that worker for a while ( > maxInactiveTime)
- void this.pool.destroyWorker(workerCreated)
- }
- })
- return workerCreated
+ return this.createDynamicallyWorkerCallback()
}
}
* Worker choice strategy context constructor.
*
* @param pool The pool instance.
+ * @param createDynamicallyWorkerCallback The worker creation callback for dynamic pool.
* @param workerChoiceStrategy The worker choice strategy.
*/
public constructor (
private readonly pool: IPoolInternal<Worker, Data, Response>,
+ private createDynamicallyWorkerCallback: () => Worker,
workerChoiceStrategy: WorkerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
) {
this.setWorkerChoiceStrategy(workerChoiceStrategy)
private getPoolWorkerChoiceStrategy (
workerChoiceStrategy: WorkerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
): IWorkerChoiceStrategy<Worker> {
- if (this.pool.dynamic) {
+ if (this.pool.type === PoolType.DYNAMIC) {
return new DynamicPoolWorkerChoiceStrategy(
this.pool,
+ this.createDynamicallyWorkerCallback,
workerChoiceStrategy
)
}
}
/**
- * Worker selection strategies helpers.
+ * Worker selection strategies helpers class.
*/
class SelectionStrategiesUtils {
- /**
- * Find a free worker based on number of tasks the worker has applied.
- *
- * If a worker was found that has `0` tasks, it is detected as free and will be returned.
- *
- * If no free worker was found, `null` will be returned.
- *
- * @param pool The pool instance.
- * @returns A free worker if there was one, otherwise `null`.
- */
- public static findFreeWorkerBasedOnTasks<
- Worker extends IWorker,
- Data,
- Response
- > (pool: IPoolInternal<Worker, Data, Response>): Worker | null {
- for (const [worker, numberOfTasks] of pool.tasks) {
- if (numberOfTasks === 0) {
- // A worker is free, use it
- return worker
- }
- }
- return null
- }
-
/**
* Get the worker choice strategy instance.
*
return new LessRecentlyUsedWorkerChoiceStrategy(pool)
default:
throw new Error(
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
`Worker choice strategy '${workerChoiceStrategy}' not found`
)
}