@@ -25,6 +25,11 @@ export interface IEworkOptions {
2525 * Default: 1.
2626 */
2727 minFreeThreads ?: number ;
28+ /**
29+ * Initialization function that will be executed after spawning the worker and
30+ * before sending jobs to it.
31+ */
32+ init ?: ( ) => any ;
2833}
2934
3035type WorkerResolveFn < Output > = ( result : Output ) => void ;
@@ -43,13 +48,28 @@ interface IWorkerJob<Input, Output> {
4348 reject : WorkerRejectFn ;
4449}
4550
46- interface IWorkerMessage < Output > {
47- id : number ;
48- type : 'result' ;
49- status : 'success' | 'error' ;
50- result ?: Output ;
51- error ?: any ;
52- }
51+ type IWorkerMessage < Output > =
52+ | {
53+ type : 'result' ;
54+ id : number ;
55+ status : 'success' ;
56+ result : Output ;
57+ }
58+ | {
59+ type : 'result' ;
60+ id : number ;
61+ status : 'error' ;
62+ error : any ;
63+ }
64+ | {
65+ type : 'init' ;
66+ status : 'success' ;
67+ }
68+ | {
69+ type : 'init' ;
70+ status : 'error' ;
71+ error : any ;
72+ } ;
5373
5474export class Ework < Input , Output > {
5575 private totalWorkers : number ;
@@ -69,7 +89,11 @@ export class Ework<Input, Output> {
6989 throw new TypeError ( 'options must be an object' ) ;
7090 }
7191
72- const { maxWorkers = numCpus , minFreeThreads = 1 } = options ;
92+ const {
93+ maxWorkers = numCpus ,
94+ minFreeThreads = 1 ,
95+ init = ( ) => null ,
96+ } = options ;
7397
7498 if ( ! Number . isInteger ( maxWorkers ) || maxWorkers < 1 ) {
7599 throw new RangeError ( 'options.maxWorkers must be a positive integer' ) ;
@@ -80,28 +104,41 @@ export class Ework<Input, Output> {
80104 ) ;
81105 }
82106
107+ if ( typeof init !== 'function' ) {
108+ throw new TypeError ( 'options.init must be a function' ) ;
109+ }
110+
111+ const initString = init . toString ( ) ;
83112 const workerString = worker . toString ( ) ;
84- const workerCode = makeWorkerCode ( workerString ) ;
113+ const workerCode = makeWorkerCode ( initString , workerString ) ;
85114
86115 this . totalWorkers = Math . max (
87116 Math . min ( maxWorkers , numCpus - minFreeThreads ) ,
88117 1 ,
89118 ) ;
90- this . freeWorkers = this . totalWorkers ;
119+ this . freeWorkers = 0 ;
91120
92121 this . workers = [ ] ;
93122 for ( let i = 0 ; i < this . totalWorkers ; i ++ ) {
94123 const worker = spawnWorker ( workerCode ) ;
95124 const workerObj : IWorker < Input , Output > = {
96125 worker,
97- isWorking : false ,
126+ isWorking : true ,
98127 job : null ,
99128 } ;
100129 addWorkerListener (
101130 worker ,
102131 'message' ,
103132 ( message : IWorkerMessage < Output > ) => {
104- if ( message . type === 'result' ) {
133+ if ( message . type === 'init' ) {
134+ if ( message . status === 'success' ) {
135+ workerObj . isWorking = false ;
136+ this . freeWorkers ++ ;
137+ this . run ( ) ;
138+ } else {
139+ // TODO handle init error
140+ }
141+ } else if ( message . type === 'result' ) {
105142 const job = workerObj . job ;
106143 if ( job === null ) {
107144 throw new Error ( 'UNREACHABLE' ) ;
@@ -110,9 +147,6 @@ export class Ework<Input, Output> {
110147 throw new Error ( 'UNREACHABLE' ) ;
111148 }
112149 if ( message . status === 'success' ) {
113- if ( message . result === undefined ) {
114- throw new Error ( 'UNREACHABLE' ) ;
115- }
116150 job . resolve ( message . result ) ;
117151 } else {
118152 job . reject ( new Error ( message . error ) ) ;
@@ -121,9 +155,12 @@ export class Ework<Input, Output> {
121155 workerObj . isWorking = false ;
122156 this . freeWorkers ++ ;
123157 this . run ( ) ;
158+ } else {
159+ throw new Error ( 'UNREACHABLE' ) ;
124160 }
125161 } ,
126162 ) ;
163+ worker . postMessage ( { type : 'init' } ) ;
127164 this . workers . push ( workerObj ) ;
128165 }
129166
0 commit comments