fix: fix worker choice strategy retries mechanism on some edge cases
[poolifier.git] / src / pools / selection-strategies / least-elu-worker-choice-strategy.ts
CommitLineData
3c93feb9
JB
1import {
2 DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS,
3 DEFAULT_WORKER_CHOICE_STRATEGY_OPTIONS
4} from '../../utils'
058a9457
JB
5import type { IPool } from '../pool'
6import type { IWorker } from '../worker'
7import { AbstractWorkerChoiceStrategy } from './abstract-worker-choice-strategy'
8import type {
9 IWorkerChoiceStrategy,
b1aae695 10 StrategyPolicy,
05302647 11 TaskStatisticsRequirements,
058a9457
JB
12 WorkerChoiceStrategyOptions
13} from './selection-strategies-types'
14
15/**
16 * Selects the worker with the least ELU.
17 *
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.
058a9457
JB
21 */
22export class LeastEluWorkerChoiceStrategy<
23 Worker extends IWorker,
24 Data = unknown,
25 Response = unknown
26 >
27 extends AbstractWorkerChoiceStrategy<Worker, Data, Response>
28 implements IWorkerChoiceStrategy {
b1aae695
JB
29 /** @inheritDoc */
30 public readonly strategyPolicy: StrategyPolicy = {
31 dynamicWorkerUsage: false,
32 dynamicWorkerReady: true
33 }
34
058a9457 35 /** @inheritDoc */
05302647 36 public readonly taskStatisticsRequirements: TaskStatisticsRequirements = {
3c93feb9
JB
37 runTime: DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS,
38 waitTime: DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS,
5df69fab
JB
39 elu: {
40 aggregate: true,
41 average: false,
42 median: false
43 }
058a9457
JB
44 }
45
46 /** @inheritDoc */
47 public constructor (
48 pool: IPool<Worker, Data, Response>,
49 opts: WorkerChoiceStrategyOptions = DEFAULT_WORKER_CHOICE_STRATEGY_OPTIONS
50 ) {
51 super(pool, opts)
e460940e 52 this.setTaskStatisticsRequirements(this.opts)
058a9457
JB
53 }
54
55 /** @inheritDoc */
56 public reset (): boolean {
57 return true
58 }
59
60 /** @inheritDoc */
61 public update (): boolean {
db703c75
JB
62 return true
63 }
64
65 /** @inheritDoc */
b1aae695
JB
66 public choose (): number | undefined {
67 const chosenWorkerNodeKey = this.leastEluNextWorkerNodeKey()
68 this.assignChosenWorkerNodeKey(chosenWorkerNodeKey)
69 return this.nextWorkerNodeKey
9b106837
JB
70 }
71
72 /** @inheritDoc */
73 public remove (): boolean {
74 return true
75 }
76
b1aae695 77 private leastEluNextWorkerNodeKey (): number | undefined {
cdb517b3 78 let minWorkerElu = Infinity
b1aae695 79 let chosenWorkerNodeKey: number | undefined
058a9457 80 for (const [workerNodeKey, workerNode] of this.pool.workerNodes.entries()) {
465b2940 81 const workerUsage = workerNode.usage
98e72cda 82 const workerElu = workerUsage.elu?.active?.aggregate ?? 0
8990357d 83 if (this.isWorkerNodeEligible(workerNodeKey) && workerElu === 0) {
b1aae695 84 chosenWorkerNodeKey = workerNodeKey
5ea80606 85 break
19dbc45b 86 } else if (
8990357d 87 this.isWorkerNodeEligible(workerNodeKey) &&
19dbc45b
JB
88 workerElu < minWorkerElu
89 ) {
cdb517b3 90 minWorkerElu = workerElu
b1aae695 91 chosenWorkerNodeKey = workerNodeKey
058a9457
JB
92 }
93 }
b1aae695 94 return chosenWorkerNodeKey
058a9457
JB
95 }
96}