]>
Commit | Line | Data |
---|---|---|
e9ed6eee | 1 | import type { IPool } from '../pool.js' |
d35e5717 | 2 | import type { IWorker } from '../worker.js' |
10fcfaf4 JB |
3 | import type { |
4 | IWorkerChoiceStrategy, | |
6c6afb84 | 5 | StrategyPolicy, |
39618ede | 6 | TaskStatisticsRequirements, |
3a502712 | 7 | WorkerChoiceStrategyOptions, |
d35e5717 | 8 | } from './selection-strategies-types.js' |
97231086 JB |
9 | |
10 | import { DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS } from '../utils.js' | |
763abb1c JB |
11 | import { |
12 | buildWorkerChoiceStrategyOptions, | |
3a502712 | 13 | toggleMedianMeasurementStatisticsRequirements, |
763abb1c | 14 | } from './selection-strategies-utils.js' |
bdaf31cd JB |
15 | |
16 | /** | |
9cd39dd4 | 17 | * Worker choice strategy abstract base class. |
38e795c1 | 18 | * @typeParam Worker - Type of worker which manages the strategy. |
e102732c JB |
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. | |
bdaf31cd JB |
21 | */ |
22 | export abstract class AbstractWorkerChoiceStrategy< | |
f06e48d8 | 23 | Worker extends IWorker, |
b2b1d84e JB |
24 | Data = unknown, |
25 | Response = unknown | |
17393ac8 | 26 | > implements IWorkerChoiceStrategy { |
6c6afb84 | 27 | /** @inheritDoc */ |
49d53529 | 28 | public readonly strategyPolicy: StrategyPolicy = Object.freeze({ |
3a502712 | 29 | dynamicWorkerReady: true, |
97231086 | 30 | dynamicWorkerUsage: false, |
49d53529 | 31 | }) |
6c6afb84 | 32 | |
afc003b2 | 33 | /** @inheritDoc */ |
7cec62a4 JB |
34 | public readonly taskStatisticsRequirements: TaskStatisticsRequirements = |
35 | Object.freeze({ | |
36 | elu: DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS, | |
37 | runTime: DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS, | |
38 | waitTime: DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS, | |
39 | }) | |
bdaf31cd | 40 | |
5de88a2a JB |
41 | /** |
42 | * The next worker node key. | |
43 | */ | |
44 | protected nextWorkerNodeKey: number | undefined = 0 | |
45 | ||
46 | /** | |
47 | * The previous worker node key. | |
48 | */ | |
49 | protected previousWorkerNodeKey = 0 | |
50 | ||
bdaf31cd | 51 | /** |
6533c3e6 | 52 | * Constructs a worker choice strategy bound to the pool. |
38e795c1 | 53 | * @param pool - The pool instance. |
da309861 | 54 | * @param opts - The worker choice strategy options. |
bdaf31cd JB |
55 | */ |
56 | public constructor ( | |
c4855468 | 57 | protected readonly pool: IPool<Worker, Data, Response>, |
39618ede | 58 | protected opts?: WorkerChoiceStrategyOptions |
b8f3418c | 59 | ) { |
7254e419 | 60 | this.choose = this.choose.bind(this) |
04d875a3 | 61 | this.setOptions(this.opts) |
b8f3418c | 62 | } |
bdaf31cd | 63 | |
5de88a2a JB |
64 | /** @inheritDoc */ |
65 | public abstract choose (): number | undefined | |
66 | ||
67 | /** @inheritDoc */ | |
68 | public abstract remove (workerNodeKey: number): boolean | |
69 | ||
70 | /** @inheritDoc */ | |
71 | public abstract reset (): boolean | |
72 | ||
73 | /** @inheritDoc */ | |
74 | public setOptions (opts: undefined | WorkerChoiceStrategyOptions): void { | |
75 | this.opts = buildWorkerChoiceStrategyOptions<Worker, Data, Response>( | |
76 | this.pool, | |
77 | opts | |
78 | ) | |
79 | this.setTaskStatisticsRequirements(this.opts) | |
80 | } | |
81 | ||
82 | /** @inheritDoc */ | |
83 | public abstract update (workerNodeKey: number): boolean | |
84 | ||
a38b62f1 | 85 | /** |
8e8d9101 | 86 | * Check the next worker node key. |
a38b62f1 | 87 | */ |
8e8d9101 JB |
88 | protected checkNextWorkerNodeKey (): void { |
89 | if ( | |
90 | this.nextWorkerNodeKey != null && | |
91 | (this.nextWorkerNodeKey < 0 || | |
92 | !this.isWorkerNodeReady(this.nextWorkerNodeKey)) | |
93 | ) { | |
a38b62f1 JB |
94 | delete this.nextWorkerNodeKey |
95 | } | |
96 | } | |
97 | ||
97231086 JB |
98 | /** |
99 | * Gets the worker node task ELU. | |
100 | * If the task statistics require the average ELU, the average ELU is returned. | |
101 | * If the task statistics require the median ELU, the median ELU is returned. | |
102 | * @param workerNodeKey - The worker node key. | |
103 | * @returns The worker node task ELU. | |
104 | */ | |
105 | protected getWorkerNodeTaskElu (workerNodeKey: number): number { | |
106 | return this.taskStatisticsRequirements.elu.median | |
c18e0539 JB |
107 | ? (this.pool.workerNodes[workerNodeKey]?.usage.elu.active.median ?? 0) |
108 | : (this.pool.workerNodes[workerNodeKey]?.usage.elu.active.average ?? 0) | |
97231086 JB |
109 | } |
110 | ||
f6b641d6 | 111 | /** |
f3a91bac | 112 | * Gets the worker node task runtime. |
932fc8be | 113 | * If the task statistics require the average runtime, the average runtime is returned. |
e0843544 | 114 | * If the task statistics require the median runtime, the median runtime is returned. |
f6b641d6 | 115 | * @param workerNodeKey - The worker node key. |
f3a91bac | 116 | * @returns The worker node task runtime. |
f6b641d6 | 117 | */ |
f3a91bac | 118 | protected getWorkerNodeTaskRunTime (workerNodeKey: number): number { |
932fc8be | 119 | return this.taskStatisticsRequirements.runTime.median |
c18e0539 JB |
120 | ? (this.pool.workerNodes[workerNodeKey]?.usage.runTime.median ?? 0) |
121 | : (this.pool.workerNodes[workerNodeKey]?.usage.runTime.average ?? 0) | |
f6b641d6 JB |
122 | } |
123 | ||
ef680bb8 | 124 | /** |
f3a91bac | 125 | * Gets the worker node task wait time. |
932fc8be JB |
126 | * If the task statistics require the average wait time, the average wait time is returned. |
127 | * If the task statistics require the median wait time, the median wait time is returned. | |
ef680bb8 | 128 | * @param workerNodeKey - The worker node key. |
f3a91bac | 129 | * @returns The worker node task wait time. |
ef680bb8 | 130 | */ |
f3a91bac | 131 | protected getWorkerNodeTaskWaitTime (workerNodeKey: number): number { |
932fc8be | 132 | return this.taskStatisticsRequirements.waitTime.median |
c18e0539 JB |
133 | ? (this.pool.workerNodes[workerNodeKey]?.usage.waitTime.median ?? 0) |
134 | : (this.pool.workerNodes[workerNodeKey]?.usage.waitTime.average ?? 0) | |
ef680bb8 JB |
135 | } |
136 | ||
5df69fab | 137 | /** |
97231086 | 138 | * Whether the worker node is ready or not. |
5df69fab | 139 | * @param workerNodeKey - The worker node key. |
97231086 | 140 | * @returns Whether the worker node is ready or not. |
5df69fab | 141 | */ |
97231086 | 142 | protected isWorkerNodeReady (workerNodeKey: number): boolean { |
c18e0539 | 143 | return this.pool.workerNodes[workerNodeKey]?.info.ready ?? false |
97231086 JB |
144 | } |
145 | ||
146 | protected resetWorkerNodeKeyProperties (): void { | |
147 | this.nextWorkerNodeKey = 0 | |
148 | this.previousWorkerNodeKey = 0 | |
5df69fab JB |
149 | } |
150 | ||
baca80f7 JB |
151 | /** |
152 | * Sets safely the previous worker node key. | |
baca80f7 JB |
153 | * @param workerNodeKey - The worker node key. |
154 | */ | |
155 | protected setPreviousWorkerNodeKey (workerNodeKey: number | undefined): void { | |
8e8d9101 JB |
156 | this.previousWorkerNodeKey = |
157 | workerNodeKey != null && workerNodeKey >= 0 | |
158 | ? workerNodeKey | |
159 | : this.previousWorkerNodeKey | |
baca80f7 | 160 | } |
97231086 JB |
161 | |
162 | protected setTaskStatisticsRequirements ( | |
163 | opts: undefined | WorkerChoiceStrategyOptions | |
164 | ): void { | |
165 | toggleMedianMeasurementStatisticsRequirements( | |
166 | this.taskStatisticsRequirements.runTime, | |
167 | // eslint-disable-next-line @typescript-eslint/no-non-null-assertion | |
168 | opts!.runTime!.median | |
169 | ) | |
170 | toggleMedianMeasurementStatisticsRequirements( | |
171 | this.taskStatisticsRequirements.waitTime, | |
172 | // eslint-disable-next-line @typescript-eslint/no-non-null-assertion | |
173 | opts!.waitTime!.median | |
174 | ) | |
175 | toggleMedianMeasurementStatisticsRequirements( | |
176 | this.taskStatisticsRequirements.elu, | |
177 | // eslint-disable-next-line @typescript-eslint/no-non-null-assertion | |
178 | opts!.elu!.median | |
179 | ) | |
180 | } | |
bdaf31cd | 181 | } |