test: fix worker choice defaults
[poolifier.git] / src / pools / selection-strategies / worker-choice-strategy-context.ts
CommitLineData
00e1bdeb 1import { buildInternalWorkerChoiceStrategyOptions } from '../../utils'
c4855468 2import type { IPool } from '../pool'
f06e48d8 3import type { IWorker } from '../worker'
51fe3d3c 4import { FairShareWorkerChoiceStrategy } from './fair-share-worker-choice-strategy'
feec6e8c 5import { InterleavedWeightedRoundRobinWorkerChoiceStrategy } from './interleaved-weighted-round-robin-worker-choice-strategy'
e4543b14
JB
6import { LeastBusyWorkerChoiceStrategy } from './least-busy-worker-choice-strategy'
7import { LeastUsedWorkerChoiceStrategy } from './least-used-worker-choice-strategy'
058a9457 8import { LeastEluWorkerChoiceStrategy } from './least-elu-worker-choice-strategy'
51fe3d3c 9import { RoundRobinWorkerChoiceStrategy } from './round-robin-worker-choice-strategy'
bdaf31cd
JB
10import type {
11 IWorkerChoiceStrategy,
26ce26ca 12 InternalWorkerChoiceStrategyOptions,
6c6afb84 13 StrategyPolicy,
87de9ff5 14 TaskStatisticsRequirements,
26ce26ca 15 WorkerChoiceStrategy
bdaf31cd
JB
16} from './selection-strategies-types'
17import { WorkerChoiceStrategies } from './selection-strategies-types'
51fe3d3c 18import { WeightedRoundRobinWorkerChoiceStrategy } from './weighted-round-robin-worker-choice-strategy'
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 ])
17d12ee0 110 this.setOptions(pool, this.opts)
bdaf31cd
JB
111 }
112
6c6afb84
JB
113 /**
114 * Gets the strategy policy in the context.
115 *
116 * @returns The strategy policy.
117 */
118 public getStrategyPolicy (): StrategyPolicy {
119 return (
120 this.workerChoiceStrategies.get(
121 this.workerChoiceStrategy
122 ) as IWorkerChoiceStrategy
123 ).strategyPolicy
124 }
125
97a2abc3 126 /**
8990357d 127 * Gets the worker choice strategy in the context task statistics requirements.
97a2abc3 128 *
87de9ff5 129 * @returns The task statistics requirements.
97a2abc3 130 */
87de9ff5 131 public getTaskStatisticsRequirements (): TaskStatisticsRequirements {
95c83464
JB
132 return (
133 this.workerChoiceStrategies.get(
d710242d 134 this.workerChoiceStrategy
17393ac8 135 ) as IWorkerChoiceStrategy
87de9ff5 136 ).taskStatisticsRequirements
97a2abc3
JB
137 }
138
bdaf31cd 139 /**
bdede008 140 * Sets the worker choice strategy to use in the context.
bdaf31cd 141 *
38e795c1 142 * @param workerChoiceStrategy - The worker choice strategy to set.
bdaf31cd
JB
143 */
144 public setWorkerChoiceStrategy (
145 workerChoiceStrategy: WorkerChoiceStrategy
146 ): void {
d710242d
JB
147 if (this.workerChoiceStrategy !== workerChoiceStrategy) {
148 this.workerChoiceStrategy = workerChoiceStrategy
b2b1d84e 149 }
d710242d 150 this.workerChoiceStrategies.get(this.workerChoiceStrategy)?.reset()
bdaf31cd
JB
151 }
152
138d29a8 153 /**
8990357d 154 * Updates the worker node key in the worker choice strategy in the context internals.
138d29a8
JB
155 *
156 * @returns `true` if the update is successful, `false` otherwise.
157 */
a4958de2 158 public update (workerNodeKey: number): boolean {
138d29a8
JB
159 return (
160 this.workerChoiceStrategies.get(
161 this.workerChoiceStrategy
162 ) as IWorkerChoiceStrategy
a4958de2 163 ).update(workerNodeKey)
138d29a8
JB
164 }
165
bdaf31cd 166 /**
8990357d 167 * Executes the worker choice strategy in the context algorithm.
bdaf31cd 168 *
f06e48d8 169 * @returns The key of the worker node.
fb5a7307 170 * @throws {@link https://nodejs.org/api/errors.html#class-error} If after configured retries the worker node key is null or undefined.
bdaf31cd 171 */
c923ce56 172 public execute (): number {
fb5a7307
JB
173 const workerChoiceStrategy = this.workerChoiceStrategies.get(
174 this.workerChoiceStrategy
175 ) as IWorkerChoiceStrategy
613a91dc 176 if (!workerChoiceStrategy.hasPoolWorkerNodesReady()) {
722d55a0 177 return this.execute()
613a91dc
JB
178 }
179 return this.executeStrategy(workerChoiceStrategy)
180 }
181
182 /**
183 * Executes the given worker choice strategy.
184 *
185 * @param workerChoiceStrategy - The worker choice strategy.
186 * @returns The key of the worker node.
187 * @throws {@link https://nodejs.org/api/errors.html#class-error} If after configured retries the worker node key is null or undefined.
188 */
189 private executeStrategy (workerChoiceStrategy: IWorkerChoiceStrategy): number {
fb5a7307 190 let workerNodeKey: number | undefined
fb5a7307
JB
191 let chooseCount = 0
192 let retriesCount = 0
193 do {
613a91dc
JB
194 workerNodeKey = workerChoiceStrategy.choose()
195 if (workerNodeKey == null && chooseCount > 0) {
196 retriesCount++
fb5a7307 197 }
613a91dc 198 chooseCount++
fb5a7307 199 } while (
613a91dc 200 workerNodeKey == null &&
26ce26ca 201 retriesCount < (this.opts?.retries as number)
fb5a7307 202 )
fb5a7307 203 if (workerNodeKey == null) {
e695d66f 204 throw new Error(
fb5a7307 205 `Worker node key chosen is null or undefined after ${retriesCount} retries`
4ba8492f 206 )
b0d6ed8f
JB
207 }
208 return workerNodeKey
bdaf31cd 209 }
97a2abc3
JB
210
211 /**
c7e196ba 212 * Removes the worker node key from the worker choice strategy in the context.
97a2abc3 213 *
501aea93 214 * @param workerNodeKey - The worker node key.
97a2abc3
JB
215 * @returns `true` if the removal is successful, `false` otherwise.
216 */
f06e48d8 217 public remove (workerNodeKey: number): boolean {
95c83464
JB
218 return (
219 this.workerChoiceStrategies.get(
d710242d 220 this.workerChoiceStrategy
17393ac8 221 ) as IWorkerChoiceStrategy
f06e48d8 222 ).remove(workerNodeKey)
95c83464 223 }
a20f0ba5
JB
224
225 /**
226 * Sets the worker choice strategies in the context options.
227 *
af7f2788 228 * @param pool - The pool instance.
a20f0ba5
JB
229 * @param opts - The worker choice strategy options.
230 */
26ce26ca
JB
231 public setOptions (
232 pool: IPool<Worker, Data, Response>,
233 opts?: InternalWorkerChoiceStrategyOptions
234 ): void {
00e1bdeb
JB
235 this.opts = buildInternalWorkerChoiceStrategyOptions(
236 pool.info.maxSize,
237 opts
238 )
0509fd43 239 for (const workerChoiceStrategy of this.workerChoiceStrategies.values()) {
26ce26ca 240 workerChoiceStrategy.setOptions(this.opts)
0509fd43 241 }
a20f0ba5 242 }
bdaf31cd 243}