chore: v2.4.0-3
[poolifier.git] / src / pools / selection-strategies / fair-share-worker-choice-strategy.ts
CommitLineData
ea7a90d3 1import type { IPoolWorker } from '../pool-worker'
23ff945a 2import { AbstractWorkerChoiceStrategy } from './abstract-worker-choice-strategy'
bf90656c
JB
3import type {
4 IWorkerChoiceStrategy,
5 RequiredStatistics
6} from './selection-strategies-types'
23ff945a
JB
7
8/**
9 * Worker virtual task timestamp.
10 */
78cea37e 11interface WorkerVirtualTaskTimestamp {
23ff945a
JB
12 start: number
13 end: number
14}
15
16/**
17 * Selects the next worker with a fair share scheduling algorithm.
18 * Loosely modeled after the fair queueing algorithm: https://en.wikipedia.org/wiki/Fair_queuing.
19 *
38e795c1
JB
20 * @typeParam Worker - Type of worker which manages the strategy.
21 * @typeParam Data - Type of data sent to the worker. This can only be serializable data.
22 * @typeParam Response - Type of response of execution. This can only be serializable data.
23ff945a
JB
23 */
24export class FairShareWorkerChoiceStrategy<
bf90656c
JB
25 Worker extends IPoolWorker,
26 Data,
27 Response
28 >
29 extends AbstractWorkerChoiceStrategy<Worker, Data, Response>
30 implements IWorkerChoiceStrategy {
38e795c1 31 /** {@inheritDoc} */
ea7a90d3 32 public readonly requiredStatistics: RequiredStatistics = {
10fcfaf4
JB
33 runTime: true
34 }
35
23ff945a
JB
36 /**
37 * Worker last virtual task execution timestamp.
38 */
ea7a90d3 39 private readonly workerLastVirtualTaskTimestamp: Map<
c923ce56 40 number,
78cea37e 41 WorkerVirtualTaskTimestamp
c923ce56 42 > = new Map<number, WorkerVirtualTaskTimestamp>()
23ff945a 43
38e795c1 44 /** {@inheritDoc} */
a6f7f1b4 45 public reset (): boolean {
ea7a90d3
JB
46 this.workerLastVirtualTaskTimestamp.clear()
47 return true
48 }
49
38e795c1 50 /** {@inheritDoc} */
c923ce56 51 public choose (): number {
23ff945a 52 let minWorkerVirtualTaskEndTimestamp = Infinity
c923ce56
JB
53 let chosenWorkerKey!: number
54 for (const [index] of this.pool.workers.entries()) {
55 this.computeWorkerLastVirtualTaskTimestamp(index)
23ff945a 56 const workerLastVirtualTaskEndTimestamp =
c923ce56 57 this.workerLastVirtualTaskTimestamp.get(index)?.end ?? 0
23ff945a
JB
58 if (
59 workerLastVirtualTaskEndTimestamp < minWorkerVirtualTaskEndTimestamp
60 ) {
61 minWorkerVirtualTaskEndTimestamp = workerLastVirtualTaskEndTimestamp
c923ce56 62 chosenWorkerKey = index
23ff945a
JB
63 }
64 }
c923ce56 65 return chosenWorkerKey
23ff945a
JB
66 }
67
97a2abc3
JB
68 /** {@inheritDoc} */
69 public remove (workerKey: number): boolean {
70 const workerDeleted = this.workerLastVirtualTaskTimestamp.delete(workerKey)
71 for (const [key, value] of this.workerLastVirtualTaskTimestamp.entries()) {
72 if (key > workerKey) {
73 this.workerLastVirtualTaskTimestamp.set(key - 1, value)
74 }
75 }
76 return workerDeleted
77 }
78
23ff945a 79 /**
11df3590
JB
80 * Computes worker last virtual task timestamp.
81 *
c923ce56 82 * @param workerKey - The worker key.
23ff945a 83 */
c923ce56 84 private computeWorkerLastVirtualTaskTimestamp (workerKey: number): void {
11df3590
JB
85 const workerVirtualTaskStartTimestamp = Math.max(
86 Date.now(),
c923ce56 87 this.workerLastVirtualTaskTimestamp.get(workerKey)?.end ?? -Infinity
11df3590 88 )
c923ce56 89 this.workerLastVirtualTaskTimestamp.set(workerKey, {
11df3590 90 start: workerVirtualTaskStartTimestamp,
61d849ff
JB
91 end:
92 workerVirtualTaskStartTimestamp +
c923ce56 93 (this.pool.workers[workerKey].tasksUsage.avgRunTime ?? 0)
11df3590 94 })
23ff945a
JB
95 }
96}