refactor: renable standard JS linter rules
[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 {
67f3f2d6
JB
118 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
119 return this.workerChoiceStrategies.get(this.workerChoiceStrategy)!
120 .strategyPolicy
6c6afb84
JB
121 }
122
97a2abc3 123 /**
8990357d 124 * Gets the worker choice strategy in the context task statistics requirements.
97a2abc3 125 *
87de9ff5 126 * @returns The task statistics requirements.
97a2abc3 127 */
87de9ff5 128 public getTaskStatisticsRequirements (): TaskStatisticsRequirements {
67f3f2d6
JB
129 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
130 return this.workerChoiceStrategies.get(this.workerChoiceStrategy)!
131 .taskStatisticsRequirements
97a2abc3
JB
132 }
133
bdaf31cd 134 /**
bdede008 135 * Sets the worker choice strategy to use in the context.
bdaf31cd 136 *
38e795c1 137 * @param workerChoiceStrategy - The worker choice strategy to set.
bdaf31cd
JB
138 */
139 public setWorkerChoiceStrategy (
140 workerChoiceStrategy: WorkerChoiceStrategy
141 ): void {
d710242d
JB
142 if (this.workerChoiceStrategy !== workerChoiceStrategy) {
143 this.workerChoiceStrategy = workerChoiceStrategy
b2b1d84e 144 }
d710242d 145 this.workerChoiceStrategies.get(this.workerChoiceStrategy)?.reset()
bdaf31cd
JB
146 }
147
138d29a8 148 /**
8990357d 149 * Updates the worker node key in the worker choice strategy in the context internals.
138d29a8
JB
150 *
151 * @returns `true` if the update is successful, `false` otherwise.
152 */
a4958de2 153 public update (workerNodeKey: number): boolean {
67f3f2d6
JB
154 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
155 return this.workerChoiceStrategies
156 .get(this.workerChoiceStrategy)!
157 .update(workerNodeKey)
138d29a8
JB
158 }
159
bdaf31cd 160 /**
8990357d 161 * Executes the worker choice strategy in the context algorithm.
bdaf31cd 162 *
f06e48d8 163 * @returns The key of the worker node.
fb5a7307 164 * @throws {@link https://nodejs.org/api/errors.html#class-error} If after configured retries the worker node key is null or undefined.
bdaf31cd 165 */
c923ce56 166 public execute (): number {
67f3f2d6 167 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
fb5a7307
JB
168 const workerChoiceStrategy = this.workerChoiceStrategies.get(
169 this.workerChoiceStrategy
67f3f2d6 170 )!
613a91dc 171 if (!workerChoiceStrategy.hasPoolWorkerNodesReady()) {
722d55a0 172 return this.execute()
613a91dc
JB
173 }
174 return this.executeStrategy(workerChoiceStrategy)
175 }
176
177 /**
178 * Executes the given worker choice strategy.
179 *
180 * @param workerChoiceStrategy - The worker choice strategy.
181 * @returns The key of the worker node.
182 * @throws {@link https://nodejs.org/api/errors.html#class-error} If after configured retries the worker node key is null or undefined.
183 */
184 private executeStrategy (workerChoiceStrategy: IWorkerChoiceStrategy): number {
fb5a7307 185 let workerNodeKey: number | undefined
fb5a7307
JB
186 let chooseCount = 0
187 let retriesCount = 0
188 do {
613a91dc
JB
189 workerNodeKey = workerChoiceStrategy.choose()
190 if (workerNodeKey == null && chooseCount > 0) {
191 retriesCount++
fb5a7307 192 }
613a91dc 193 chooseCount++
67f3f2d6
JB
194 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
195 } while (workerNodeKey == null && retriesCount < this.opts!.retries!)
fb5a7307 196 if (workerNodeKey == null) {
e695d66f 197 throw new Error(
fb5a7307 198 `Worker node key chosen is null or undefined after ${retriesCount} retries`
4ba8492f 199 )
b0d6ed8f
JB
200 }
201 return workerNodeKey
bdaf31cd 202 }
97a2abc3
JB
203
204 /**
c7e196ba 205 * Removes the worker node key from the worker choice strategy in the context.
97a2abc3 206 *
501aea93 207 * @param workerNodeKey - The worker node key.
97a2abc3
JB
208 * @returns `true` if the removal is successful, `false` otherwise.
209 */
f06e48d8 210 public remove (workerNodeKey: number): boolean {
67f3f2d6
JB
211 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
212 return this.workerChoiceStrategies
213 .get(this.workerChoiceStrategy)!
214 .remove(workerNodeKey)
95c83464 215 }
a20f0ba5
JB
216
217 /**
218 * Sets the worker choice strategies in the context options.
219 *
af7f2788 220 * @param pool - The pool instance.
a20f0ba5
JB
221 * @param opts - The worker choice strategy options.
222 */
26ce26ca
JB
223 public setOptions (
224 pool: IPool<Worker, Data, Response>,
225 opts?: InternalWorkerChoiceStrategyOptions
226 ): void {
00e1bdeb
JB
227 this.opts = buildInternalWorkerChoiceStrategyOptions(
228 pool.info.maxSize,
229 opts
230 )
0509fd43 231 for (const workerChoiceStrategy of this.workerChoiceStrategies.values()) {
26ce26ca 232 workerChoiceStrategy.setOptions(this.opts)
0509fd43 233 }
a20f0ba5 234 }
bdaf31cd 235}