Fixes to worker selection strategies
[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'
10fcfaf4 3import type { RequiredStatistics } from './selection-strategies-types'
23ff945a
JB
4
5/**
6 * Worker virtual task timestamp.
7 */
8type WorkerVirtualTaskTimestamp = {
9 start: number
10 end: number
11}
12
13/**
14 * Selects the next worker with a fair share scheduling algorithm.
15 * Loosely modeled after the fair queueing algorithm: https://en.wikipedia.org/wiki/Fair_queuing.
16 *
17 * @template Worker Type of worker which manages the strategy.
18 * @template Data Type of data sent to the worker. This can only be serializable data.
19 * @template Response Type of response of execution. This can only be serializable data.
20 */
21export class FairShareWorkerChoiceStrategy<
ea7a90d3 22 Worker extends IPoolWorker,
23ff945a
JB
23 Data,
24 Response
25> extends AbstractWorkerChoiceStrategy<Worker, Data, Response> {
10fcfaf4 26 /** @inheritDoc */
ea7a90d3 27 public readonly requiredStatistics: RequiredStatistics = {
10fcfaf4
JB
28 runTime: true
29 }
30
23ff945a
JB
31 /**
32 * Worker last virtual task execution timestamp.
33 */
ea7a90d3 34 private readonly workerLastVirtualTaskTimestamp: Map<
23ff945a
JB
35 Worker,
36 WorkerVirtualTaskTimestamp
37 > = new Map<Worker, WorkerVirtualTaskTimestamp>()
38
ea7a90d3 39 /** @inheritDoc */
a6f7f1b4 40 public reset (): boolean {
ea7a90d3
JB
41 this.workerLastVirtualTaskTimestamp.clear()
42 return true
43 }
44
23ff945a
JB
45 /** @inheritDoc */
46 public choose (): Worker {
23ff945a
JB
47 let minWorkerVirtualTaskEndTimestamp = Infinity
48 let chosenWorker!: Worker
49 for (const worker of this.pool.workers) {
11df3590 50 this.computeWorkerLastVirtualTaskTimestamp(worker)
23ff945a
JB
51 const workerLastVirtualTaskEndTimestamp =
52 this.workerLastVirtualTaskTimestamp.get(worker)?.end ?? 0
53 if (
54 workerLastVirtualTaskEndTimestamp < minWorkerVirtualTaskEndTimestamp
55 ) {
56 minWorkerVirtualTaskEndTimestamp = workerLastVirtualTaskEndTimestamp
57 chosenWorker = worker
58 }
59 }
60 return chosenWorker
61 }
62
63 /**
11df3590
JB
64 * Computes worker last virtual task timestamp.
65 *
66 * @param worker The worker.
23ff945a 67 */
11df3590
JB
68 private computeWorkerLastVirtualTaskTimestamp (worker: Worker): void {
69 const workerVirtualTaskStartTimestamp = Math.max(
70 Date.now(),
71 this.workerLastVirtualTaskTimestamp.get(worker)?.end ?? -Infinity
72 )
73 const workerVirtualTaskEndTimestamp =
74 workerVirtualTaskStartTimestamp +
75 (this.pool.getWorkerAverageTasksRunTime(worker) ?? 0)
76 this.workerLastVirtualTaskTimestamp.set(worker, {
77 start: workerVirtualTaskStartTimestamp,
78 end: workerVirtualTaskEndTimestamp
79 })
23ff945a
JB
80 }
81}