1
1
import type { Worker } from 'node:worker_threads' ;
2
2
import type { Subscription } from 'rxjs' ;
3
- import type { WorkerFactory , WorkerTask } from './types.js' ;
3
+ import type {
4
+ TaskCallback ,
5
+ WorkerFactory ,
6
+ WorkerResultInternal ,
7
+ WorkerTask ,
8
+ WorkerTaskInput ,
9
+ } from './types.js' ;
4
10
import { Subject } from 'rxjs' ;
11
+ import { WorkerFunction , WorkerResult } from './types.js' ;
12
+ import * as errors from './errors.js' ;
5
13
6
14
const taskInfoSymbol = Symbol ( 'Task Info Symbol' ) ;
7
- type TaskCallback = ( result : any | undefined , error : Error | undefined ) => void ;
8
15
type PoolStatus = 'idle' | 'working' | 'queued' ;
9
16
10
17
class WorkerPool {
@@ -23,7 +30,7 @@ class WorkerPool {
23
30
public poolStatus : PoolStatus = 'idle' ;
24
31
25
32
constructor ( workerNum : number , workerFactory : WorkerFactory ) {
26
- if ( workerNum < 1 ) throw Error ( 'TMP IMP must be at least 1 worker' ) ;
33
+ if ( workerNum < 1 ) throw new errors . ErrorWorkerPoolInvalidWorkers ( ) ;
27
34
this . workerFactory = workerFactory ;
28
35
for ( let i = 0 ; i < workerNum ; i ++ ) {
29
36
this . addWorker ( ) ;
@@ -50,9 +57,9 @@ class WorkerPool {
50
57
51
58
protected addWorker ( ) {
52
59
const worker = this . workerFactory ( ) ;
53
- const messageHandler = ( result : { result ?: unknown ; error ?: Error } ) => {
60
+ const messageHandler = ( result : WorkerResultInternal ) => {
54
61
if ( result . error != null ) worker [ taskInfoSymbol ] ( undefined , result . error ) ;
55
- else worker [ taskInfoSymbol ] ( result . result ) ;
62
+ else worker [ taskInfoSymbol ] ( result . data , undefined ) ;
56
63
worker [ taskInfoSymbol ] = undefined ;
57
64
this . freeWorkers . push ( worker ) ;
58
65
this . $workerFreed . next ( ) ;
@@ -83,7 +90,7 @@ class WorkerPool {
83
90
this . $workerFreed . next ( ) ;
84
91
}
85
92
86
- public runTask ( task : any , callback : any ) {
93
+ public runTask ( task : WorkerTaskInput , callback : TaskCallback ) {
87
94
if ( this . terminating ) throw Error ( 'TMP IMP terminating' ) ;
88
95
if ( this . freeWorkers . length === 0 ) {
89
96
this . queue . push ( { task, callback } ) ;
@@ -95,33 +102,13 @@ class WorkerPool {
95
102
const worker = this . freeWorkers . pop ( ) ! ;
96
103
if ( wasIdle ) this . $poolStatus . next ( 'working' ) ;
97
104
worker [ taskInfoSymbol ] = callback ;
98
- worker . postMessage ( task ) ;
105
+ worker . postMessage ( { type : task . type , data : task . data } , task . transferList ) ;
99
106
}
100
107
101
108
public async terminate ( force : boolean ) {
102
109
this . terminating = true ;
103
- if ( ! force ) {
104
- // Prevent new tasks and wait for exising queue to drain
105
- await new Promise < void > ( ( resolve ) => {
106
- if (
107
- this . freeWorkers . length === this . workers . size &&
108
- this . queue . length === 0
109
- ) {
110
- return resolve ( ) ;
111
- }
112
- const subscription = this . $workerFreed . subscribe ( ( ) => {
113
- // Wait for the queue to drain and the workers to free
114
- if (
115
- this . freeWorkers . length === this . workers . size &&
116
- this . queue . length === 0
117
- ) {
118
- subscription . unsubscribe ( ) ;
119
- resolve ( ) ;
120
- }
121
- } ) ;
122
- } ) ;
123
- }
124
-
110
+ // Prevent new tasks and wait for exising queue to drain
111
+ if ( ! force ) await this . settled ( ) ;
125
112
// Prevent terminations from creating new workers
126
113
this . handleDestroySubscription . unsubscribe ( ) ;
127
114
const workerTerminatePs : Array < Promise < number > > = [ ] ;
0 commit comments