@parcel/workers 2.0.0-nightly.92 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/WorkerFarm.js CHANGED
@@ -20,7 +20,7 @@ import {
20
20
  restoreDeserializedObject,
21
21
  serialize,
22
22
  } from '@parcel/core';
23
- import ThrowableDiagnostic, {anyToDiagnostic} from '@parcel/diagnostic';
23
+ import ThrowableDiagnostic, {anyToDiagnostic, md} from '@parcel/diagnostic';
24
24
  import Worker, {type WorkerCall} from './Worker';
25
25
  import cpuCount from './cpuCount';
26
26
  import Handle from './Handle';
@@ -31,9 +31,10 @@ import Trace from './Trace';
31
31
  import fs from 'fs';
32
32
  import logger from '@parcel/logger';
33
33
 
34
- let profileId = 1;
35
34
  let referenceId = 1;
36
35
 
36
+ export opaque type SharedReference = number;
37
+
37
38
  export type FarmOptions = {|
38
39
  maxConcurrentWorkers: number,
39
40
  maxConcurrentCallsPerWorker: number,
@@ -42,7 +43,7 @@ export type FarmOptions = {|
42
43
  warmWorkers: boolean,
43
44
  workerPath?: FilePath,
44
45
  backend: BackendType,
45
- patchConsole?: boolean,
46
+ shouldPatchConsole?: boolean,
46
47
  |};
47
48
 
48
49
  type WorkerModule = {|
@@ -52,7 +53,8 @@ type WorkerModule = {|
52
53
  export type WorkerApi = {|
53
54
  callMaster(CallRequest, ?boolean): Promise<mixed>,
54
55
  createReverseHandle(fn: HandleFunction): Handle,
55
- getSharedReference(ref: number): mixed,
56
+ getSharedReference(ref: SharedReference): mixed,
57
+ resolveSharedReference(value: mixed): ?SharedReference,
56
58
  callChild?: (childId: number, request: HandleCallRequest) => Promise<mixed>,
57
59
  |};
58
60
 
@@ -66,12 +68,14 @@ export default class WorkerFarm extends EventEmitter {
66
68
  callQueue: Array<WorkerCall> = [];
67
69
  ending: boolean = false;
68
70
  localWorker: WorkerModule;
71
+ localWorkerInit: ?Promise<void>;
69
72
  options: FarmOptions;
70
73
  run: HandleFunction;
71
74
  warmWorkers: number = 0;
72
75
  workers: Map<number, Worker> = new Map();
73
76
  handles: Map<number, Handle> = new Map();
74
- sharedReferences: Map<number, mixed> = new Map();
77
+ sharedReferences: Map<SharedReference, mixed> = new Map();
78
+ sharedReferencesByValue: Map<mixed, SharedReference> = new Map();
75
79
  profiler: ?Profiler;
76
80
 
77
81
  constructor(farmOptions: $Shape<FarmOptions> = {}) {
@@ -92,12 +96,24 @@ export default class WorkerFarm extends EventEmitter {
92
96
 
93
97
  // $FlowFixMe this must be dynamic
94
98
  this.localWorker = require(this.options.workerPath);
99
+ this.localWorkerInit =
100
+ this.localWorker.childInit != null ? this.localWorker.childInit() : null;
95
101
  this.run = this.createHandle('run');
96
102
 
97
103
  this.startMaxWorkers();
98
104
  }
99
105
 
100
- workerApi = {
106
+ workerApi: {|
107
+ callChild: (childId: number, request: HandleCallRequest) => Promise<mixed>,
108
+ callMaster: (
109
+ request: CallRequest,
110
+ awaitResponse?: ?boolean,
111
+ ) => Promise<mixed>,
112
+ createReverseHandle: (fn: HandleFunction) => Handle,
113
+ getSharedReference: (ref: SharedReference) => mixed,
114
+ resolveSharedReference: (value: mixed) => void | SharedReference,
115
+ runHandle: (handle: Handle, args: Array<any>) => Promise<mixed>,
116
+ |} = {
101
117
  callMaster: async (
102
118
  request: CallRequest,
103
119
  awaitResponse: ?boolean = true,
@@ -120,7 +136,15 @@ export default class WorkerFarm extends EventEmitter {
120
136
  retries: 0,
121
137
  });
122
138
  }),
123
- getSharedReference: (ref: number) => this.sharedReferences.get(ref),
139
+ runHandle: (handle: Handle, args: Array<any>): Promise<mixed> =>
140
+ this.workerApi.callChild(nullthrows(handle.childId), {
141
+ handle: handle.id,
142
+ args,
143
+ }),
144
+ getSharedReference: (ref: SharedReference) =>
145
+ this.sharedReferences.get(ref),
146
+ resolveSharedReference: (value: mixed) =>
147
+ this.sharedReferencesByValue.get(value),
124
148
  };
125
149
 
126
150
  warmupWorker(method: string, args: Array<any>): void {
@@ -152,7 +176,7 @@ export default class WorkerFarm extends EventEmitter {
152
176
  }
153
177
 
154
178
  createHandle(method: string): HandleFunction {
155
- return (...args) => {
179
+ return async (...args) => {
156
180
  // Child process workers are slow to start (~600ms).
157
181
  // While we're waiting, just run on the main thread.
158
182
  // This significantly speeds up startup time.
@@ -166,15 +190,22 @@ export default class WorkerFarm extends EventEmitter {
166
190
  let processedArgs = restoreDeserializedObject(
167
191
  prepareForSerialization([...args, false]),
168
192
  );
193
+
194
+ if (this.localWorkerInit != null) {
195
+ await this.localWorkerInit;
196
+ this.localWorkerInit = null;
197
+ }
169
198
  return this.localWorker[method](this.workerApi, ...processedArgs);
170
199
  }
171
200
  };
172
201
  }
173
202
 
174
- onError(error: ErrorWithCode, worker: Worker) {
203
+ onError(error: ErrorWithCode, worker: Worker): void | Promise<void> {
175
204
  // Handle ipc errors
176
205
  if (error.code === 'ERR_IPC_CHANNEL_CLOSED') {
177
206
  return this.stopWorker(worker);
207
+ } else {
208
+ logger.error(error, '@parcel/workers');
178
209
  }
179
210
  }
180
211
 
@@ -182,7 +213,8 @@ export default class WorkerFarm extends EventEmitter {
182
213
  let worker = new Worker({
183
214
  forcedKillTime: this.options.forcedKillTime,
184
215
  backend: this.options.backend,
185
- patchConsole: this.options.patchConsole,
216
+ shouldPatchConsole: this.options.shouldPatchConsole,
217
+ sharedReferences: this.sharedReferences,
186
218
  });
187
219
 
188
220
  worker.fork(nullthrows(this.options.workerPath));
@@ -227,7 +259,11 @@ export default class WorkerFarm extends EventEmitter {
227
259
  this.startChild();
228
260
  }
229
261
 
230
- for (let worker of this.workers.values()) {
262
+ let workers = [...this.workers.values()].sort(
263
+ (a, b) => a.calls.size - b.calls.size,
264
+ );
265
+
266
+ for (let worker of workers) {
231
267
  if (!this.callQueue.length) {
232
268
  break;
233
269
  }
@@ -251,7 +287,7 @@ export default class WorkerFarm extends EventEmitter {
251
287
  let {method, args, location, awaitResponse, idx, handle: handleId} = data;
252
288
  let mod;
253
289
  if (handleId != null) {
254
- mod = nullthrows(this.handles.get(handleId)).fn;
290
+ mod = nullthrows(this.handles.get(handleId)?.fn);
255
291
  } else if (location) {
256
292
  // $FlowFixMe this must be dynamic
257
293
  mod = require(location);
@@ -282,7 +318,6 @@ export default class WorkerFarm extends EventEmitter {
282
318
  }
283
319
  } else {
284
320
  // ESModule default interop
285
- // $FlowFixMe
286
321
  if (mod.__esModule && !mod[method] && mod.default) {
287
322
  mod = mod.default;
288
323
  }
@@ -327,15 +362,17 @@ export default class WorkerFarm extends EventEmitter {
327
362
  async end(): Promise<void> {
328
363
  this.ending = true;
329
364
 
365
+ await Promise.all(
366
+ Array.from(this.workers.values()).map(worker => this.stopWorker(worker)),
367
+ );
368
+
330
369
  for (let handle of this.handles.values()) {
331
370
  handle.dispose();
332
371
  }
333
372
  this.handles = new Map();
334
373
  this.sharedReferences = new Map();
374
+ this.sharedReferencesByValue = new Map();
335
375
 
336
- await Promise.all(
337
- Array.from(this.workers.values()).map(worker => this.stopWorker(worker)),
338
- );
339
376
  this.ending = false;
340
377
  }
341
378
 
@@ -357,28 +394,28 @@ export default class WorkerFarm extends EventEmitter {
357
394
  );
358
395
  }
359
396
 
360
- createReverseHandle(fn: HandleFunction) {
361
- let handle = new Handle({fn, workerApi: this.workerApi});
397
+ createReverseHandle(fn: HandleFunction): Handle {
398
+ let handle = new Handle({fn});
362
399
  this.handles.set(handle.id, handle);
363
400
  return handle;
364
401
  }
365
402
 
366
- async createSharedReference(value: mixed) {
403
+ async createSharedReference(
404
+ value: mixed,
405
+ // An optional, pre-serialized representation of the value to be used
406
+ // in its place.
407
+ buffer?: Buffer,
408
+ ): Promise<{|ref: SharedReference, dispose(): Promise<mixed>|}> {
367
409
  let ref = referenceId++;
368
410
  this.sharedReferences.set(ref, value);
411
+ this.sharedReferencesByValue.set(value, ref);
412
+
413
+ let toSend = buffer ? buffer.buffer : value;
369
414
  let promises = [];
370
415
  for (let worker of this.workers.values()) {
371
- promises.push(
372
- new Promise((resolve, reject) => {
373
- worker.call({
374
- method: 'createSharedReference',
375
- args: [ref, value],
376
- resolve,
377
- reject,
378
- retries: 0,
379
- });
380
- }),
381
- );
416
+ if (worker.ready) {
417
+ promises.push(worker.sendSharedReference(ref, toSend));
418
+ }
382
419
  }
383
420
 
384
421
  await Promise.all(promises);
@@ -387,6 +424,7 @@ export default class WorkerFarm extends EventEmitter {
387
424
  ref,
388
425
  dispose: () => {
389
426
  this.sharedReferences.delete(ref);
427
+ this.sharedReferencesByValue.delete(value);
390
428
  let promises = [];
391
429
  for (let worker of this.workers.values()) {
392
430
  promises.push(
@@ -396,6 +434,7 @@ export default class WorkerFarm extends EventEmitter {
396
434
  args: [ref],
397
435
  resolve,
398
436
  reject,
437
+ skipReadyCheck: true,
399
438
  retries: 0,
400
439
  });
401
440
  }),
@@ -417,6 +456,7 @@ export default class WorkerFarm extends EventEmitter {
417
456
  resolve,
418
457
  reject,
419
458
  retries: 0,
459
+ skipReadyCheck: true,
420
460
  });
421
461
  }),
422
462
  );
@@ -446,6 +486,7 @@ export default class WorkerFarm extends EventEmitter {
446
486
  resolve,
447
487
  reject,
448
488
  retries: 0,
489
+ skipReadyCheck: true,
449
490
  });
450
491
  }),
451
492
  );
@@ -453,7 +494,7 @@ export default class WorkerFarm extends EventEmitter {
453
494
 
454
495
  var profiles = await Promise.all(promises);
455
496
  let trace = new Trace();
456
- let filename = `profile-${profileId++}.trace`;
497
+ let filename = `profile-${getTimeId()}.trace`;
457
498
  let stream = trace.pipe(fs.createWriteStream(filename));
458
499
 
459
500
  for (let profile of profiles) {
@@ -467,21 +508,84 @@ export default class WorkerFarm extends EventEmitter {
467
508
 
468
509
  logger.info({
469
510
  origin: '@parcel/workers',
470
- message: `Wrote profile to ${filename}`,
511
+ message: md`Wrote profile to ${filename}`,
471
512
  });
472
513
  }
473
514
 
474
- static getNumWorkers() {
515
+ async callAllWorkers(method: string, args: Array<any>) {
516
+ let promises = [];
517
+ for (let worker of this.workers.values()) {
518
+ promises.push(
519
+ new Promise((resolve, reject) => {
520
+ worker.call({
521
+ method,
522
+ args,
523
+ resolve,
524
+ reject,
525
+ retries: 0,
526
+ });
527
+ }),
528
+ );
529
+ }
530
+
531
+ promises.push(this.localWorker[method](this.workerApi, ...args));
532
+ await Promise.all(promises);
533
+ }
534
+
535
+ async takeHeapSnapshot() {
536
+ let snapshotId = getTimeId();
537
+
538
+ try {
539
+ let snapshotPaths = await Promise.all(
540
+ [...this.workers.values()].map(
541
+ worker =>
542
+ new Promise((resolve, reject) => {
543
+ worker.call({
544
+ method: 'takeHeapSnapshot',
545
+ args: [snapshotId],
546
+ resolve,
547
+ reject,
548
+ retries: 0,
549
+ skipReadyCheck: true,
550
+ });
551
+ }),
552
+ ),
553
+ );
554
+
555
+ logger.info({
556
+ origin: '@parcel/workers',
557
+ message: md`Wrote heap snapshots to the following paths:\n${snapshotPaths.join(
558
+ '\n',
559
+ )}`,
560
+ });
561
+ } catch {
562
+ logger.error({
563
+ origin: '@parcel/workers',
564
+ message: 'Unable to take heap snapshots. Note: requires Node 11.13.0+',
565
+ });
566
+ }
567
+ }
568
+
569
+ static getNumWorkers(): number {
475
570
  return process.env.PARCEL_WORKERS
476
571
  ? parseInt(process.env.PARCEL_WORKERS, 10)
477
- : cpuCount();
572
+ : Math.ceil(cpuCount() / 2);
478
573
  }
479
574
 
480
- static isWorker() {
575
+ static isWorker(): boolean {
481
576
  return !!child;
482
577
  }
483
578
 
484
- static getWorkerApi() {
579
+ static getWorkerApi(): {|
580
+ callMaster: (
581
+ request: CallRequest,
582
+ awaitResponse?: ?boolean,
583
+ ) => Promise<mixed>,
584
+ createReverseHandle: (fn: (...args: Array<any>) => mixed) => Handle,
585
+ getSharedReference: (ref: SharedReference) => mixed,
586
+ resolveSharedReference: (value: mixed) => void | SharedReference,
587
+ runHandle: (handle: Handle, args: Array<any>) => Promise<mixed>,
588
+ |} {
485
589
  invariant(
486
590
  child != null,
487
591
  'WorkerFarm.getWorkerApi can only be called within workers',
@@ -489,7 +593,20 @@ export default class WorkerFarm extends EventEmitter {
489
593
  return child.workerApi;
490
594
  }
491
595
 
492
- static getConcurrentCallsPerWorker() {
493
- return parseInt(process.env.PARCEL_MAX_CONCURRENT_CALLS, 10) || 5;
596
+ static getConcurrentCallsPerWorker(): number {
597
+ return parseInt(process.env.PARCEL_MAX_CONCURRENT_CALLS, 10) || 30;
494
598
  }
495
599
  }
600
+
601
+ function getTimeId() {
602
+ let now = new Date();
603
+ return (
604
+ String(now.getFullYear()) +
605
+ String(now.getMonth() + 1).padStart(2, '0') +
606
+ String(now.getDate()).padStart(2, '0') +
607
+ '-' +
608
+ String(now.getHours()).padStart(2, '0') +
609
+ String(now.getMinutes()).padStart(2, '0') +
610
+ String(now.getSeconds()).padStart(2, '0')
611
+ );
612
+ }
package/src/backend.js CHANGED
@@ -2,6 +2,12 @@
2
2
  import type {BackendType, WorkerImpl} from './types';
3
3
 
4
4
  export function detectBackend(): BackendType {
5
+ switch (process.env.PARCEL_WORKER_BACKEND) {
6
+ case 'threads':
7
+ case 'process':
8
+ return process.env.PARCEL_WORKER_BACKEND;
9
+ }
10
+
5
11
  try {
6
12
  require('worker_threads');
7
13
  return 'threads';
package/src/bus.js CHANGED
@@ -20,4 +20,4 @@ class Bus extends EventEmitter {
20
20
  }
21
21
  }
22
22
 
23
- export default new Bus();
23
+ export default (new Bus(): Bus);
package/src/child.js CHANGED
@@ -9,16 +9,20 @@ import type {
9
9
  WorkerResponse,
10
10
  ChildImpl,
11
11
  } from './types';
12
- import type {IDisposable} from '@parcel/types';
13
- import type {WorkerApi} from './WorkerFarm';
12
+ import type {Async, IDisposable} from '@parcel/types';
13
+ import type {SharedReference, WorkerApi} from './WorkerFarm';
14
14
 
15
15
  import invariant from 'assert';
16
16
  import nullthrows from 'nullthrows';
17
17
  import Logger, {patchConsole, unpatchConsole} from '@parcel/logger';
18
18
  import ThrowableDiagnostic, {anyToDiagnostic} from '@parcel/diagnostic';
19
+ import {deserialize} from '@parcel/core';
19
20
  import bus from './bus';
20
21
  import Profiler from './Profiler';
21
- import Handle from './Handle';
22
+ import _Handle from './Handle';
23
+
24
+ // The import of './Handle' should really be imported eagerly (with @babel/plugin-transform-modules-commonjs's lazy mode).
25
+ const Handle = _Handle;
22
26
 
23
27
  type ChildCall = WorkerRequest & {|
24
28
  resolve: (result: Promise<any> | any) => void,
@@ -30,19 +34,22 @@ export class Child {
30
34
  childId: ?number;
31
35
  maxConcurrentCalls: number = 10;
32
36
  module: ?any;
33
- responseId = 0;
37
+ responseId: number = 0;
34
38
  responseQueue: Map<number, ChildCall> = new Map();
35
39
  loggerDisposable: IDisposable;
36
40
  child: ChildImpl;
37
41
  profiler: ?Profiler;
38
42
  workerApi: WorkerApi;
39
43
  handles: Map<number, Handle> = new Map();
40
- sharedReferences: Map<number, mixed> = new Map();
44
+ sharedReferences: Map<SharedReference, mixed> = new Map();
45
+ sharedReferencesByValue: Map<mixed, SharedReference> = new Map();
41
46
 
42
47
  constructor(ChildBackend: Class<ChildImpl>) {
43
48
  this.child = new ChildBackend(
44
- this.messageListener.bind(this),
45
- this.handleEnd.bind(this),
49
+ m => {
50
+ this.messageListener(m);
51
+ },
52
+ () => this.handleEnd(),
46
53
  );
47
54
 
48
55
  // Monitior all logging events inside this child process and forward to
@@ -52,17 +59,31 @@ export class Child {
52
59
  });
53
60
  }
54
61
 
55
- workerApi = {
62
+ workerApi: {|
63
+ callMaster: (
64
+ request: CallRequest,
65
+ awaitResponse?: ?boolean,
66
+ ) => Promise<mixed>,
67
+ createReverseHandle: (fn: (...args: Array<any>) => mixed) => Handle,
68
+ getSharedReference: (ref: SharedReference) => mixed,
69
+ resolveSharedReference: (value: mixed) => void | SharedReference,
70
+ runHandle: (handle: Handle, args: Array<any>) => Promise<mixed>,
71
+ |} = {
56
72
  callMaster: (
57
73
  request: CallRequest,
58
74
  awaitResponse: ?boolean = true,
59
75
  ): Promise<mixed> => this.addCall(request, awaitResponse),
60
76
  createReverseHandle: (fn: (...args: Array<any>) => mixed): Handle =>
61
77
  this.createReverseHandle(fn),
62
- getSharedReference: (ref: number) => this.sharedReferences.get(ref),
78
+ runHandle: (handle: Handle, args: Array<any>): Promise<mixed> =>
79
+ this.workerApi.callMaster({handle: handle.id, args}, true),
80
+ getSharedReference: (ref: SharedReference) =>
81
+ this.sharedReferences.get(ref),
82
+ resolveSharedReference: (value: mixed) =>
83
+ this.sharedReferencesByValue.get(value),
63
84
  };
64
85
 
65
- messageListener(message: WorkerMessage): void | Promise<void> {
86
+ messageListener(message: WorkerMessage): Async<void> {
66
87
  if (message.type === 'response') {
67
88
  return this.handleResponse(message);
68
89
  } else if (message.type === 'request') {
@@ -74,10 +95,14 @@ export class Child {
74
95
  this.child.send(data);
75
96
  }
76
97
 
77
- childInit(module: string, childId: number): void {
98
+ async childInit(module: string, childId: number): Promise<void> {
78
99
  // $FlowFixMe this must be dynamic
79
100
  this.module = require(module);
80
101
  this.childId = childId;
102
+
103
+ if (this.module.childInit != null) {
104
+ await this.module.childInit();
105
+ }
81
106
  }
82
107
 
83
108
  async handleRequest(data: WorkerRequest): Promise<void> {
@@ -103,7 +128,7 @@ export class Child {
103
128
  let result;
104
129
  if (handleId != null) {
105
130
  try {
106
- let fn = nullthrows(this.handles.get(handleId)).fn;
131
+ let fn = nullthrows(this.handles.get(handleId)?.fn);
107
132
  result = responseFromContent(fn(...args));
108
133
  } catch (e) {
109
134
  result = errorResponseFromError(e);
@@ -111,13 +136,13 @@ export class Child {
111
136
  } else if (method === 'childInit') {
112
137
  try {
113
138
  let [moduleName, childOptions] = args;
114
- if (childOptions.patchConsole) {
139
+ if (childOptions.shouldPatchConsole) {
115
140
  patchConsole();
116
141
  } else {
117
142
  unpatchConsole();
118
143
  }
119
144
 
120
- result = responseFromContent(this.childInit(moduleName, child));
145
+ result = responseFromContent(await this.childInit(moduleName, child));
121
146
  } catch (e) {
122
147
  result = errorResponseFromError(e);
123
148
  }
@@ -135,11 +160,38 @@ export class Child {
135
160
  } catch (e) {
136
161
  result = errorResponseFromError(e);
137
162
  }
163
+ } else if (method === 'takeHeapSnapshot') {
164
+ try {
165
+ let v8 = require('v8');
166
+ result = responseFromContent(
167
+ // $FlowFixMe
168
+ v8.writeHeapSnapshot(
169
+ 'heap-' +
170
+ args[0] +
171
+ '-' +
172
+ (this.childId ? 'worker' + this.childId : 'main') +
173
+ '.heapsnapshot',
174
+ ),
175
+ );
176
+ } catch (e) {
177
+ result = errorResponseFromError(e);
178
+ }
138
179
  } else if (method === 'createSharedReference') {
139
- this.sharedReferences.set(args[0], args[1]);
180
+ let [ref, _value] = args;
181
+ let value =
182
+ _value instanceof ArrayBuffer
183
+ ? // In the case the value is pre-serialized as a buffer,
184
+ // deserialize it.
185
+ deserialize(Buffer.from(_value))
186
+ : _value;
187
+ this.sharedReferences.set(ref, value);
188
+ this.sharedReferencesByValue.set(value, ref);
140
189
  result = responseFromContent(null);
141
190
  } else if (method === 'deleteSharedReference') {
142
- this.sharedReferences.delete(args[0]);
191
+ let ref = args[0];
192
+ let value = this.sharedReferences.get(ref);
193
+ this.sharedReferencesByValue.delete(value);
194
+ this.sharedReferences.delete(ref);
143
195
  result = responseFromContent(null);
144
196
  } else {
145
197
  try {
@@ -152,7 +204,11 @@ export class Child {
152
204
  }
153
205
  }
154
206
 
155
- this.send(result);
207
+ try {
208
+ this.send(result);
209
+ } catch (e) {
210
+ result = this.send(errorResponseFromError(e));
211
+ }
156
212
  }
157
213
 
158
214
  handleResponse(data: WorkerResponse): void {
@@ -184,6 +240,7 @@ export class Child {
184
240
  ...request,
185
241
  type: 'request',
186
242
  child: this.childId,
243
+ // $FlowFixMe Added in Flow 0.121.0 upgrade in #4381
187
244
  awaitResponse,
188
245
  resolve: () => {},
189
246
  reject: () => {},
@@ -236,10 +293,9 @@ export class Child {
236
293
  this.loggerDisposable.dispose();
237
294
  }
238
295
 
239
- createReverseHandle(fn: (...args: Array<any>) => mixed) {
296
+ createReverseHandle(fn: (...args: Array<any>) => mixed): Handle {
240
297
  let handle = new Handle({
241
298
  fn,
242
- workerApi: this.workerApi,
243
299
  childId: this.childId,
244
300
  });
245
301
  this.handles.set(handle.id, handle);
package/src/cpuCount.js CHANGED
@@ -26,6 +26,11 @@ export function detectRealCores(): number {
26
26
  );
27
27
  } else if (platform === 'darwin') {
28
28
  amount = parseInt(exec('sysctl -n hw.physicalcpu_max'), 10);
29
+ } else if (platform === 'win32') {
30
+ const str = exec('wmic cpu get NumberOfCores').match(/\d+/g);
31
+ if (str !== null) {
32
+ amount = parseInt(str.filter(n => n !== '')[0], 10);
33
+ }
29
34
  }
30
35
 
31
36
  if (!amount || amount <= 0) {
@@ -36,9 +41,8 @@ export function detectRealCores(): number {
36
41
  }
37
42
 
38
43
  let cores;
39
- export default function getCores(bypassCache?: boolean = false) {
44
+ export default function getCores(bypassCache?: boolean = false): number {
40
45
  // Do not re-run commands if we already have the count...
41
- // $FlowFixMe
42
46
  if (cores && !bypassCache) {
43
47
  return cores;
44
48
  }
@@ -49,8 +53,9 @@ export default function getCores(bypassCache?: boolean = false) {
49
53
  // Guess the amount of real cores
50
54
  cores = os
51
55
  .cpus()
52
- .filter((cpu, index) => !cpu.model.includes('Intel') || index % 2 === 1)
53
- .length;
56
+ .filter(
57
+ (cpu, index) => !cpu.model.includes('Intel') || index % 2 === 1,
58
+ ).length;
54
59
  }
55
60
 
56
61
  // Another fallback
package/src/index.js CHANGED
@@ -34,4 +34,4 @@ if (!WorkerFarm.isWorker()) {
34
34
  export default WorkerFarm;
35
35
  export {bus};
36
36
  export {Handle} from './WorkerFarm';
37
- export type {WorkerApi, FarmOptions} from './WorkerFarm';
37
+ export type {WorkerApi, FarmOptions, SharedReference} from './WorkerFarm';
@@ -25,7 +25,7 @@ export default class ProcessChild implements ChildImpl {
25
25
  process.on('message', data => this.handleMessage(data));
26
26
  }
27
27
 
28
- handleMessage(data: string) {
28
+ handleMessage(data: string): void {
29
29
  if (data === 'die') {
30
30
  return this.stop();
31
31
  }
@@ -34,7 +34,7 @@ export default class ProcessWorker implements WorkerImpl {
34
34
  this.onExit = onExit;
35
35
  }
36
36
 
37
- start() {
37
+ start(): Promise<void> {
38
38
  this.child = childProcess.fork(WORKER_PATH, process.argv, {
39
39
  execArgv: this.execArgv,
40
40
  env: process.env,
@@ -32,7 +32,7 @@ export default class ThreadsWorker implements WorkerImpl {
32
32
  this.onExit = onExit;
33
33
  }
34
34
 
35
- start() {
35
+ start(): Promise<void> {
36
36
  this.worker = new Worker(WORKER_PATH, {
37
37
  execArgv: this.execArgv,
38
38
  env: process.env,
@@ -47,7 +47,7 @@ export default class ThreadsWorker implements WorkerImpl {
47
47
  });
48
48
  }
49
49
 
50
- stop() {
50
+ stop(): Promise<void> {
51
51
  // In node 12, this returns a promise, but previously it accepted a callback
52
52
  // TODO: Pass a callback in earlier versions of Node
53
53
  return Promise.resolve(this.worker.terminate());
@@ -3,7 +3,7 @@ import os from 'os';
3
3
 
4
4
  import getCores, {detectRealCores} from '../src/cpuCount';
5
5
 
6
- describe('cpuCount', function() {
6
+ describe('cpuCount', function () {
7
7
  it('Should be able to detect real cpu count', () => {
8
8
  // Windows not supported as getting the cpu count takes a couple seconds...
9
9
  if (os.platform() === 'win32') return;