UNPKG

3.34 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, '__esModule', {
4 value: true
5});
6exports.default = void 0;
7
8function _mergeStream() {
9 const data = _interopRequireDefault(require('merge-stream'));
10
11 _mergeStream = function () {
12 return data;
13 };
14
15 return data;
16}
17
18var _types = require('../types');
19
20function _interopRequireDefault(obj) {
21 return obj && obj.__esModule ? obj : {default: obj};
22}
23
24/**
25 * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
26 *
27 * This source code is licensed under the MIT license found in the
28 * LICENSE file in the root directory of this source tree.
29 */
30// How long to wait for the child process to terminate
31// after CHILD_MESSAGE_END before sending force exiting.
32const FORCE_EXIT_DELAY = 500;
33/* istanbul ignore next */
34// eslint-disable-next-line @typescript-eslint/no-empty-function
35
36const emptyMethod = () => {};
37
38class BaseWorkerPool {
39 _stderr;
40 _stdout;
41 _options;
42 _workers;
43
44 constructor(workerPath, options) {
45 this._options = options;
46 this._workers = new Array(options.numWorkers);
47 const stdout = (0, _mergeStream().default)();
48 const stderr = (0, _mergeStream().default)();
49 const {forkOptions, maxRetries, resourceLimits, setupArgs} = options;
50
51 for (let i = 0; i < options.numWorkers; i++) {
52 const workerOptions = {
53 forkOptions,
54 idleMemoryLimit: this._options.idleMemoryLimit,
55 maxRetries,
56 resourceLimits,
57 setupArgs,
58 workerId: i,
59 workerPath
60 };
61 const worker = this.createWorker(workerOptions);
62 const workerStdout = worker.getStdout();
63 const workerStderr = worker.getStderr();
64
65 if (workerStdout) {
66 stdout.add(workerStdout);
67 }
68
69 if (workerStderr) {
70 stderr.add(workerStderr);
71 }
72
73 this._workers[i] = worker;
74 }
75
76 this._stdout = stdout;
77 this._stderr = stderr;
78 }
79
80 getStderr() {
81 return this._stderr;
82 }
83
84 getStdout() {
85 return this._stdout;
86 }
87
88 getWorkers() {
89 return this._workers;
90 }
91
92 getWorkerById(workerId) {
93 return this._workers[workerId];
94 }
95
96 createWorker(_workerOptions) {
97 throw Error('Missing method createWorker in WorkerPool');
98 }
99
100 async end() {
101 // We do not cache the request object here. If so, it would only be only
102 // processed by one of the workers, and we want them all to close.
103 const workerExitPromises = this._workers.map(async worker => {
104 worker.send(
105 [_types.CHILD_MESSAGE_END, false],
106 emptyMethod,
107 emptyMethod,
108 emptyMethod
109 ); // Schedule a force exit in case worker fails to exit gracefully so
110 // await worker.waitForExit() never takes longer than FORCE_EXIT_DELAY
111
112 let forceExited = false;
113 const forceExitTimeout = setTimeout(() => {
114 worker.forceExit();
115 forceExited = true;
116 }, FORCE_EXIT_DELAY);
117 await worker.waitForExit(); // Worker ideally exited gracefully, don't send force exit then
118
119 clearTimeout(forceExitTimeout);
120 return forceExited;
121 });
122
123 const workerExits = await Promise.all(workerExitPromises);
124 return workerExits.reduce(
125 (result, forceExited) => ({
126 forceExited: result.forceExited || forceExited
127 }),
128 {
129 forceExited: false
130 }
131 );
132 }
133}
134
135exports.default = BaseWorkerPool;