build: switch default to ESM
[poolifier.git] / src / pools / selection-strategies / worker-choice-strategy-context.ts
CommitLineData
d35e5717
JB
1import { buildInternalWorkerChoiceStrategyOptions } from '../../utils.js'
2import type { IPool } from '../pool.js'
3import type { IWorker } from '../worker.js'
4import { FairShareWorkerChoiceStrategy } from './fair-share-worker-choice-strategy.js'
5import { InterleavedWeightedRoundRobinWorkerChoiceStrategy } from './interleaved-weighted-round-robin-worker-choice-strategy.js'
6import { LeastBusyWorkerChoiceStrategy } from './least-busy-worker-choice-strategy.js'
7import { LeastUsedWorkerChoiceStrategy } from './least-used-worker-choice-strategy.js'
8import { LeastEluWorkerChoiceStrategy } from './least-elu-worker-choice-strategy.js'
9import { RoundRobinWorkerChoiceStrategy } from './round-robin-worker-choice-strategy.js'
bdaf31cd
JB
10import type {
11 IWorkerChoiceStrategy,
26ce26ca 12 InternalWorkerChoiceStrategyOptions,
6c6afb84 13 StrategyPolicy,
87de9ff5 14 TaskStatisticsRequirements,
26ce26ca 15 WorkerChoiceStrategy
d35e5717
JB
16} from './selection-strategies-types.js'
17import { WorkerChoiceStrategies } from './selection-strategies-types.js'
18import { WeightedRoundRobinWorkerChoiceStrategy } from './weighted-round-robin-worker-choice-strategy.js'
bdaf31cd
JB
19
20/**
21 * The worker choice strategy context.
22 *
38e795c1 23 * @typeParam Worker - Type of worker.
e102732c
JB
24 * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data.
25 * @typeParam Response - Type of execution response. This can only be structured-cloneable data.
bdaf31cd
JB
26 */
27export class WorkerChoiceStrategyContext<
f06e48d8 28 Worker extends IWorker,
b2b1d84e
JB
29 Data = unknown,
30 Response = unknown
bdaf31cd 31> {
b529c323 32 private readonly workerChoiceStrategies: Map<
95c83464 33 WorkerChoiceStrategy,
17393ac8 34 IWorkerChoiceStrategy
b529c323 35 >
bdaf31cd
JB
36
37 /**
38 * Worker choice strategy context constructor.
39 *
38e795c1 40 * @param pool - The pool instance.
d710242d 41 * @param workerChoiceStrategy - The worker choice strategy.
da309861 42 * @param opts - The worker choice strategy options.
bdaf31cd
JB
43 */
44 public constructor (
c4855468 45 pool: IPool<Worker, Data, Response>,
d710242d 46 private workerChoiceStrategy: WorkerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN,
26ce26ca 47 private opts?: InternalWorkerChoiceStrategyOptions
bdaf31cd 48 ) {
00e1bdeb
JB
49 this.opts = buildInternalWorkerChoiceStrategyOptions(
50 pool.info.maxSize,
51 this.opts
52 )
7254e419 53 this.execute = this.execute.bind(this)
b529c323
JB
54 this.workerChoiceStrategies = new Map<
55 WorkerChoiceStrategy,
17393ac8 56 IWorkerChoiceStrategy
b529c323
JB
57 >([
58 [
59 WorkerChoiceStrategies.ROUND_ROBIN,
7254e419
JB
60 new (RoundRobinWorkerChoiceStrategy.bind(this))<Worker, Data, Response>(
61 pool,
26ce26ca 62 this.opts
7254e419 63 )
b529c323
JB
64 ],
65 [
e4543b14
JB
66 WorkerChoiceStrategies.LEAST_USED,
67 new (LeastUsedWorkerChoiceStrategy.bind(this))<Worker, Data, Response>(
7254e419 68 pool,
26ce26ca 69 this.opts
7254e419 70 )
b529c323
JB
71 ],
72 [
e4543b14
JB
73 WorkerChoiceStrategies.LEAST_BUSY,
74 new (LeastBusyWorkerChoiceStrategy.bind(this))<Worker, Data, Response>(
7254e419 75 pool,
26ce26ca 76 this.opts
7254e419 77 )
b529c323
JB
78 ],
79 [
058a9457
JB
80 WorkerChoiceStrategies.LEAST_ELU,
81 new (LeastEluWorkerChoiceStrategy.bind(this))<Worker, Data, Response>(
82 pool,
26ce26ca 83 this.opts
058a9457
JB
84 )
85 ],
86 [
b529c323 87 WorkerChoiceStrategies.FAIR_SHARE,
7254e419 88 new (FairShareWorkerChoiceStrategy.bind(this))<Worker, Data, Response>(
da309861 89 pool,
26ce26ca 90 this.opts
da309861 91 )
7254e419
JB
92 ],
93 [
94 WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN,
95 new (WeightedRoundRobinWorkerChoiceStrategy.bind(this))<
96 Worker,
97 Data,
98 Response
26ce26ca 99 >(pool, this.opts)
feec6e8c
JB
100 ],
101 [
102 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN,
103 new (InterleavedWeightedRoundRobinWorkerChoiceStrategy.bind(this))<
104 Worker,
105 Data,
106 Response
26ce26ca 107 >(pool, this.opts)
b529c323
JB
108 ]
109 ])
bdaf31cd
JB
110 }
111
6c6afb84
JB
112 /**
113 * Gets the strategy policy in the context.
114 *
115 * @returns The strategy policy.
116 */
117 public getStrategyPolicy (): StrategyPolicy {
118 return (
119 this.workerChoiceStrategies.get(
120 this.workerChoiceStrategy
121 ) as IWorkerChoiceStrategy
122 ).strategyPolicy
123 }
124
97a2abc3 125 /**
8990357d 126 * Gets the worker choice strategy in the context task statistics requirements.
97a2abc3 127 *
87de9ff5 128 * @returns The task statistics requirements.
97a2abc3 129 */
87de9ff5 130 public getTaskStatisticsRequirements (): TaskStatisticsRequirements {
95c83464
JB
131 return (
132 this.workerChoiceStrategies.get(
d710242d 133 this.workerChoiceStrategy
17393ac8 134 ) as IWorkerChoiceStrategy
87de9ff5 135 ).taskStatisticsRequirements
97a2abc3
JB
136 }
137
bdaf31cd 138 /**
bdede008 139 * Sets the worker choice strategy to use in the context.
bdaf31cd 140 *
38e795c1 141 * @param workerChoiceStrategy - The worker choice strategy to set.
bdaf31cd
JB
142 */
143 public setWorkerChoiceStrategy (
144 workerChoiceStrategy: WorkerChoiceStrategy
145 ): void {
d710242d
JB
146 if (this.workerChoiceStrategy !== workerChoiceStrategy) {
147 this.workerChoiceStrategy = workerChoiceStrategy
b2b1d84e 148 }
d710242d 149 this.workerChoiceStrategies.get(this.workerChoiceStrategy)?.reset()
bdaf31cd
JB
150 }
151
138d29a8 152 /**
8990357d 153 * Updates the worker node key in the worker choice strategy in the context internals.
138d29a8
JB
154 *
155 * @returns `true` if the update is successful, `false` otherwise.
156 */
a4958de2 157 public update (workerNodeKey: number): boolean {
138d29a8
JB
158 return (
159 this.workerChoiceStrategies.get(
160 this.workerChoiceStrategy
161 ) as IWorkerChoiceStrategy
a4958de2 162 ).update(workerNodeKey)
138d29a8
JB
163 }
164
bdaf31cd 165 /**
8990357d 166 * Executes the worker choice strategy in the context algorithm.
bdaf31cd 167 *
f06e48d8 168 * @returns The key of the worker node.
fb5a7307 169 * @throws {@link https://nodejs.org/api/errors.html#class-error} If after configured retries the worker node key is null or undefined.
bdaf31cd 170 */
c923ce56 171 public execute (): number {
fb5a7307
JB
172 const workerChoiceStrategy = this.workerChoiceStrategies.get(
173 this.workerChoiceStrategy
174 ) as IWorkerChoiceStrategy
613a91dc 175 if (!workerChoiceStrategy.hasPoolWorkerNodesReady()) {
722d55a0 176 return this.execute()
613a91dc
JB
177 }
178 return this.executeStrategy(workerChoiceStrategy)
179 }
180
181 /**
182 * Executes the given worker choice strategy.
183 *
184 * @param workerChoiceStrategy - The worker choice strategy.
185 * @returns The key of the worker node.
186 * @throws {@link https://nodejs.org/api/errors.html#class-error} If after configured retries the worker node key is null or undefined.
187 */
188 private executeStrategy (workerChoiceStrategy: IWorkerChoiceStrategy): number {
fb5a7307 189 let workerNodeKey: number | undefined
fb5a7307
JB
190 let chooseCount = 0
191 let retriesCount = 0
192 do {
613a91dc
JB
193 workerNodeKey = workerChoiceStrategy.choose()
194 if (workerNodeKey == null && chooseCount > 0) {
195 retriesCount++
fb5a7307 196 }
613a91dc 197 chooseCount++
fb5a7307 198 } while (
613a91dc 199 workerNodeKey == null &&
26ce26ca 200 retriesCount < (this.opts?.retries as number)
fb5a7307 201 )
fb5a7307 202 if (workerNodeKey == null) {
e695d66f 203 throw new Error(
fb5a7307 204 `Worker node key chosen is null or undefined after ${retriesCount} retries`
4ba8492f 205 )
b0d6ed8f
JB
206 }
207 return workerNodeKey
bdaf31cd 208 }
97a2abc3
JB
209
210 /**
c7e196ba 211 * Removes the worker node key from the worker choice strategy in the context.
97a2abc3 212 *
501aea93 213 * @param workerNodeKey - The worker node key.
97a2abc3
JB
214 * @returns `true` if the removal is successful, `false` otherwise.
215 */
f06e48d8 216 public remove (workerNodeKey: number): boolean {
95c83464
JB
217 return (
218 this.workerChoiceStrategies.get(
d710242d 219 this.workerChoiceStrategy
17393ac8 220 ) as IWorkerChoiceStrategy
f06e48d8 221 ).remove(workerNodeKey)
95c83464 222 }
a20f0ba5
JB
223
224 /**
225 * Sets the worker choice strategies in the context options.
226 *
af7f2788 227 * @param pool - The pool instance.
a20f0ba5
JB
228 * @param opts - The worker choice strategy options.
229 */
26ce26ca
JB
230 public setOptions (
231 pool: IPool<Worker, Data, Response>,
232 opts?: InternalWorkerChoiceStrategyOptions
233 ): void {
00e1bdeb
JB
234 this.opts = buildInternalWorkerChoiceStrategyOptions(
235 pool.info.maxSize,
236 opts
237 )
0509fd43 238 for (const workerChoiceStrategy of this.workerChoiceStrategies.values()) {
26ce26ca 239 workerChoiceStrategy.setOptions(this.opts)
0509fd43 240 }
a20f0ba5 241 }
bdaf31cd 242}