fix: ensure worker removal impact is propated to worker choice strategy
[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 > extends AbstractWorkerChoiceStrategy<Worker, Data, Response> {
23 private readonly workerChoiceStrategy: IWorkerChoiceStrategy
24
25 /**
26 * Constructs a worker choice strategy for dynamic pool.
27 *
28 * @param pool - The pool instance.
29 * @param createWorkerCallback - The worker creation callback for dynamic pool.
30 * @param workerChoiceStrategy - The worker choice strategy when the pool is busy.
31 */
32 public constructor (
33 pool: IPoolInternal<Worker, Data, Response>,
34 private readonly createWorkerCallback: () => number,
35 workerChoiceStrategy: WorkerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
36 ) {
37 super(pool)
38 this.workerChoiceStrategy = getWorkerChoiceStrategy(
39 this.pool,
40 workerChoiceStrategy
41 )
42 this.requiredStatistics = this.workerChoiceStrategy.requiredStatistics
43 }
44
45 /** {@inheritDoc} */
46 public reset (): boolean {
47 return this.workerChoiceStrategy.reset()
48 }
49
50 /** {@inheritDoc} */
51 public choose (): number {
52 const freeWorkerKey = this.pool.findFreeWorkerKey()
53 if (freeWorkerKey !== false) {
54 return freeWorkerKey
55 }
56
57 if (this.pool.busy) {
58 return this.workerChoiceStrategy.choose()
59 }
60
61 // All workers are busy, create a new worker
62 return this.createWorkerCallback()
63 }
64
65 /** {@inheritDoc} */
66 public remove (workerKey: number): boolean {
67 return this.workerChoiceStrategy.remove(workerKey)
68 }
69 }