1 import type { IPool
} from
'../pool.js'
2 import { DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS
} from
'../utils.js'
3 import type { IWorker
} from
'../worker.js'
7 TaskStatisticsRequirements
,
8 WorkerChoiceStrategyOptions
9 } from
'./selection-strategies-types.js'
11 buildWorkerChoiceStrategyOptions
,
12 toggleMedianMeasurementStatisticsRequirements
13 } from
'./selection-strategies-utils.js'
16 * Worker choice strategy abstract base class.
18 * @typeParam Worker - Type of worker which manages the strategy.
19 * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data.
20 * @typeParam Response - Type of execution response. This can only be structured-cloneable data.
22 export abstract class AbstractWorkerChoiceStrategy
<
23 Worker
extends IWorker
,
26 > implements IWorkerChoiceStrategy
{
28 * The next worker node key.
30 protected nextWorkerNodeKey
: number | undefined = 0
33 * The previous worker node key.
35 protected previousWorkerNodeKey
= 0
38 public readonly strategyPolicy
: StrategyPolicy
= {
39 dynamicWorkerUsage
: false,
40 dynamicWorkerReady
: true
44 public readonly taskStatisticsRequirements
: TaskStatisticsRequirements
= {
45 runTime
: DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS
,
46 waitTime
: DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS
,
47 elu
: DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS
51 * Constructs a worker choice strategy bound to the pool.
53 * @param pool - The pool instance.
54 * @param opts - The worker choice strategy options.
57 protected readonly pool
: IPool
<Worker
, Data
, Response
>,
58 protected opts
?: WorkerChoiceStrategyOptions
60 this.choose
= this.choose
.bind(this)
61 this.setOptions(this.opts
)
64 protected setTaskStatisticsRequirements (
65 opts
: WorkerChoiceStrategyOptions
| undefined
67 toggleMedianMeasurementStatisticsRequirements(
68 this.taskStatisticsRequirements
.runTime
,
69 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
72 toggleMedianMeasurementStatisticsRequirements(
73 this.taskStatisticsRequirements
.waitTime
,
74 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
75 opts
!.waitTime
!.median
77 toggleMedianMeasurementStatisticsRequirements(
78 this.taskStatisticsRequirements
.elu
,
79 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
84 protected resetWorkerNodeKeyProperties (): void {
85 this.nextWorkerNodeKey
= 0
86 this.previousWorkerNodeKey
= 0
90 public abstract reset (): boolean
93 public abstract update (workerNodeKey
: number): boolean
96 public abstract choose (): number | undefined
99 public abstract remove (workerNodeKey
: number): boolean
102 public setOptions (opts
: WorkerChoiceStrategyOptions
| undefined): void {
103 this.opts
= buildWorkerChoiceStrategyOptions
<Worker
, Data
, Response
>(
107 this.setTaskStatisticsRequirements(this.opts
)
111 * Whether the worker node is ready or not.
113 * @param workerNodeKey - The worker node key.
114 * @returns Whether the worker node is ready or not.
116 protected isWorkerNodeReady (workerNodeKey
: number): boolean {
117 return this.pool
.workerNodes
[workerNodeKey
]?.info
?.ready
?? false
121 * Check the next worker node key.
123 protected checkNextWorkerNodeKey (): void {
125 this.nextWorkerNodeKey
!= null &&
126 (this.nextWorkerNodeKey
< 0 ||
127 !this.isWorkerNodeReady(this.nextWorkerNodeKey
))
129 delete this.nextWorkerNodeKey
134 * Gets the worker node task runtime.
135 * If the task statistics require the average runtime, the average runtime is returned.
136 * If the task statistics require the median runtime , the median runtime is returned.
138 * @param workerNodeKey - The worker node key.
139 * @returns The worker node task runtime.
141 protected getWorkerNodeTaskRunTime (workerNodeKey
: number): number {
142 return this.taskStatisticsRequirements
.runTime
.median
143 ? this.pool
.workerNodes
[workerNodeKey
].usage
.runTime
.median
?? 0
144 : this.pool
.workerNodes
[workerNodeKey
].usage
.runTime
.average
?? 0
148 * Gets the worker node task wait time.
149 * If the task statistics require the average wait time, the average wait time is returned.
150 * If the task statistics require the median wait time, the median wait time is returned.
152 * @param workerNodeKey - The worker node key.
153 * @returns The worker node task wait time.
155 protected getWorkerNodeTaskWaitTime (workerNodeKey
: number): number {
156 return this.taskStatisticsRequirements
.waitTime
.median
157 ? this.pool
.workerNodes
[workerNodeKey
].usage
.waitTime
.median
?? 0
158 : this.pool
.workerNodes
[workerNodeKey
].usage
.waitTime
.average
?? 0
162 * Gets the worker node task ELU.
163 * If the task statistics require the average ELU, the average ELU is returned.
164 * If the task statistics require the median ELU, the median ELU is returned.
166 * @param workerNodeKey - The worker node key.
167 * @returns The worker node task ELU.
169 protected getWorkerNodeTaskElu (workerNodeKey
: number): number {
170 return this.taskStatisticsRequirements
.elu
.median
171 ? this.pool
.workerNodes
[workerNodeKey
].usage
.elu
.active
.median
?? 0
172 : this.pool
.workerNodes
[workerNodeKey
].usage
.elu
.active
.average
?? 0
176 * Sets safely the previous worker node key.
178 * @param workerNodeKey - The worker node key.
180 protected setPreviousWorkerNodeKey (workerNodeKey
: number | undefined): void {
181 this.previousWorkerNodeKey
=
182 workerNodeKey
!= null && workerNodeKey
>= 0
184 : this.previousWorkerNodeKey