-
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathdynamic.ts
More file actions
133 lines (122 loc) · 3.91 KB
/
dynamic.ts
File metadata and controls
133 lines (122 loc) · 3.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import { PoolEvents, type PoolInfo, type PoolType, PoolTypes } from '../pool.ts'
import { checkDynamicPoolSize } from '../utils.ts'
import { FixedThreadPool, type ThreadPoolOptions } from './fixed.ts'
/**
* A thread pool with a dynamic number of threads, but a guaranteed minimum number of threads.
*
* This thread pool creates new threads when the others are busy, up to the maximum number of threads.
* When the maximum number of threads is reached and workers are busy, an event is emitted. If you want to listen to this event, use the pool's `eventTarget`.
*
* @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data.
* @typeParam Response - Type of execution response. This can only be structured-cloneable data.
* @author [Alessandro Pio Ardizio](https://github.com/pioardi)
* @since 0.0.1
*/
export class DynamicThreadPool<
Data = unknown,
Response = unknown,
> extends FixedThreadPool<Data, Response> {
/**
* Whether the pool empty event has been emitted or not
*/
private emptyEventEmitted: boolean
/**
* Whether the pool full event has been emitted or not.
*/
private fullEventEmitted: boolean
/**
* Constructs a new poolifier dynamic thread pool.
*
* @param min - Minimum number of threads which are always active.
* @param max - Maximum number of threads that can be created by this pool.
* @param specifier - Specifier to an implementation of a `ThreadWorker` file.
* @param opts - Options for this dynamic thread pool.
*/
public constructor(
min: number,
max: number,
specifier: URL | string,
opts: ThreadPoolOptions = {},
) {
super(min, specifier, opts, max)
checkDynamicPoolSize(
this.minimumNumberOfWorkers,
this.maximumNumberOfWorkers!,
)
this.emptyEventEmitted = false
this.fullEventEmitted = false
}
/** @inheritDoc */
protected override shallCreateDynamicWorker(): boolean {
return (
this.started &&
!this.destroying &&
((!this.full && this.internalBusy()) || this.empty)
)
}
/** @inheritDoc */
protected override checkAndEmitDynamicWorkerCreationEvents(): void {
if (this.eventTarget != null) {
if (!this.fullEventEmitted && this.full) {
this.eventTarget.dispatchEvent(
new CustomEvent<PoolInfo>(PoolEvents.full, { detail: this.info }),
)
this.fullEventEmitted = true
}
if (this.emptyEventEmitted && !this.empty) {
this.emptyEventEmitted = false
}
}
}
/** @inheritDoc */
protected override checkAndEmitDynamicWorkerDestructionEvents(): void {
if (this.eventTarget != null) {
if (this.fullEventEmitted && !this.full) {
this.eventTarget.dispatchEvent(
new CustomEvent<PoolInfo>(PoolEvents.fullEnd, { detail: this.info }),
)
this.fullEventEmitted = false
}
if (!this.emptyEventEmitted && this.empty) {
this.eventTarget.dispatchEvent(
new CustomEvent<PoolInfo>(PoolEvents.empty, { detail: this.info }),
)
this.emptyEventEmitted = true
}
}
}
/**
* Whether the pool is empty or not.
*
* @returns The pool emptiness boolean status.
*/
private get empty(): boolean {
return (
this.minimumNumberOfWorkers === 0 &&
this.workerNodes.length === this.minimumNumberOfWorkers
)
}
/**
* Whether the pool is full or not.
*
* @returns The pool fullness boolean status.
*/
private get full(): boolean {
return (
this.workerNodes.length >=
(this.maximumNumberOfWorkers ?? this.minimumNumberOfWorkers)
)
}
/** @inheritDoc */
protected override get type(): PoolType {
return PoolTypes.dynamic
}
/** @inheritDoc */
protected override get backPressure(): boolean {
return this.full && this.internalBackPressure()
}
/** @inheritDoc */
protected override get busy(): boolean {
return this.full && this.internalBusy()
}
}