1 import type { IPool
} from
'../pool.js'
2 import type { IWorker
} from
'../worker.js'
6 TaskStatisticsRequirements
,
8 WorkerChoiceStrategyOptions
9 } from
'./selection-strategies-types.js'
10 import { WorkerChoiceStrategies
} from
'./selection-strategies-types.js'
12 buildWorkerChoiceStrategiesPolicy
,
13 buildWorkerChoiceStrategiesTaskStatisticsRequirements
,
14 getWorkerChoiceStrategiesRetries
,
15 getWorkerChoiceStrategy
16 } from
'./selection-strategies-utils.js'
19 * The worker choice strategies context.
21 * @typeParam Worker - Type of worker.
22 * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data.
23 * @typeParam Response - Type of execution response. This can only be structured-cloneable data.
25 export class WorkerChoiceStrategiesContext
<
26 Worker
extends IWorker
,
31 * The number of worker choice strategies execution retries.
33 public retriesCount
: number
36 * The default worker choice strategy in the context.
38 private defaultWorkerChoiceStrategy
: WorkerChoiceStrategy
41 * The worker choice strategies registered in the context.
43 private readonly workerChoiceStrategies
: Map
<
49 * The active worker choice strategies in the context policy.
51 private workerChoiceStrategiesPolicy
: StrategyPolicy
54 * The active worker choice strategies in the context task statistics requirements.
56 private workerChoiceStrategiesTaskStatisticsRequirements
: TaskStatisticsRequirements
59 * The maximum number of worker choice strategies execution retries.
61 private readonly retries
: number
64 * Worker choice strategies context constructor.
66 * @param pool - The pool instance.
67 * @param workerChoiceStrategies - The worker choice strategies. @defaultValue [WorkerChoiceStrategies.ROUND_ROBIN]
68 * @param opts - The worker choice strategy options.
71 private readonly pool
: IPool
<Worker
, Data
, Response
>,
72 workerChoiceStrategies
: WorkerChoiceStrategy
[] = [
73 WorkerChoiceStrategies
.ROUND_ROBIN
75 opts
?: WorkerChoiceStrategyOptions
77 this.execute
= this.execute
.bind(this)
78 this.defaultWorkerChoiceStrategy
= workerChoiceStrategies
[0]
79 this.workerChoiceStrategies
= new Map
<
83 for (const workerChoiceStrategy
of workerChoiceStrategies
) {
84 this.addWorkerChoiceStrategy(workerChoiceStrategy
, this.pool
, opts
)
86 this.workerChoiceStrategiesPolicy
= buildWorkerChoiceStrategiesPolicy(
87 this.workerChoiceStrategies
89 this.workerChoiceStrategiesTaskStatisticsRequirements
=
90 buildWorkerChoiceStrategiesTaskStatisticsRequirements(
91 this.workerChoiceStrategies
94 this.retries
= getWorkerChoiceStrategiesRetries
<Worker
, Data
, Response
>(
101 * Gets the active worker choice strategies in the context policy.
103 * @returns The strategies policy.
105 public getPolicy (): StrategyPolicy
{
106 return this.workerChoiceStrategiesPolicy
110 * Gets the active worker choice strategies in the context task statistics requirements.
112 * @returns The strategies task statistics requirements.
114 public getTaskStatisticsRequirements (): TaskStatisticsRequirements
{
115 return this.workerChoiceStrategiesTaskStatisticsRequirements
119 * Sets the default worker choice strategy to use in the context.
121 * @param workerChoiceStrategy - The default worker choice strategy to set.
122 * @param opts - The worker choice strategy options.
124 public setDefaultWorkerChoiceStrategy (
125 workerChoiceStrategy
: WorkerChoiceStrategy
,
126 opts
?: WorkerChoiceStrategyOptions
128 if (workerChoiceStrategy
!== this.defaultWorkerChoiceStrategy
) {
129 this.defaultWorkerChoiceStrategy
= workerChoiceStrategy
130 this.addWorkerChoiceStrategy(workerChoiceStrategy
, this.pool
, opts
)
135 * Updates the worker node key in the active worker choice strategies in the context internals.
137 * @returns `true` if the update is successful, `false` otherwise.
139 public update (workerNodeKey
: number): boolean {
140 const res
: boolean[] = []
141 for (const workerChoiceStrategy
of this.workerChoiceStrategies
.values()) {
142 res
.push(workerChoiceStrategy
.update(workerNodeKey
))
144 return res
.every(r
=> r
)
148 * Executes the given worker choice strategy in the context algorithm.
150 * @param workerChoiceStrategy - The worker choice strategy algorithm to execute. @defaultValue this.defaultWorkerChoiceStrategy
151 * @returns The key of the worker node.
152 * @throws {@link https://nodejs.org/api/errors.html#class-error} If after computed retries the worker node key is null or undefined.
155 workerChoiceStrategy
: WorkerChoiceStrategy
= this
156 .defaultWorkerChoiceStrategy
158 return this.executeStrategy(
159 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
160 this.workerChoiceStrategies
.get(workerChoiceStrategy
)!
165 * Executes the given worker choice strategy.
167 * @param workerChoiceStrategy - The worker choice strategy.
168 * @returns The key of the worker node.
169 * @throws {@link https://nodejs.org/api/errors.html#class-error} If after computed retries the worker node key is null or undefined.
171 private executeStrategy (workerChoiceStrategy
: IWorkerChoiceStrategy
): number {
172 let workerNodeKey
: number | undefined
176 workerNodeKey
= workerChoiceStrategy
.choose()
177 if (workerNodeKey
== null && chooseCount
> 0) {
182 } while (workerNodeKey
== null && retriesCount
< this.retries
)
183 if (workerNodeKey
== null) {
185 `Worker node key chosen is null or undefined after ${retriesCount} retries`
192 * Removes the worker node key from the active worker choice strategies in the context.
194 * @param workerNodeKey - The worker node key.
195 * @returns `true` if the removal is successful, `false` otherwise.
197 public remove (workerNodeKey
: number): boolean {
198 const res
: boolean[] = []
199 for (const workerChoiceStrategy
of this.workerChoiceStrategies
.values()) {
200 res
.push(workerChoiceStrategy
.remove(workerNodeKey
))
202 return res
.every(r
=> r
)
206 * Sets the active worker choice strategies in the context options.
208 * @param opts - The worker choice strategy options.
210 public setOptions (opts
: WorkerChoiceStrategyOptions
| undefined): void {
211 for (const workerChoiceStrategy
of this.workerChoiceStrategies
.values()) {
212 workerChoiceStrategy
.setOptions(opts
)
217 * Synchronizes the active worker choice strategies in the context with the given worker choice strategies.
219 * @param workerChoiceStrategies - The worker choice strategies to synchronize.
220 * @param opts - The worker choice strategy options.
222 public syncWorkerChoiceStrategies (
223 workerChoiceStrategies
: Set
<WorkerChoiceStrategy
>,
224 opts
?: WorkerChoiceStrategyOptions
226 for (const workerChoiceStrategy
of this.workerChoiceStrategies
.keys()) {
227 if (!workerChoiceStrategies
.has(workerChoiceStrategy
)) {
228 this.removeWorkerChoiceStrategy(workerChoiceStrategy
)
231 for (const workerChoiceStrategy
of workerChoiceStrategies
) {
232 if (!this.workerChoiceStrategies
.has(workerChoiceStrategy
)) {
233 this.addWorkerChoiceStrategy(workerChoiceStrategy
, this.pool
, opts
)
236 this.workerChoiceStrategiesPolicy
= buildWorkerChoiceStrategiesPolicy(
237 this.workerChoiceStrategies
239 this.workerChoiceStrategiesTaskStatisticsRequirements
=
240 buildWorkerChoiceStrategiesTaskStatisticsRequirements(
241 this.workerChoiceStrategies
246 * Adds a worker choice strategy to the context.
248 * @param workerChoiceStrategy - The worker choice strategy to add.
249 * @param opts - The worker choice strategy options.
250 * @returns The worker choice strategies.
252 private addWorkerChoiceStrategy (
253 workerChoiceStrategy
: WorkerChoiceStrategy
,
254 pool
: IPool
<Worker
, Data
, Response
>,
255 opts
?: WorkerChoiceStrategyOptions
256 ): Map
<WorkerChoiceStrategy
, IWorkerChoiceStrategy
> {
257 if (!this.workerChoiceStrategies
.has(workerChoiceStrategy
)) {
258 return this.workerChoiceStrategies
.set(
259 workerChoiceStrategy
,
260 getWorkerChoiceStrategy
<Worker
, Data
, Response
>(
261 workerChoiceStrategy
,
268 return this.workerChoiceStrategies
272 * Removes a worker choice strategy from the context.
274 * @param workerChoiceStrategy - The worker choice strategy to remove.
275 * @returns `true` if the worker choice strategy is removed, `false` otherwise.
277 private removeWorkerChoiceStrategy (
278 workerChoiceStrategy
: WorkerChoiceStrategy
280 return this.workerChoiceStrategies
.delete(workerChoiceStrategy
)