fix: only pickup a free worker with dynamic pool if the worker selection
[poolifier.git] / src / pools / selection-strategies / dynamic-pool-worker-choice-strategy.ts
1 import type { IPoolInternal } from '../pool-internal'
2 import type { IPoolWorker } from '../pool-worker'
3 import { AbstractWorkerChoiceStrategy } from './abstract-worker-choice-strategy'
4 import type {
5 IWorkerChoiceStrategy,
6 WorkerChoiceStrategy
7 } from './selection-strategies-types'
8 import { WorkerChoiceStrategies } from './selection-strategies-types'
9 import { getWorkerChoiceStrategy } from './selection-strategies-utils'
10
11 /**
12 * Selects the next worker for dynamic pool.
13 *
14 * @typeParam Worker - Type of worker which manages the strategy.
15 * @typeParam Data - Type of data sent to the worker. This can only be serializable data.
16 * @typeParam Response - Type of response of execution. This can only be serializable data.
17 */
18 export class DynamicPoolWorkerChoiceStrategy<
19 Worker extends IPoolWorker,
20 Data,
21 Response
22 >
23 extends AbstractWorkerChoiceStrategy<Worker, Data, Response>
24 implements IWorkerChoiceStrategy {
25 private readonly workerChoiceStrategy: IWorkerChoiceStrategy
26
27 /**
28 * Constructs a worker choice strategy for dynamic pool.
29 *
30 * @param pool - The pool instance.
31 * @param createWorkerCallback - The worker creation callback for dynamic pool.
32 * @param workerChoiceStrategy - The worker choice strategy when the pool is busy.
33 */
34 public constructor (
35 pool: IPoolInternal<Worker, Data, Response>,
36 private readonly createWorkerCallback: () => number,
37 workerChoiceStrategy: WorkerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
38 ) {
39 super(pool)
40 this.workerChoiceStrategy = getWorkerChoiceStrategy(
41 this.pool,
42 workerChoiceStrategy
43 )
44 this.requiredStatistics = this.workerChoiceStrategy.requiredStatistics
45 }
46
47 /** {@inheritDoc} */
48 public reset (): boolean {
49 return this.workerChoiceStrategy.reset()
50 }
51
52 /** {@inheritDoc} */
53 public choose (): number {
54 if (this.pool.busy) {
55 return this.workerChoiceStrategy.choose()
56 }
57 const freeWorkerKey = this.pool.findFreeWorkerKey()
58 if (freeWorkerKey === -1) {
59 return this.createWorkerCallback()
60 }
61 return this.workerChoiceStrategy.choose()
62 }
63
64 /** {@inheritDoc} */
65 public remove (workerKey: number): boolean {
66 return this.workerChoiceStrategy.remove(workerKey)
67 }
68 }