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.
17 * @typeParam Worker - Type of worker which manages the strategy.
18 * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data.
19 * @typeParam Response - Type of execution response. This can only be structured-cloneable data.
21 export abstract class AbstractWorkerChoiceStrategy
<
22 Worker
extends IWorker
,
25 > implements IWorkerChoiceStrategy
{
27 * The next worker node key.
29 protected nextWorkerNodeKey
: number | undefined = 0
32 * The previous worker node key.
34 protected previousWorkerNodeKey
= 0
37 public readonly strategyPolicy
: StrategyPolicy
= {
38 dynamicWorkerUsage
: false,
39 dynamicWorkerReady
: true,
43 public readonly taskStatisticsRequirements
: TaskStatisticsRequirements
= {
44 runTime
: DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS
,
45 waitTime
: DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS
,
46 elu
: DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS
,
50 * Constructs a worker choice strategy bound to the pool.
51 * @param pool - The pool instance.
52 * @param opts - The worker choice strategy options.
55 protected readonly pool
: IPool
<Worker
, Data
, Response
>,
56 protected opts
?: WorkerChoiceStrategyOptions
58 this.choose
= this.choose
.bind(this)
59 this.setOptions(this.opts
)
62 protected setTaskStatisticsRequirements (
63 opts
: WorkerChoiceStrategyOptions
| undefined
65 toggleMedianMeasurementStatisticsRequirements(
66 this.taskStatisticsRequirements
.runTime
,
67 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
70 toggleMedianMeasurementStatisticsRequirements(
71 this.taskStatisticsRequirements
.waitTime
,
72 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
73 opts
!.waitTime
!.median
75 toggleMedianMeasurementStatisticsRequirements(
76 this.taskStatisticsRequirements
.elu
,
77 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
82 protected resetWorkerNodeKeyProperties (): void {
83 this.nextWorkerNodeKey
= 0
84 this.previousWorkerNodeKey
= 0
88 public abstract reset (): boolean
91 public abstract update (workerNodeKey
: number): boolean
94 public abstract choose (): number | undefined
97 public abstract remove (workerNodeKey
: number): boolean
100 public setOptions (opts
: WorkerChoiceStrategyOptions
| undefined): void {
101 this.opts
= buildWorkerChoiceStrategyOptions
<Worker
, Data
, Response
>(
105 this.setTaskStatisticsRequirements(this.opts
)
109 * Whether the worker node is ready or not.
110 * @param workerNodeKey - The worker node key.
111 * @returns Whether the worker node is ready or not.
113 protected isWorkerNodeReady (workerNodeKey
: number): boolean {
114 return this.pool
.workerNodes
[workerNodeKey
]?.info
?.ready
?? false
118 * Check the next worker node key.
120 protected checkNextWorkerNodeKey (): void {
122 this.nextWorkerNodeKey
!= null &&
123 (this.nextWorkerNodeKey
< 0 ||
124 !this.isWorkerNodeReady(this.nextWorkerNodeKey
))
126 delete this.nextWorkerNodeKey
131 * Gets the worker node task runtime.
132 * If the task statistics require the average runtime, the average runtime is returned.
133 * If the task statistics require the median runtime, the median runtime is returned.
134 * @param workerNodeKey - The worker node key.
135 * @returns The worker node task runtime.
137 protected getWorkerNodeTaskRunTime (workerNodeKey
: number): number {
138 return this.taskStatisticsRequirements
.runTime
.median
139 ? this.pool
.workerNodes
[workerNodeKey
].usage
.runTime
.median
?? 0
140 : this.pool
.workerNodes
[workerNodeKey
].usage
.runTime
.average
?? 0
144 * Gets the worker node task wait time.
145 * If the task statistics require the average wait time, the average wait time is returned.
146 * If the task statistics require the median wait time, the median wait time is returned.
147 * @param workerNodeKey - The worker node key.
148 * @returns The worker node task wait time.
150 protected getWorkerNodeTaskWaitTime (workerNodeKey
: number): number {
151 return this.taskStatisticsRequirements
.waitTime
.median
152 ? this.pool
.workerNodes
[workerNodeKey
].usage
.waitTime
.median
?? 0
153 : this.pool
.workerNodes
[workerNodeKey
].usage
.waitTime
.average
?? 0
157 * Gets the worker node task ELU.
158 * If the task statistics require the average ELU, the average ELU is returned.
159 * If the task statistics require the median ELU, the median ELU is returned.
160 * @param workerNodeKey - The worker node key.
161 * @returns The worker node task ELU.
163 protected getWorkerNodeTaskElu (workerNodeKey
: number): number {
164 return this.taskStatisticsRequirements
.elu
.median
165 ? this.pool
.workerNodes
[workerNodeKey
].usage
.elu
.active
.median
?? 0
166 : this.pool
.workerNodes
[workerNodeKey
].usage
.elu
.active
.average
?? 0
170 * Sets safely the previous worker node key.
171 * @param workerNodeKey - The worker node key.
173 protected setPreviousWorkerNodeKey (workerNodeKey
: number | undefined): void {
174 this.previousWorkerNodeKey
=
175 workerNodeKey
!= null && workerNodeKey
>= 0
177 : this.previousWorkerNodeKey