nx 21.0.0-beta.2 → 21.0.0-beta.3
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/package.json +11 -11
- package/src/config/nx-json.d.ts +1 -1
- package/src/core/graph/main.js +1 -1
- package/src/executors/run-script/run-script.impl.js +1 -0
- package/src/native/index.js +16 -2
- package/src/native/nx.wasm32-wasi.wasm +0 -0
- package/src/plugins/package-json/create-nodes.d.ts +1 -1
- package/src/tasks-runner/forked-process-task-runner.d.ts +2 -0
- package/src/tasks-runner/forked-process-task-runner.js +28 -19
- package/src/tasks-runner/task-orchestrator.js +1 -0
@@ -40,6 +40,7 @@ function nodeProcess(command, cwd, env) {
|
|
40
40
|
}
|
41
41
|
async function ptyProcess(command, cwd, env) {
|
42
42
|
const terminal = (0, pseudo_terminal_1.createPseudoTerminal)();
|
43
|
+
await terminal.init();
|
43
44
|
return new Promise((res, rej) => {
|
44
45
|
const cp = terminal.runCommand(command, { cwd, jsEnv: env });
|
45
46
|
cp.onExit((code) => {
|
package/src/native/index.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
const { join, basename } = require('path');
|
2
|
-
const { copyFileSync, existsSync, mkdirSync } = require('fs');
|
2
|
+
const { copyFileSync, existsSync, mkdirSync, renameSync } = require('fs');
|
3
3
|
const Module = require('module');
|
4
4
|
const { nxVersion } = require('../utils/versions');
|
5
5
|
const { getNativeFileCacheLocation } = require('./native-file-cache-location');
|
@@ -71,14 +71,28 @@ Module._load = function (request, parent, isMain) {
|
|
71
71
|
|
72
72
|
// we copy the file to a workspace-scoped tmp directory and prefix with nxVersion to avoid stale files being loaded
|
73
73
|
const nativeFileCacheLocation = getNativeFileCacheLocation();
|
74
|
+
// This is a path to copy to, not the one that gets loaded
|
75
|
+
const tmpTmpFile = join(
|
76
|
+
nativeFileCacheLocation,
|
77
|
+
nxVersion + '-' + Math.random() + fileName
|
78
|
+
);
|
79
|
+
// This is the path that will get loaded
|
74
80
|
const tmpFile = join(nativeFileCacheLocation, nxVersion + '-' + fileName);
|
81
|
+
|
82
|
+
// If the file to be loaded already exists, just load it
|
75
83
|
if (existsSync(tmpFile)) {
|
76
84
|
return originalLoad.apply(this, [tmpFile, parent, isMain]);
|
77
85
|
}
|
78
86
|
if (!existsSync(nativeFileCacheLocation)) {
|
79
87
|
mkdirSync(nativeFileCacheLocation, { recursive: true });
|
80
88
|
}
|
81
|
-
|
89
|
+
// First copy to a unique location for each process
|
90
|
+
copyFileSync(nativeLocation, tmpTmpFile);
|
91
|
+
|
92
|
+
// Then rename to the final location
|
93
|
+
renameSync(tmpTmpFile, tmpFile);
|
94
|
+
|
95
|
+
// Load from the final location
|
82
96
|
return originalLoad.apply(this, [tmpFile, parent, isMain]);
|
83
97
|
} else {
|
84
98
|
// call the original _load function for everything else
|
Binary file
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { NxJsonConfiguration } from '../../config/nx-json';
|
2
|
-
import { ProjectConfiguration } from '../../config/workspace-json-project-json';
|
2
|
+
import type { ProjectConfiguration } from '../../config/workspace-json-project-json';
|
3
3
|
import { PackageJson } from '../../utils/package-json';
|
4
4
|
import { CreateNodesV2 } from '../../project-graph/plugins';
|
5
5
|
import { PackageJsonConfigurationCache } from '../../../plugins/package-json';
|
@@ -11,10 +11,12 @@ export declare class ForkedProcessTaskRunner {
|
|
11
11
|
cliPath: string;
|
12
12
|
private readonly verbose;
|
13
13
|
private processes;
|
14
|
+
private finishedProcesses;
|
14
15
|
private pseudoTerminals;
|
15
16
|
constructor(options: DefaultTasksRunnerOptions, tuiEnabled: boolean);
|
16
17
|
init(): Promise<void>;
|
17
18
|
forkProcessForBatch({ executorName, taskGraph: batchTaskGraph }: Batch, projectGraph: ProjectGraph, fullTaskGraph: TaskGraph, env: NodeJS.ProcessEnv): Promise<BatchProcess>;
|
19
|
+
cleanUpBatchProcesses(): void;
|
18
20
|
forkProcessLegacy(task: Task, { temporaryOutputPath, streamOutput, pipeOutput, taskGraph, env, }: {
|
19
21
|
temporaryOutputPath: string;
|
20
22
|
streamOutput: boolean;
|
@@ -22,6 +22,7 @@ class ForkedProcessTaskRunner {
|
|
22
22
|
this.cliPath = (0, utils_1.getCliPath)();
|
23
23
|
this.verbose = process.env.NX_VERBOSE_LOGGING === 'true';
|
24
24
|
this.processes = new Set();
|
25
|
+
this.finishedProcesses = new Set();
|
25
26
|
this.pseudoTerminals = new Set();
|
26
27
|
}
|
27
28
|
async init() {
|
@@ -56,6 +57,14 @@ class ForkedProcessTaskRunner {
|
|
56
57
|
});
|
57
58
|
return cp;
|
58
59
|
}
|
60
|
+
cleanUpBatchProcesses() {
|
61
|
+
if (this.finishedProcesses.size > 0) {
|
62
|
+
this.finishedProcesses.forEach((p) => {
|
63
|
+
p.kill();
|
64
|
+
});
|
65
|
+
this.finishedProcesses.clear();
|
66
|
+
}
|
67
|
+
}
|
59
68
|
async forkProcessLegacy(task, { temporaryOutputPath, streamOutput, pipeOutput, taskGraph, env, }) {
|
60
69
|
return pipeOutput
|
61
70
|
? this.forkProcessWithPrefixAndNotTTY(task, {
|
@@ -221,41 +230,41 @@ class ForkedProcessTaskRunner {
|
|
221
230
|
(0, fs_1.writeFileSync)(outputPath, content);
|
222
231
|
}
|
223
232
|
setupProcessEventListeners() {
|
224
|
-
|
225
|
-
process.on('message', (message) => {
|
233
|
+
const messageHandler = (message) => {
|
226
234
|
this.pseudoTerminals.forEach((p) => {
|
227
235
|
p.sendMessageToChildren(message);
|
228
236
|
});
|
229
237
|
this.processes.forEach((p) => {
|
230
|
-
if ('send' in p) {
|
238
|
+
if ('connected' in p && p.connected && 'send' in p) {
|
231
239
|
p.send(message);
|
232
240
|
}
|
233
241
|
});
|
234
|
-
}
|
235
|
-
//
|
236
|
-
process.on('
|
242
|
+
};
|
243
|
+
// When the nx process gets a message, it will be sent into the task's process
|
244
|
+
process.on('message', messageHandler);
|
245
|
+
const cleanUp = (signal) => {
|
237
246
|
this.processes.forEach((p) => {
|
238
|
-
p.kill();
|
247
|
+
p.kill(signal);
|
239
248
|
});
|
249
|
+
process.off('message', messageHandler);
|
250
|
+
this.cleanUpBatchProcesses();
|
251
|
+
};
|
252
|
+
// Terminate any task processes on exit
|
253
|
+
process.once('exit', () => {
|
254
|
+
cleanUp();
|
240
255
|
});
|
241
|
-
process.
|
242
|
-
|
243
|
-
p.kill('SIGTERM');
|
244
|
-
});
|
256
|
+
process.once('SIGINT', () => {
|
257
|
+
cleanUp('SIGTERM');
|
245
258
|
// we exit here because we don't need to write anything to cache.
|
246
259
|
process.exit((0, exit_codes_1.signalToCode)('SIGINT'));
|
247
260
|
});
|
248
|
-
process.
|
249
|
-
|
250
|
-
p.kill('SIGTERM');
|
251
|
-
});
|
261
|
+
process.once('SIGTERM', () => {
|
262
|
+
cleanUp('SIGTERM');
|
252
263
|
// no exit here because we expect child processes to terminate which
|
253
264
|
// will store results to the cache and will terminate this process
|
254
265
|
});
|
255
|
-
process.
|
256
|
-
|
257
|
-
p.kill('SIGTERM');
|
258
|
-
});
|
266
|
+
process.once('SIGHUP', () => {
|
267
|
+
cleanUp('SIGTERM');
|
259
268
|
// no exit here because we expect child processes to terminate which
|
260
269
|
// will store results to the cache and will terminate this process
|
261
270
|
});
|
@@ -201,6 +201,7 @@ class TaskOrchestrator {
|
|
201
201
|
results.push(...batchResults);
|
202
202
|
}
|
203
203
|
await this.postRunSteps(tasks, results, doNotSkipCache, { groupId });
|
204
|
+
this.forkedProcessTaskRunner.cleanUpBatchProcesses();
|
204
205
|
const tasksCompleted = taskEntries.filter(([taskId]) => this.completedTasks[taskId]);
|
205
206
|
// Batch is still not done, run it again
|
206
207
|
if (tasksCompleted.length !== taskEntries.length) {
|