Commit | Line | Data |
---|---|---|
d35e5717 | 1 | import { PoolEvents, type PoolType, PoolTypes } from '../pool.js' |
ded253e2 | 2 | import { checkDynamicPoolSize } from '../utils.js' |
d35e5717 | 3 | import { type ClusterPoolOptions, FixedClusterPool } from './fixed.js' |
f045358d | 4 | |
4ade5f1f | 5 | /** |
729c563d | 6 | * A cluster pool with a dynamic number of workers, but a guaranteed minimum number of workers. |
4ade5f1f | 7 | * |
729c563d | 8 | * This cluster pool creates new workers when the others are busy, up to the maximum number of workers. |
9cd39dd4 | 9 | * When the maximum number of workers is reached and workers are busy, an event is emitted. If you want to listen to this event, use the pool's `emitter`. |
e102732c JB |
10 | * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. |
11 | * @typeParam Response - Type of execution response. This can only be structured-cloneable data. | |
325f50bc S |
12 | * @author [Christopher Quadflieg](https://github.com/Shinigami92) |
13 | * @since 2.0.0 | |
4ade5f1f | 14 | */ |
325f50bc | 15 | export class DynamicClusterPool< |
deb85c12 JB |
16 | Data = unknown, |
17 | Response = unknown | |
325f50bc | 18 | > extends FixedClusterPool<Data, Response> { |
7923fe59 JB |
19 | /** |
20 | * Whether the pool empty event has been emitted or not | |
21 | */ | |
22 | private emptyEventEmitted: boolean | |
23 | ||
5f9e9050 JB |
24 | /** |
25 | * Whether the pool full event has been emitted or not. | |
26 | */ | |
27 | private fullEventEmitted: boolean | |
28 | ||
4ade5f1f | 29 | /** |
729c563d | 30 | * Constructs a new poolifier dynamic cluster pool. |
38e795c1 JB |
31 | * @param min - Minimum number of workers which are always active. |
32 | * @param max - Maximum number of workers that can be created by this pool. | |
33 | * @param filePath - Path to an implementation of a `ClusterWorker` file, which can be relative or absolute. | |
34 | * @param opts - Options for this dynamic cluster pool. | |
4ade5f1f S |
35 | */ |
36 | public constructor ( | |
c97c7edb | 37 | min: number, |
26ce26ca | 38 | max: number, |
31b90205 | 39 | filePath: string, |
2889bd70 | 40 | opts: ClusterPoolOptions = {} |
4ade5f1f | 41 | ) { |
26ce26ca JB |
42 | super(min, filePath, opts, max) |
43 | checkDynamicPoolSize( | |
44 | this.minimumNumberOfWorkers, | |
c63a35a0 | 45 | this.maximumNumberOfWorkers |
26ce26ca | 46 | ) |
7923fe59 | 47 | this.emptyEventEmitted = false |
5f9e9050 | 48 | this.fullEventEmitted = false |
4ade5f1f S |
49 | } |
50 | ||
d0878034 | 51 | /** @inheritDoc */ |
ae85b351 | 52 | protected override checkAndEmitDynamicWorkerCreationEvents (): void { |
7923fe59 JB |
53 | if (this.emitter != null) { |
54 | if (!this.fullEventEmitted && this.full) { | |
55 | this.emitter.emit(PoolEvents.full, this.info) | |
56 | this.fullEventEmitted = true | |
57 | } | |
58 | if (this.emptyEventEmitted && !this.empty) { | |
59 | this.emptyEventEmitted = false | |
60 | } | |
5f9e9050 JB |
61 | } |
62 | } | |
63 | ||
64 | /** @inheritDoc */ | |
ae85b351 | 65 | protected override checkAndEmitDynamicWorkerDestructionEvents (): void { |
e6cf2a95 JB |
66 | if (this.emitter != null) { |
67 | if (this.fullEventEmitted && !this.full) { | |
68 | this.emitter.emit(PoolEvents.fullEnd, this.info) | |
69 | this.fullEventEmitted = false | |
70 | } | |
7923fe59 | 71 | if (!this.emptyEventEmitted && this.empty) { |
e6cf2a95 | 72 | this.emitter.emit(PoolEvents.empty, this.info) |
7923fe59 | 73 | this.emptyEventEmitted = true |
e6cf2a95 | 74 | } |
d0878034 JB |
75 | } |
76 | } | |
77 | ||
afc003b2 | 78 | /** @inheritDoc */ |
ae85b351 | 79 | protected override shallCreateDynamicWorker (): boolean { |
97231086 | 80 | return (!this.full && this.internalBusy()) || this.empty |
7c0ba920 JB |
81 | } |
82 | ||
227e9e9b | 83 | /** @inheritDoc */ |
ae85b351 | 84 | protected override get backPressure (): boolean { |
227e9e9b JB |
85 | return this.full && this.internalBackPressure() |
86 | } | |
87 | ||
afc003b2 | 88 | /** @inheritDoc */ |
ae85b351 | 89 | protected override get busy (): boolean { |
0527b6db | 90 | return this.full && this.internalBusy() |
c2ade475 | 91 | } |
97231086 | 92 | |
21e6b0ef JB |
93 | /** |
94 | * Whether the pool is empty or not. | |
95 | * @returns The pool emptiness boolean status. | |
96 | */ | |
97 | private get empty (): boolean { | |
98 | return ( | |
99 | this.minimumNumberOfWorkers === 0 && | |
100 | this.workerNodes.length === this.minimumNumberOfWorkers | |
101 | ) | |
102 | } | |
103 | ||
104 | /** | |
105 | * Whether the pool is full or not. | |
106 | * @returns The pool fullness boolean status. | |
107 | */ | |
108 | private get full (): boolean { | |
109 | return ( | |
110 | this.workerNodes.length >= | |
111 | (this.maximumNumberOfWorkers ?? this.minimumNumberOfWorkers) | |
112 | ) | |
113 | } | |
114 | ||
97231086 | 115 | /** @inheritDoc */ |
ae85b351 | 116 | protected override get type (): PoolType { |
97231086 JB |
117 | return PoolTypes.dynamic |
118 | } | |
4ade5f1f | 119 | } |