nx 20.1.1 → 20.1.3
Sign up to get free protection for your applications and to get access to all the features.
- package/package.json +11 -11
- package/release/changelog-renderer/index.js +1 -1
- package/src/core/graph/main.js +1 -1
- package/src/daemon/client/client.js +3 -0
- package/src/daemon/server/server.js +9 -0
- package/src/daemon/tmp-dir.js +1 -1
- package/src/native/nx.wasm32-wasi.wasm +0 -0
- package/src/project-graph/plugins/isolation/plugin-pool.js +15 -11
- package/src/project-graph/plugins/isolation/plugin-worker.js +20 -2
@@ -406,6 +406,9 @@ class DaemonClient {
|
|
406
406
|
}
|
407
407
|
}
|
408
408
|
async startInBackground() {
|
409
|
+
if (global.NX_PLUGIN_WORKER) {
|
410
|
+
throw new Error('Fatal Error: Something unexpected has occurred. Plugin Workers should not start a new daemon process. Please report this issue.');
|
411
|
+
}
|
409
412
|
(0, node_fs_1.mkdirSync)(tmp_dir_1.DAEMON_DIR_FOR_CURRENT_WORKSPACE, { recursive: true });
|
410
413
|
if (!(0, node_fs_1.existsSync)(tmp_dir_1.DAEMON_OUTPUT_LOG_FILE)) {
|
411
414
|
(0, node_fs_1.writeFileSync)(tmp_dir_1.DAEMON_OUTPUT_LOG_FILE, '');
|
@@ -353,6 +353,15 @@ async function startServer() {
|
|
353
353
|
server.listen((0, socket_utils_1.getFullOsSocketPath)(), async () => {
|
354
354
|
try {
|
355
355
|
logger_1.serverLogger.log(`Started listening on: ${(0, socket_utils_1.getFullOsSocketPath)()}`);
|
356
|
+
setInterval(() => {
|
357
|
+
if ((0, cache_1.getDaemonProcessIdSync)() !== process.pid) {
|
358
|
+
return (0, shutdown_utils_1.handleServerProcessTermination)({
|
359
|
+
server,
|
360
|
+
reason: 'this process is no longer the current daemon (native)',
|
361
|
+
sockets: exports.openSockets,
|
362
|
+
});
|
363
|
+
}
|
364
|
+
}).unref();
|
356
365
|
// this triggers the storage of the lock file hash
|
357
366
|
daemonIsOutdated();
|
358
367
|
if (!(0, shutdown_utils_1.getWatcherInstance)()) {
|
package/src/daemon/tmp-dir.js
CHANGED
@@ -43,7 +43,7 @@ function isDaemonDisabled() {
|
|
43
43
|
function socketDirName() {
|
44
44
|
const hasher = (0, crypto_1.createHash)('sha256');
|
45
45
|
hasher.update(workspace_root_1.workspaceRoot.toLowerCase());
|
46
|
-
const unique = hasher.digest('hex').substring(0,
|
46
|
+
const unique = hasher.digest('hex').substring(0, 20);
|
47
47
|
return (0, path_1.join)(tmp_1.tmpdir, unique);
|
48
48
|
}
|
49
49
|
/**
|
Binary file
|
@@ -12,7 +12,15 @@ const pluginNames = new Map();
|
|
12
12
|
const PLUGIN_TIMEOUT_HINT_TEXT = 'As a last resort, you can set NX_PLUGIN_NO_TIMEOUTS=true to bypass this timeout.';
|
13
13
|
const MINUTES = 10;
|
14
14
|
const MAX_MESSAGE_WAIT = process.env.NX_PLUGIN_NO_TIMEOUTS === 'true'
|
15
|
-
?
|
15
|
+
? // Registering a timeout prevents the process from exiting
|
16
|
+
// if the call to a plugin happens to be the only thing
|
17
|
+
// keeping the process alive. As such, even if timeouts are disabled
|
18
|
+
// we need to register one. 2147483647 is the max timeout
|
19
|
+
// that Node.js allows, and is equivalent to 24.8 days....
|
20
|
+
// This does mean that the NX_PLUGIN_NO_TIMEOUTS env var
|
21
|
+
// would still timeout after 24.8 days, but that seems
|
22
|
+
// like a reasonable compromise.
|
23
|
+
2147483647
|
16
24
|
: 1000 * 60 * MINUTES; // 10 minutes
|
17
25
|
const nxPluginWorkerCache = (global['nxPluginWorkerCache'] ??= new Map());
|
18
26
|
async function loadRemoteNxPlugin(plugin, root) {
|
@@ -35,11 +43,9 @@ async function loadRemoteNxPlugin(plugin, root) {
|
|
35
43
|
payload: { plugin, root },
|
36
44
|
});
|
37
45
|
// logger.verbose(`[plugin-worker] started worker: ${worker.pid}`);
|
38
|
-
const loadTimeout =
|
39
|
-
|
40
|
-
|
41
|
-
}, MAX_MESSAGE_WAIT)
|
42
|
-
: undefined;
|
46
|
+
const loadTimeout = setTimeout(() => {
|
47
|
+
rej(new Error(`Loading "${typeof plugin === 'string' ? plugin : plugin.plugin}" timed out after ${MINUTES} minutes. ${PLUGIN_TIMEOUT_HINT_TEXT}`));
|
48
|
+
}, MAX_MESSAGE_WAIT);
|
43
49
|
socket.on('data', (0, consume_messages_from_socket_1.consumeMessagesFromSocket)(createWorkerHandler(worker, pendingPromises, (val) => {
|
44
50
|
if (loadTimeout)
|
45
51
|
clearTimeout(loadTimeout);
|
@@ -169,11 +175,9 @@ function registerPendingPromise(tx, pending, callback, context) {
|
|
169
175
|
const promise = new Promise((res, rej) => {
|
170
176
|
rejector = rej;
|
171
177
|
resolver = res;
|
172
|
-
timeout =
|
173
|
-
|
174
|
-
|
175
|
-
}, MAX_MESSAGE_WAIT)
|
176
|
-
: undefined;
|
178
|
+
timeout = setTimeout(() => {
|
179
|
+
rej(new Error(`${context.plugin} timed out after ${MINUTES} minutes during ${context.operation}. ${PLUGIN_TIMEOUT_HINT_TEXT}`));
|
180
|
+
}, MAX_MESSAGE_WAIT);
|
177
181
|
callback();
|
178
182
|
}).finally(() => {
|
179
183
|
pending.delete(tx);
|
@@ -10,9 +10,19 @@ if (process.env.NX_PERF_LOGGING === 'true') {
|
|
10
10
|
require('../../../utils/perf-logging');
|
11
11
|
}
|
12
12
|
global.NX_GRAPH_CREATION = true;
|
13
|
+
global.NX_PLUGIN_WORKER = true;
|
14
|
+
let connected = false;
|
13
15
|
let plugin;
|
14
16
|
const socketPath = process.argv[2];
|
15
17
|
const server = (0, net_1.createServer)((socket) => {
|
18
|
+
connected = true;
|
19
|
+
// This handles cases where the host process was killed
|
20
|
+
// after the worker connected but before the worker was
|
21
|
+
// instructed to load the plugin.
|
22
|
+
const loadTimeout = setTimeout(() => {
|
23
|
+
console.error(`Plugin Worker exited because no plugin was loaded within 10 seconds of starting up.`);
|
24
|
+
process.exit(1);
|
25
|
+
}, 10000).unref();
|
16
26
|
socket.on('data', (0, consume_messages_from_socket_1.consumeMessagesFromSocket)((raw) => {
|
17
27
|
const message = JSON.parse(raw.toString());
|
18
28
|
if (!(0, messaging_1.isPluginWorkerMessage)(message)) {
|
@@ -20,6 +30,8 @@ const server = (0, net_1.createServer)((socket) => {
|
|
20
30
|
}
|
21
31
|
return (0, messaging_1.consumeMessage)(socket, message, {
|
22
32
|
load: async ({ plugin: pluginConfiguration, root }) => {
|
33
|
+
if (loadTimeout)
|
34
|
+
clearTimeout(loadTimeout);
|
23
35
|
process.chdir(root);
|
24
36
|
try {
|
25
37
|
const [promise] = (0, loader_1.loadNxPlugin)(pluginConfiguration, root);
|
@@ -112,6 +124,8 @@ const server = (0, net_1.createServer)((socket) => {
|
|
112
124
|
// since the worker is spawned per host process. As such,
|
113
125
|
// we can safely close the worker when the host disconnects.
|
114
126
|
socket.on('end', () => {
|
127
|
+
// Destroys the socket once it's fully closed.
|
128
|
+
socket.destroySoon();
|
115
129
|
// Stops accepting new connections, but existing connections are
|
116
130
|
// not closed immediately.
|
117
131
|
server.close(() => {
|
@@ -121,11 +135,15 @@ const server = (0, net_1.createServer)((socket) => {
|
|
121
135
|
catch (e) { }
|
122
136
|
process.exit(0);
|
123
137
|
});
|
124
|
-
// Destroys the socket once it's fully closed.
|
125
|
-
socket.destroySoon();
|
126
138
|
});
|
127
139
|
});
|
128
140
|
server.listen(socketPath);
|
141
|
+
setTimeout(() => {
|
142
|
+
if (!connected) {
|
143
|
+
console.error('The plugin worker is exiting as it was not connected to within 5 seconds.');
|
144
|
+
process.exit(1);
|
145
|
+
}
|
146
|
+
}, 5000).unref();
|
129
147
|
const exitHandler = (exitCode) => () => {
|
130
148
|
server.close();
|
131
149
|
try {
|