@atlaspack/workers 2.14.0 → 2.14.1-canary.6
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/LICENSE +201 -0
- package/lib/Handle.js +45 -0
- package/lib/Worker.js +188 -0
- package/lib/WorkerFarm.js +553 -0
- package/lib/backend.js +34 -0
- package/lib/bus.js +31 -0
- package/lib/child.js +284 -0
- package/lib/childState.js +14 -0
- package/lib/cpuCount.js +79 -0
- package/lib/index.js +75 -0
- package/lib/process/ProcessChild.js +58 -0
- package/lib/process/ProcessWorker.js +83 -0
- package/lib/threads/ThreadsChild.js +49 -0
- package/lib/threads/ThreadsWorker.js +61 -0
- package/lib/types.js +1 -0
- package/lib/web/WebChild.js +44 -0
- package/lib/web/WebWorker.js +85 -0
- package/package.json +9 -8
package/lib/child.js
ADDED
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.Child = void 0;
|
|
7
|
+
function _assert() {
|
|
8
|
+
const data = _interopRequireDefault(require("assert"));
|
|
9
|
+
_assert = function () {
|
|
10
|
+
return data;
|
|
11
|
+
};
|
|
12
|
+
return data;
|
|
13
|
+
}
|
|
14
|
+
function _nullthrows() {
|
|
15
|
+
const data = _interopRequireDefault(require("nullthrows"));
|
|
16
|
+
_nullthrows = function () {
|
|
17
|
+
return data;
|
|
18
|
+
};
|
|
19
|
+
return data;
|
|
20
|
+
}
|
|
21
|
+
function _buildCache() {
|
|
22
|
+
const data = require("@atlaspack/build-cache");
|
|
23
|
+
_buildCache = function () {
|
|
24
|
+
return data;
|
|
25
|
+
};
|
|
26
|
+
return data;
|
|
27
|
+
}
|
|
28
|
+
function _logger() {
|
|
29
|
+
const data = _interopRequireWildcard(require("@atlaspack/logger"));
|
|
30
|
+
_logger = function () {
|
|
31
|
+
return data;
|
|
32
|
+
};
|
|
33
|
+
return data;
|
|
34
|
+
}
|
|
35
|
+
function _diagnostic() {
|
|
36
|
+
const data = _interopRequireWildcard(require("@atlaspack/diagnostic"));
|
|
37
|
+
_diagnostic = function () {
|
|
38
|
+
return data;
|
|
39
|
+
};
|
|
40
|
+
return data;
|
|
41
|
+
}
|
|
42
|
+
var _bus = _interopRequireDefault(require("./bus"));
|
|
43
|
+
function _profiler() {
|
|
44
|
+
const data = require("@atlaspack/profiler");
|
|
45
|
+
_profiler = function () {
|
|
46
|
+
return data;
|
|
47
|
+
};
|
|
48
|
+
return data;
|
|
49
|
+
}
|
|
50
|
+
var _Handle2 = _interopRequireDefault(require("./Handle"));
|
|
51
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
52
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
53
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
54
|
+
// The import of './Handle' should really be imported eagerly (with @babel/plugin-transform-modules-commonjs's lazy mode).
|
|
55
|
+
const Handle = _Handle2.default;
|
|
56
|
+
class Child {
|
|
57
|
+
callQueue = [];
|
|
58
|
+
maxConcurrentCalls = 10;
|
|
59
|
+
responseId = 0;
|
|
60
|
+
responseQueue = new Map();
|
|
61
|
+
handles = new Map();
|
|
62
|
+
sharedReferences = new Map();
|
|
63
|
+
sharedReferencesByValue = new Map();
|
|
64
|
+
constructor(ChildBackend) {
|
|
65
|
+
this.child = new ChildBackend(m => {
|
|
66
|
+
this.messageListener(m);
|
|
67
|
+
}, () => this.handleEnd());
|
|
68
|
+
|
|
69
|
+
// Monitior all logging events inside this child process and forward to
|
|
70
|
+
// the main process via the bus.
|
|
71
|
+
this.loggerDisposable = _logger().default.onLog(event => {
|
|
72
|
+
_bus.default.emit('logEvent', event);
|
|
73
|
+
});
|
|
74
|
+
// .. and do the same for trace events
|
|
75
|
+
this.tracerDisposable = _profiler().tracer.onTrace(event => {
|
|
76
|
+
_bus.default.emit('traceEvent', event);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
workerApi = {
|
|
80
|
+
callMaster: (request, awaitResponse = true) => this.addCall(request, awaitResponse),
|
|
81
|
+
createReverseHandle: fn => this.createReverseHandle(fn),
|
|
82
|
+
runHandle: (handle, args) => this.workerApi.callMaster({
|
|
83
|
+
handle: handle.id,
|
|
84
|
+
args
|
|
85
|
+
}, true),
|
|
86
|
+
getSharedReference: ref => this.sharedReferences.get(ref),
|
|
87
|
+
resolveSharedReference: value => this.sharedReferencesByValue.get(value)
|
|
88
|
+
};
|
|
89
|
+
messageListener(message) {
|
|
90
|
+
if (message.type === 'response') {
|
|
91
|
+
return this.handleResponse(message);
|
|
92
|
+
} else if (message.type === 'request') {
|
|
93
|
+
return this.handleRequest(message);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
send(data) {
|
|
97
|
+
this.child.send(data);
|
|
98
|
+
}
|
|
99
|
+
async childInit(module, childId) {
|
|
100
|
+
// $FlowFixMe
|
|
101
|
+
this.module = require(module);
|
|
102
|
+
this.childId = childId;
|
|
103
|
+
if (this.module.childInit != null) {
|
|
104
|
+
await this.module.childInit();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
async handleRequest(data) {
|
|
108
|
+
let {
|
|
109
|
+
idx,
|
|
110
|
+
method,
|
|
111
|
+
args,
|
|
112
|
+
handle: handleId
|
|
113
|
+
} = data;
|
|
114
|
+
let child = (0, _nullthrows().default)(data.child);
|
|
115
|
+
const responseFromContent = content => ({
|
|
116
|
+
idx,
|
|
117
|
+
child,
|
|
118
|
+
type: 'response',
|
|
119
|
+
contentType: 'data',
|
|
120
|
+
content
|
|
121
|
+
});
|
|
122
|
+
const errorResponseFromError = e => ({
|
|
123
|
+
idx,
|
|
124
|
+
child,
|
|
125
|
+
type: 'response',
|
|
126
|
+
contentType: 'error',
|
|
127
|
+
content: (0, _diagnostic().anyToDiagnostic)(e)
|
|
128
|
+
});
|
|
129
|
+
let result;
|
|
130
|
+
if (handleId != null) {
|
|
131
|
+
try {
|
|
132
|
+
var _this$handles$get;
|
|
133
|
+
let fn = (0, _nullthrows().default)((_this$handles$get = this.handles.get(handleId)) === null || _this$handles$get === void 0 ? void 0 : _this$handles$get.fn);
|
|
134
|
+
result = responseFromContent(fn(...args));
|
|
135
|
+
} catch (e) {
|
|
136
|
+
result = errorResponseFromError(e);
|
|
137
|
+
}
|
|
138
|
+
} else if (method === 'childInit') {
|
|
139
|
+
try {
|
|
140
|
+
let [moduleName, childOptions] = args;
|
|
141
|
+
if (childOptions.shouldPatchConsole) {
|
|
142
|
+
(0, _logger().patchConsole)();
|
|
143
|
+
} else {
|
|
144
|
+
(0, _logger().unpatchConsole)();
|
|
145
|
+
}
|
|
146
|
+
if (childOptions.shouldTrace) {
|
|
147
|
+
_profiler().tracer.enable();
|
|
148
|
+
}
|
|
149
|
+
result = responseFromContent(await this.childInit(moduleName, child));
|
|
150
|
+
} catch (e) {
|
|
151
|
+
result = errorResponseFromError(e);
|
|
152
|
+
}
|
|
153
|
+
} else if (method === 'startProfile') {
|
|
154
|
+
this.profiler = new (_profiler().SamplingProfiler)();
|
|
155
|
+
try {
|
|
156
|
+
result = responseFromContent(await this.profiler.startProfiling());
|
|
157
|
+
} catch (e) {
|
|
158
|
+
result = errorResponseFromError(e);
|
|
159
|
+
}
|
|
160
|
+
} else if (method === 'endProfile') {
|
|
161
|
+
try {
|
|
162
|
+
let res = this.profiler ? await this.profiler.stopProfiling() : null;
|
|
163
|
+
result = responseFromContent(res);
|
|
164
|
+
} catch (e) {
|
|
165
|
+
result = errorResponseFromError(e);
|
|
166
|
+
}
|
|
167
|
+
} else if (method === 'takeHeapSnapshot') {
|
|
168
|
+
try {
|
|
169
|
+
let v8 = require('v8');
|
|
170
|
+
result = responseFromContent(v8.writeHeapSnapshot('heap-' + args[0] + '-' + (this.childId ? 'worker' + this.childId : 'main') + '.heapsnapshot'));
|
|
171
|
+
} catch (e) {
|
|
172
|
+
result = errorResponseFromError(e);
|
|
173
|
+
}
|
|
174
|
+
} else if (method === 'createSharedReference') {
|
|
175
|
+
let [ref, _value] = args;
|
|
176
|
+
let value = _value instanceof ArrayBuffer ?
|
|
177
|
+
// In the case the value is pre-serialized as a buffer,
|
|
178
|
+
// deserialize it.
|
|
179
|
+
(0, _buildCache().deserialize)(Buffer.from(_value)) : _value;
|
|
180
|
+
this.sharedReferences.set(ref, value);
|
|
181
|
+
this.sharedReferencesByValue.set(value, ref);
|
|
182
|
+
result = responseFromContent(null);
|
|
183
|
+
} else if (method === 'deleteSharedReference') {
|
|
184
|
+
let ref = args[0];
|
|
185
|
+
let value = this.sharedReferences.get(ref);
|
|
186
|
+
this.sharedReferencesByValue.delete(value);
|
|
187
|
+
this.sharedReferences.delete(ref);
|
|
188
|
+
result = responseFromContent(null);
|
|
189
|
+
} else {
|
|
190
|
+
try {
|
|
191
|
+
result = responseFromContent(
|
|
192
|
+
// $FlowFixMe
|
|
193
|
+
await this.module[method](this.workerApi, ...args));
|
|
194
|
+
} catch (e) {
|
|
195
|
+
result = errorResponseFromError(e);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
try {
|
|
199
|
+
this.send(result);
|
|
200
|
+
} catch (e) {
|
|
201
|
+
result = this.send(errorResponseFromError(e));
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
handleResponse(data) {
|
|
205
|
+
let idx = (0, _nullthrows().default)(data.idx);
|
|
206
|
+
let contentType = data.contentType;
|
|
207
|
+
let content = data.content;
|
|
208
|
+
let call = (0, _nullthrows().default)(this.responseQueue.get(idx));
|
|
209
|
+
if (contentType === 'error') {
|
|
210
|
+
(0, _assert().default)(typeof content !== 'string');
|
|
211
|
+
call.reject(new (_diagnostic().default)({
|
|
212
|
+
diagnostic: content
|
|
213
|
+
}));
|
|
214
|
+
} else {
|
|
215
|
+
call.resolve(content);
|
|
216
|
+
}
|
|
217
|
+
this.responseQueue.delete(idx);
|
|
218
|
+
|
|
219
|
+
// Process the next call
|
|
220
|
+
this.processQueue();
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Keep in mind to make sure responses to these calls are JSON.Stringify safe
|
|
224
|
+
addCall(request, awaitResponse = true) {
|
|
225
|
+
// $FlowFixMe
|
|
226
|
+
let call = {
|
|
227
|
+
...request,
|
|
228
|
+
type: 'request',
|
|
229
|
+
child: this.childId,
|
|
230
|
+
// $FlowFixMe Added in Flow 0.121.0 upgrade in #4381
|
|
231
|
+
awaitResponse,
|
|
232
|
+
resolve: () => {},
|
|
233
|
+
reject: () => {}
|
|
234
|
+
};
|
|
235
|
+
let promise;
|
|
236
|
+
if (awaitResponse) {
|
|
237
|
+
promise = new Promise((resolve, reject) => {
|
|
238
|
+
call.resolve = resolve;
|
|
239
|
+
call.reject = reject;
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
this.callQueue.push(call);
|
|
243
|
+
this.processQueue();
|
|
244
|
+
return promise ?? Promise.resolve();
|
|
245
|
+
}
|
|
246
|
+
sendRequest(call) {
|
|
247
|
+
let idx;
|
|
248
|
+
if (call.awaitResponse) {
|
|
249
|
+
idx = this.responseId++;
|
|
250
|
+
this.responseQueue.set(idx, call);
|
|
251
|
+
}
|
|
252
|
+
this.send({
|
|
253
|
+
idx,
|
|
254
|
+
child: call.child,
|
|
255
|
+
type: call.type,
|
|
256
|
+
location: call.location,
|
|
257
|
+
handle: call.handle,
|
|
258
|
+
method: call.method,
|
|
259
|
+
args: call.args,
|
|
260
|
+
awaitResponse: call.awaitResponse
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
processQueue() {
|
|
264
|
+
if (!this.callQueue.length) {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
if (this.responseQueue.size < this.maxConcurrentCalls) {
|
|
268
|
+
this.sendRequest(this.callQueue.shift());
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
handleEnd() {
|
|
272
|
+
this.loggerDisposable.dispose();
|
|
273
|
+
this.tracerDisposable.dispose();
|
|
274
|
+
}
|
|
275
|
+
createReverseHandle(fn) {
|
|
276
|
+
let handle = new Handle({
|
|
277
|
+
fn,
|
|
278
|
+
childId: this.childId
|
|
279
|
+
});
|
|
280
|
+
this.handles.set(handle.id, handle);
|
|
281
|
+
return handle;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
exports.Child = Child;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.child = void 0;
|
|
7
|
+
exports.setChild = setChild;
|
|
8
|
+
// This file is imported by both the WorkerFarm and child implementation.
|
|
9
|
+
// When a worker is inited, it sets the state in this file.
|
|
10
|
+
// This way, WorkerFarm can access the state without directly importing the child code.
|
|
11
|
+
let child = exports.child = null;
|
|
12
|
+
function setChild(c) {
|
|
13
|
+
exports.child = child = c;
|
|
14
|
+
}
|
package/lib/cpuCount.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = getCores;
|
|
7
|
+
exports.detectRealCores = detectRealCores;
|
|
8
|
+
function _os() {
|
|
9
|
+
const data = _interopRequireDefault(require("os"));
|
|
10
|
+
_os = function () {
|
|
11
|
+
return data;
|
|
12
|
+
};
|
|
13
|
+
return data;
|
|
14
|
+
}
|
|
15
|
+
function _child_process() {
|
|
16
|
+
const data = require("child_process");
|
|
17
|
+
_child_process = function () {
|
|
18
|
+
return data;
|
|
19
|
+
};
|
|
20
|
+
return data;
|
|
21
|
+
}
|
|
22
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
23
|
+
const exec = command => {
|
|
24
|
+
try {
|
|
25
|
+
let stdout = (0, _child_process().execSync)(command, {
|
|
26
|
+
encoding: 'utf8',
|
|
27
|
+
// This prevents the command from outputting to the console
|
|
28
|
+
stdio: [null, null, null]
|
|
29
|
+
});
|
|
30
|
+
return stdout.trim();
|
|
31
|
+
} catch (e) {
|
|
32
|
+
return '';
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
function detectRealCores() {
|
|
36
|
+
let platform = _os().default.platform();
|
|
37
|
+
let amount = 0;
|
|
38
|
+
if (platform === 'linux') {
|
|
39
|
+
amount = parseInt(exec('lscpu -p | egrep -v "^#" | sort -u -t, -k 2,4 | wc -l'), 10);
|
|
40
|
+
} else if (platform === 'darwin') {
|
|
41
|
+
amount = parseInt(exec('sysctl -n hw.physicalcpu_max'), 10);
|
|
42
|
+
} else if (platform === 'win32') {
|
|
43
|
+
const str = exec('wmic cpu get NumberOfCores').match(/\d+/g);
|
|
44
|
+
if (str !== null) {
|
|
45
|
+
amount = parseInt(str.filter(n => n !== '')[0], 10);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (!amount || amount <= 0) {
|
|
49
|
+
throw new Error('Could not detect cpu count!');
|
|
50
|
+
}
|
|
51
|
+
return amount;
|
|
52
|
+
}
|
|
53
|
+
let cores;
|
|
54
|
+
function getCores(bypassCache = false) {
|
|
55
|
+
// Do not re-run commands if we already have the count...
|
|
56
|
+
if (cores && !bypassCache) {
|
|
57
|
+
return cores;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// $FlowFixMe
|
|
61
|
+
if (process.browser) {
|
|
62
|
+
// eslint-disable-next-line no-undef
|
|
63
|
+
cores = navigator.hardwareConcurrency / 2;
|
|
64
|
+
}
|
|
65
|
+
if (!cores) {
|
|
66
|
+
try {
|
|
67
|
+
cores = detectRealCores();
|
|
68
|
+
} catch (e) {
|
|
69
|
+
// Guess the amount of real cores
|
|
70
|
+
cores = _os().default.cpus().filter((cpu, index) => !cpu.model.includes('Intel') || index % 2 === 1).length;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Another fallback
|
|
75
|
+
if (!cores) {
|
|
76
|
+
cores = 1;
|
|
77
|
+
}
|
|
78
|
+
return cores;
|
|
79
|
+
}
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "Handle", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _WorkerFarm.Handle;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(exports, "bus", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () {
|
|
15
|
+
return _bus.default;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
exports.default = void 0;
|
|
19
|
+
function _assert() {
|
|
20
|
+
const data = _interopRequireDefault(require("assert"));
|
|
21
|
+
_assert = function () {
|
|
22
|
+
return data;
|
|
23
|
+
};
|
|
24
|
+
return data;
|
|
25
|
+
}
|
|
26
|
+
var _WorkerFarm = _interopRequireWildcard(require("./WorkerFarm"));
|
|
27
|
+
function _logger() {
|
|
28
|
+
const data = _interopRequireDefault(require("@atlaspack/logger"));
|
|
29
|
+
_logger = function () {
|
|
30
|
+
return data;
|
|
31
|
+
};
|
|
32
|
+
return data;
|
|
33
|
+
}
|
|
34
|
+
var _bus = _interopRequireDefault(require("./bus"));
|
|
35
|
+
function _profiler() {
|
|
36
|
+
const data = require("@atlaspack/profiler");
|
|
37
|
+
_profiler = function () {
|
|
38
|
+
return data;
|
|
39
|
+
};
|
|
40
|
+
return data;
|
|
41
|
+
}
|
|
42
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
43
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
44
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
45
|
+
if (!_WorkerFarm.default.isWorker()) {
|
|
46
|
+
// Forward all logger events originating from workers into the main process
|
|
47
|
+
_bus.default.on('logEvent', e => {
|
|
48
|
+
switch (e.level) {
|
|
49
|
+
case 'info':
|
|
50
|
+
_logger().default.info(e.diagnostics);
|
|
51
|
+
break;
|
|
52
|
+
case 'progress':
|
|
53
|
+
(0, _assert().default)(typeof e.message === 'string');
|
|
54
|
+
_logger().default.progress(e.message);
|
|
55
|
+
break;
|
|
56
|
+
case 'verbose':
|
|
57
|
+
_logger().default.verbose(e.diagnostics);
|
|
58
|
+
break;
|
|
59
|
+
case 'warn':
|
|
60
|
+
_logger().default.warn(e.diagnostics);
|
|
61
|
+
break;
|
|
62
|
+
case 'error':
|
|
63
|
+
_logger().default.error(e.diagnostics);
|
|
64
|
+
break;
|
|
65
|
+
default:
|
|
66
|
+
throw new Error('Unknown log level');
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// Forward all trace events originating from workers into the main process
|
|
71
|
+
_bus.default.on('traceEvent', e => {
|
|
72
|
+
_profiler().tracer.trace(e);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
var _default = exports.default = _WorkerFarm.default;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
function _buildCache() {
|
|
8
|
+
const data = require("@atlaspack/build-cache");
|
|
9
|
+
_buildCache = function () {
|
|
10
|
+
return data;
|
|
11
|
+
};
|
|
12
|
+
return data;
|
|
13
|
+
}
|
|
14
|
+
function _nullthrows() {
|
|
15
|
+
const data = _interopRequireDefault(require("nullthrows"));
|
|
16
|
+
_nullthrows = function () {
|
|
17
|
+
return data;
|
|
18
|
+
};
|
|
19
|
+
return data;
|
|
20
|
+
}
|
|
21
|
+
var _child = require("../child");
|
|
22
|
+
var _childState = require("../childState");
|
|
23
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
24
|
+
class ProcessChild {
|
|
25
|
+
constructor(onMessage, onExit) {
|
|
26
|
+
if (!process.send) {
|
|
27
|
+
throw new Error('Only create ProcessChild instances in a worker!');
|
|
28
|
+
}
|
|
29
|
+
this.onMessage = onMessage;
|
|
30
|
+
this.onExit = onExit;
|
|
31
|
+
process.on('message', data => this.handleMessage(data));
|
|
32
|
+
}
|
|
33
|
+
handleMessage(data) {
|
|
34
|
+
if (data === 'die') {
|
|
35
|
+
return this.stop();
|
|
36
|
+
}
|
|
37
|
+
this.onMessage((0, _buildCache().deserialize)(Buffer.from(data, 'base64')));
|
|
38
|
+
}
|
|
39
|
+
send(data) {
|
|
40
|
+
let processSend = (0, _nullthrows().default)(process.send).bind(process);
|
|
41
|
+
processSend((0, _buildCache().serialize)(data).toString('base64'), err => {
|
|
42
|
+
if (err && err instanceof Error) {
|
|
43
|
+
// $FlowFixMe[prop-missing]
|
|
44
|
+
if (err.code === 'ERR_IPC_CHANNEL_CLOSED') {
|
|
45
|
+
// IPC connection closed
|
|
46
|
+
// no need to keep the worker running if it can't send or receive data
|
|
47
|
+
return this.stop();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
stop() {
|
|
53
|
+
this.onExit(0);
|
|
54
|
+
process.exit();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
exports.default = ProcessChild;
|
|
58
|
+
(0, _childState.setChild)(new _child.Child(ProcessChild));
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
function _child_process() {
|
|
8
|
+
const data = _interopRequireDefault(require("child_process"));
|
|
9
|
+
_child_process = function () {
|
|
10
|
+
return data;
|
|
11
|
+
};
|
|
12
|
+
return data;
|
|
13
|
+
}
|
|
14
|
+
function _path() {
|
|
15
|
+
const data = _interopRequireDefault(require("path"));
|
|
16
|
+
_path = function () {
|
|
17
|
+
return data;
|
|
18
|
+
};
|
|
19
|
+
return data;
|
|
20
|
+
}
|
|
21
|
+
function _buildCache() {
|
|
22
|
+
const data = require("@atlaspack/build-cache");
|
|
23
|
+
_buildCache = function () {
|
|
24
|
+
return data;
|
|
25
|
+
};
|
|
26
|
+
return data;
|
|
27
|
+
}
|
|
28
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
29
|
+
const WORKER_PATH = _path().default.join(__dirname, './ProcessChild.js');
|
|
30
|
+
class ProcessWorker {
|
|
31
|
+
processQueue = true;
|
|
32
|
+
sendQueue = [];
|
|
33
|
+
constructor(execArgv, onMessage, onError, onExit) {
|
|
34
|
+
this.execArgv = execArgv;
|
|
35
|
+
this.onMessage = onMessage;
|
|
36
|
+
this.onError = onError;
|
|
37
|
+
this.onExit = onExit;
|
|
38
|
+
}
|
|
39
|
+
start() {
|
|
40
|
+
this.child = _child_process().default.fork(WORKER_PATH, process.argv, {
|
|
41
|
+
execArgv: this.execArgv,
|
|
42
|
+
env: process.env,
|
|
43
|
+
cwd: process.cwd()
|
|
44
|
+
});
|
|
45
|
+
this.child.on('message', data => {
|
|
46
|
+
this.onMessage((0, _buildCache().deserialize)(Buffer.from(data, 'base64')));
|
|
47
|
+
});
|
|
48
|
+
this.child.once('exit', this.onExit);
|
|
49
|
+
this.child.on('error', this.onError);
|
|
50
|
+
return Promise.resolve();
|
|
51
|
+
}
|
|
52
|
+
async stop() {
|
|
53
|
+
this.child.send('die');
|
|
54
|
+
let forceKill = setTimeout(() => this.child.kill('SIGINT'), 500);
|
|
55
|
+
await new Promise(resolve => {
|
|
56
|
+
this.child.once('exit', resolve);
|
|
57
|
+
});
|
|
58
|
+
clearTimeout(forceKill);
|
|
59
|
+
}
|
|
60
|
+
send(data) {
|
|
61
|
+
if (!this.processQueue) {
|
|
62
|
+
this.sendQueue.push(data);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
let result = this.child.send((0, _buildCache().serialize)(data).toString('base64'), error => {
|
|
66
|
+
if (error && error instanceof Error) {
|
|
67
|
+
// Ignore this, the workerfarm handles child errors
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
this.processQueue = true;
|
|
71
|
+
if (this.sendQueue.length > 0) {
|
|
72
|
+
let queueCopy = this.sendQueue.slice(0);
|
|
73
|
+
this.sendQueue = [];
|
|
74
|
+
queueCopy.forEach(entry => this.send(entry));
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
if (!result || /^win/.test(process.platform)) {
|
|
78
|
+
// Queue is handling too much messages throttle it
|
|
79
|
+
this.processQueue = false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
exports.default = ProcessWorker;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
function _worker_threads() {
|
|
8
|
+
const data = require("worker_threads");
|
|
9
|
+
_worker_threads = function () {
|
|
10
|
+
return data;
|
|
11
|
+
};
|
|
12
|
+
return data;
|
|
13
|
+
}
|
|
14
|
+
function _buildCache() {
|
|
15
|
+
const data = require("@atlaspack/build-cache");
|
|
16
|
+
_buildCache = function () {
|
|
17
|
+
return data;
|
|
18
|
+
};
|
|
19
|
+
return data;
|
|
20
|
+
}
|
|
21
|
+
function _nullthrows() {
|
|
22
|
+
const data = _interopRequireDefault(require("nullthrows"));
|
|
23
|
+
_nullthrows = function () {
|
|
24
|
+
return data;
|
|
25
|
+
};
|
|
26
|
+
return data;
|
|
27
|
+
}
|
|
28
|
+
var _child = require("../child");
|
|
29
|
+
var _childState = require("../childState");
|
|
30
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
31
|
+
class ThreadsChild {
|
|
32
|
+
constructor(onMessage, onExit) {
|
|
33
|
+
if (_worker_threads().isMainThread || !_worker_threads().parentPort) {
|
|
34
|
+
throw new Error('Only create ThreadsChild instances in a worker!');
|
|
35
|
+
}
|
|
36
|
+
this.onMessage = onMessage;
|
|
37
|
+
this.onExit = onExit;
|
|
38
|
+
_worker_threads().parentPort.on('message', data => this.handleMessage(data));
|
|
39
|
+
_worker_threads().parentPort.on('close', this.onExit);
|
|
40
|
+
}
|
|
41
|
+
handleMessage(data) {
|
|
42
|
+
this.onMessage((0, _buildCache().restoreDeserializedObject)(data));
|
|
43
|
+
}
|
|
44
|
+
send(data) {
|
|
45
|
+
(0, _nullthrows().default)(_worker_threads().parentPort).postMessage((0, _buildCache().prepareForSerialization)(data));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
exports.default = ThreadsChild;
|
|
49
|
+
(0, _childState.setChild)(new _child.Child(ThreadsChild));
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
function _worker_threads() {
|
|
8
|
+
const data = require("worker_threads");
|
|
9
|
+
_worker_threads = function () {
|
|
10
|
+
return data;
|
|
11
|
+
};
|
|
12
|
+
return data;
|
|
13
|
+
}
|
|
14
|
+
function _path() {
|
|
15
|
+
const data = _interopRequireDefault(require("path"));
|
|
16
|
+
_path = function () {
|
|
17
|
+
return data;
|
|
18
|
+
};
|
|
19
|
+
return data;
|
|
20
|
+
}
|
|
21
|
+
function _buildCache() {
|
|
22
|
+
const data = require("@atlaspack/build-cache");
|
|
23
|
+
_buildCache = function () {
|
|
24
|
+
return data;
|
|
25
|
+
};
|
|
26
|
+
return data;
|
|
27
|
+
}
|
|
28
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
29
|
+
const WORKER_PATH = _path().default.join(__dirname, './ThreadsChild.js');
|
|
30
|
+
class ThreadsWorker {
|
|
31
|
+
constructor(execArgv, onMessage, onError, onExit) {
|
|
32
|
+
this.execArgv = execArgv;
|
|
33
|
+
this.onMessage = onMessage;
|
|
34
|
+
this.onError = onError;
|
|
35
|
+
this.onExit = onExit;
|
|
36
|
+
}
|
|
37
|
+
start() {
|
|
38
|
+
this.worker = new (_worker_threads().Worker)(WORKER_PATH, {
|
|
39
|
+
execArgv: this.execArgv,
|
|
40
|
+
env: process.env
|
|
41
|
+
});
|
|
42
|
+
this.worker.on('message', data => this.handleMessage(data));
|
|
43
|
+
this.worker.on('error', this.onError);
|
|
44
|
+
this.worker.on('exit', this.onExit);
|
|
45
|
+
return new Promise(resolve => {
|
|
46
|
+
this.worker.on('online', resolve);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
stop() {
|
|
50
|
+
// In node 12, this returns a promise, but previously it accepted a callback
|
|
51
|
+
// TODO: Pass a callback in earlier versions of Node
|
|
52
|
+
return Promise.resolve(this.worker.terminate());
|
|
53
|
+
}
|
|
54
|
+
handleMessage(data) {
|
|
55
|
+
this.onMessage((0, _buildCache().restoreDeserializedObject)(data));
|
|
56
|
+
}
|
|
57
|
+
send(data) {
|
|
58
|
+
this.worker.postMessage((0, _buildCache().prepareForSerialization)(data));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
exports.default = ThreadsWorker;
|