nx 22.5.0-beta.2 → 22.5.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/README.md +3 -3
- package/package.json +13 -13
- package/src/command-line/nx-commands.js +1 -1
- package/src/command-line/release/changelog/version-plan-filtering.d.ts +6 -3
- package/src/command-line/release/changelog/version-plan-filtering.d.ts.map +1 -1
- package/src/command-line/release/changelog/version-plan-filtering.js +4 -3
- package/src/command-line/release/changelog.d.ts.map +1 -1
- package/src/command-line/release/changelog.js +11 -9
- package/src/command-line/release/utils/git.d.ts +3 -2
- package/src/command-line/release/utils/git.d.ts.map +1 -1
- package/src/command-line/release/utils/git.js +3 -69
- package/src/command-line/release/utils/release-graph.d.ts +10 -0
- package/src/command-line/release/utils/release-graph.d.ts.map +1 -1
- package/src/command-line/release/utils/release-graph.js +32 -1
- package/src/command-line/release/utils/repository-git-tags.d.ts +26 -0
- package/src/command-line/release/utils/repository-git-tags.d.ts.map +1 -0
- package/src/command-line/release/utils/repository-git-tags.js +125 -0
- package/src/command-line/release/utils/resolve-semver-specifier.d.ts +2 -1
- package/src/command-line/release/utils/resolve-semver-specifier.d.ts.map +1 -1
- package/src/command-line/release/utils/resolve-semver-specifier.js +2 -2
- package/src/command-line/release/utils/shared.d.ts +3 -2
- package/src/command-line/release/utils/shared.d.ts.map +1 -1
- package/src/command-line/release/utils/shared.js +4 -10
- package/src/command-line/release/version/derive-specifier-from-conventional-commits.d.ts +2 -1
- package/src/command-line/release/version/derive-specifier-from-conventional-commits.d.ts.map +1 -1
- package/src/command-line/release/version/derive-specifier-from-conventional-commits.js +2 -2
- package/src/command-line/release/version/release-group-processor.d.ts.map +1 -1
- package/src/command-line/release/version/release-group-processor.js +1 -1
- package/src/core/graph/main.js +1 -1
- package/src/daemon/client/client.js +4 -4
- package/src/native/nx.wasm32-wasi.wasm +0 -0
- package/src/project-graph/plugins/get-plugins.d.ts.map +1 -1
- package/src/project-graph/plugins/get-plugins.js +81 -11
- package/src/project-graph/plugins/isolation/plugin-pool.d.ts.map +1 -1
- package/src/project-graph/plugins/isolation/plugin-pool.js +78 -27
- package/src/project-graph/plugins/isolation/plugin-worker.js +33 -17
- package/src/project-graph/project-graph.js +1 -1
- package/src/utils/consume-messages-from-socket.d.ts.map +1 -1
- package/src/utils/consume-messages-from-socket.js +3 -1
- package/src/utils/promised-based-queue.d.ts +0 -7
- package/src/utils/promised-based-queue.d.ts.map +1 -1
- package/src/utils/promised-based-queue.js +0 -9
|
@@ -790,13 +790,13 @@ class DaemonClient {
|
|
|
790
790
|
this.establishConnection();
|
|
791
791
|
// Resend the pending message if one exists
|
|
792
792
|
if (this.currentMessage && this.currentResolve && this.currentReject) {
|
|
793
|
-
//
|
|
794
|
-
|
|
795
|
-
//
|
|
793
|
+
// Retry the message directly (not through the queue) to resolve the
|
|
794
|
+
// pending promise that the original queue entry is waiting on.
|
|
795
|
+
// This allows the original queue entry to complete naturally.
|
|
796
796
|
const msg = this.currentMessage;
|
|
797
797
|
const res = this.currentResolve;
|
|
798
798
|
const rej = this.currentReject;
|
|
799
|
-
this.
|
|
799
|
+
this.sendMessageToDaemon(msg).then(res, rej);
|
|
800
800
|
}
|
|
801
801
|
}
|
|
802
802
|
else {
|
|
Binary file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-plugins.d.ts","sourceRoot":"","sources":["../../../../../../packages/nx/src/project-graph/plugins/get-plugins.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAwBzD,wBAAsB,UAAU,CAC9B,IAAI,SAAgB,GACnB,OAAO,CAAC,cAAc,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"get-plugins.d.ts","sourceRoot":"","sources":["../../../../../../packages/nx/src/project-graph/plugins/get-plugins.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAwBzD,wBAAsB,UAAU,CAC9B,IAAI,SAAgB,GACnB,OAAO,CAAC,cAAc,EAAE,CAAC,CA6C3B;AAaD,wBAAsB,qBAAqB,CAAC,IAAI,SAAgB,6BAyB/D;AAED,wBAAgB,cAAc,SAK7B"}
|
|
@@ -31,10 +31,27 @@ async function getPlugins(root = workspace_root_1.workspaceRoot) {
|
|
|
31
31
|
return loadedPlugins;
|
|
32
32
|
}
|
|
33
33
|
currentPluginsConfigurationHash = pluginsConfigurationHash;
|
|
34
|
-
const
|
|
34
|
+
const results = await Promise.allSettled([
|
|
35
35
|
getOnlyDefaultPlugins(root),
|
|
36
36
|
(pendingPluginsPromise ??= loadSpecifiedNxPlugins(pluginsConfiguration, root)),
|
|
37
37
|
]);
|
|
38
|
+
const errors = [];
|
|
39
|
+
const defaultPlugins = [];
|
|
40
|
+
const specifiedPlugins = [];
|
|
41
|
+
for (let i = 0; i < results.length; i++) {
|
|
42
|
+
const result = results[i];
|
|
43
|
+
if (result.status === 'fulfilled') {
|
|
44
|
+
(i === 0 ? defaultPlugins : specifiedPlugins).push(...result.value);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
errors.push(result.reason instanceof Error
|
|
48
|
+
? result.reason
|
|
49
|
+
: new Error(String(result.reason)));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (errors.length > 0) {
|
|
53
|
+
throw new AggregateError(errors, errors.map((e) => e.message).join('\n'));
|
|
54
|
+
}
|
|
38
55
|
loadedPlugins = specifiedPlugins.concat(defaultPlugins);
|
|
39
56
|
return loadedPlugins;
|
|
40
57
|
}
|
|
@@ -79,16 +96,42 @@ async function loadDefaultNxPlugins(root = workspace_root_1.workspaceRoot) {
|
|
|
79
96
|
performance.mark('loadDefaultNxPlugins:start');
|
|
80
97
|
const plugins = getDefaultPlugins(root);
|
|
81
98
|
const cleanupFunctions = [];
|
|
99
|
+
const results = await Promise.allSettled(plugins.map(async (plugin) => {
|
|
100
|
+
performance.mark(`Load Nx Plugin: ${plugin} - start`);
|
|
101
|
+
const [loadedPluginPromise, cleanup] = await loadingMethod(plugin, root);
|
|
102
|
+
cleanupFunctions.push(cleanup);
|
|
103
|
+
const res = await loadedPluginPromise;
|
|
104
|
+
performance.mark(`Load Nx Plugin: ${plugin} - end`);
|
|
105
|
+
performance.measure(`Load Nx Plugin: ${plugin}`, `Load Nx Plugin: ${plugin} - start`, `Load Nx Plugin: ${plugin} - end`);
|
|
106
|
+
return res;
|
|
107
|
+
}));
|
|
108
|
+
const defaultPluginResults = [];
|
|
109
|
+
const errors = [];
|
|
110
|
+
for (let i = 0; i < results.length; i++) {
|
|
111
|
+
const result = results[i];
|
|
112
|
+
if (result.status === 'fulfilled') {
|
|
113
|
+
defaultPluginResults.push(result.value);
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
errors.push({
|
|
117
|
+
pluginName: plugins[i],
|
|
118
|
+
error: result.reason instanceof Error
|
|
119
|
+
? result.reason
|
|
120
|
+
: new Error(String(result.reason)),
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (errors.length > 0) {
|
|
125
|
+
for (const fn of cleanupFunctions) {
|
|
126
|
+
fn();
|
|
127
|
+
}
|
|
128
|
+
const errorMessage = errors
|
|
129
|
+
.map((e) => ` - ${e.pluginName}: ${e.error.message}`)
|
|
130
|
+
.join('\n');
|
|
131
|
+
throw new AggregateError(errors.map((e) => e.error), `Failed to load ${errors.length} default Nx plugin(s):\n${errorMessage}`);
|
|
132
|
+
}
|
|
82
133
|
const ret = [
|
|
83
|
-
|
|
84
|
-
performance.mark(`Load Nx Plugin: ${plugin} - start`);
|
|
85
|
-
const [loadedPluginPromise, cleanup] = await loadingMethod(plugin, root);
|
|
86
|
-
cleanupFunctions.push(cleanup);
|
|
87
|
-
const res = await loadedPluginPromise;
|
|
88
|
-
performance.mark(`Load Nx Plugin: ${plugin} - end`);
|
|
89
|
-
performance.measure(`Load Nx Plugin: ${plugin}`, `Load Nx Plugin: ${plugin} - start`, `Load Nx Plugin: ${plugin} - end`);
|
|
90
|
-
return res;
|
|
91
|
-
})),
|
|
134
|
+
defaultPluginResults,
|
|
92
135
|
() => {
|
|
93
136
|
for (const fn of cleanupFunctions) {
|
|
94
137
|
fn();
|
|
@@ -111,7 +154,7 @@ async function loadSpecifiedNxPlugins(pluginsConfigurations, root = workspace_ro
|
|
|
111
154
|
performance.mark('loadSpecifiedNxPlugins:start');
|
|
112
155
|
pluginsConfigurations ??= [];
|
|
113
156
|
const cleanupFunctions = [];
|
|
114
|
-
const
|
|
157
|
+
const results = await Promise.allSettled(pluginsConfigurations.map(async (plugin, index) => {
|
|
115
158
|
const pluginPath = typeof plugin === 'string' ? plugin : plugin.plugin;
|
|
116
159
|
performance.mark(`Load Nx Plugin: ${pluginPath} - start`);
|
|
117
160
|
const [loadedPluginPromise, cleanup] = await loadingMethod(plugin, root, index);
|
|
@@ -124,6 +167,33 @@ async function loadSpecifiedNxPlugins(pluginsConfigurations, root = workspace_ro
|
|
|
124
167
|
}));
|
|
125
168
|
performance.mark('loadSpecifiedNxPlugins:end');
|
|
126
169
|
performance.measure('loadSpecifiedNxPlugins', 'loadSpecifiedNxPlugins:start', 'loadSpecifiedNxPlugins:end');
|
|
170
|
+
const plugins = [];
|
|
171
|
+
const errors = [];
|
|
172
|
+
for (let i = 0; i < results.length; i++) {
|
|
173
|
+
const result = results[i];
|
|
174
|
+
if (result.status === 'fulfilled') {
|
|
175
|
+
plugins.push(result.value);
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
const pluginConfig = pluginsConfigurations[i];
|
|
179
|
+
const pluginName = typeof pluginConfig === 'string' ? pluginConfig : pluginConfig.plugin;
|
|
180
|
+
errors.push({
|
|
181
|
+
pluginName,
|
|
182
|
+
error: result.reason instanceof Error
|
|
183
|
+
? result.reason
|
|
184
|
+
: new Error(String(result.reason)),
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (errors.length > 0) {
|
|
189
|
+
for (const fn of cleanupFunctions) {
|
|
190
|
+
fn();
|
|
191
|
+
}
|
|
192
|
+
const errorMessage = errors
|
|
193
|
+
.map((e) => ` - ${e.pluginName}: ${e.error.message}`)
|
|
194
|
+
.join('\n');
|
|
195
|
+
throw new AggregateError(errors.map((e) => e.error), `Failed to load ${errors.length} Nx plugin(s):\n${errorMessage}`);
|
|
196
|
+
}
|
|
127
197
|
cleanupSpecifiedPlugins = () => {
|
|
128
198
|
for (const fn of cleanupFunctions) {
|
|
129
199
|
fn();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-pool.d.ts","sourceRoot":"","sources":["../../../../../../../packages/nx/src/project-graph/plugins/isolation/plugin-pool.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"plugin-pool.d.ts","sourceRoot":"","sources":["../../../../../../../packages/nx/src/project-graph/plugins/isolation/plugin-pool.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAM9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AA4C1D,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,mBAAmB,EAC3B,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC,CAmGhD"}
|
|
@@ -4,8 +4,7 @@ exports.loadRemoteNxPlugin = loadRemoteNxPlugin;
|
|
|
4
4
|
const child_process_1 = require("child_process");
|
|
5
5
|
const net_1 = require("net");
|
|
6
6
|
const path = require("path");
|
|
7
|
-
|
|
8
|
-
// import { logger } from '../../utils/logger';
|
|
7
|
+
const logger_1 = require("../../../utils/logger");
|
|
9
8
|
const socket_utils_1 = require("../../../daemon/socket-utils");
|
|
10
9
|
const consume_messages_from_socket_1 = require("../../../utils/consume-messages-from-socket");
|
|
11
10
|
const installation_directory_1 = require("../../../utils/installation-directory");
|
|
@@ -116,6 +115,7 @@ function createWorkerHandler(worker, pending, onload, onloadError, socket) {
|
|
|
116
115
|
const { name, createNodesPattern, include, exclude } = result;
|
|
117
116
|
pluginName = name;
|
|
118
117
|
pluginNames.set(worker, pluginName);
|
|
118
|
+
logger_1.logger.verbose(`[plugin-pool] loaded plugin "${name}" from worker (pid: ${worker.pid})`);
|
|
119
119
|
onload({
|
|
120
120
|
name,
|
|
121
121
|
include,
|
|
@@ -298,6 +298,7 @@ function registerPendingPromise(tx, pending, callback, context) {
|
|
|
298
298
|
}
|
|
299
299
|
global.nxPluginWorkerCount ??= 0;
|
|
300
300
|
async function startPluginWorker(name) {
|
|
301
|
+
performance.mark(`start-plugin-worker:${name}`);
|
|
301
302
|
// this should only really be true when running unit tests within
|
|
302
303
|
// the Nx repo. We still need to start the worker in this case,
|
|
303
304
|
// but its typescript.
|
|
@@ -325,6 +326,7 @@ async function startPluginWorker(name) {
|
|
|
325
326
|
shell: false,
|
|
326
327
|
windowsHide: true,
|
|
327
328
|
});
|
|
329
|
+
logger_1.logger.verbose(`[plugin-pool] spawned worker for "${name}" (pid: ${worker.pid}, socket: ${ipcPath})`);
|
|
328
330
|
// To make debugging easier and allow plugins to communicate things
|
|
329
331
|
// like performance metrics, we pipe the stdout/stderr of the worker
|
|
330
332
|
// to the main process.
|
|
@@ -343,32 +345,11 @@ async function startPluginWorker(name) {
|
|
|
343
345
|
if (stderrMaxListeners !== 0) {
|
|
344
346
|
process.stderr.setMaxListeners(stderrMaxListeners + 1);
|
|
345
347
|
}
|
|
346
|
-
worker.
|
|
347
|
-
worker.
|
|
348
|
+
// Pipe and unref the worker streams. The utility handles cross-runtime compatibility.
|
|
349
|
+
pipeAndUnrefChildStream(worker.stdout, process.stdout, 'stdout');
|
|
350
|
+
pipeAndUnrefChildStream(worker.stderr, process.stderr, 'stderr');
|
|
348
351
|
// Unref the worker process so it doesn't prevent the parent from exiting.
|
|
349
|
-
// IMPORTANT: We must also unref the stdout/stderr streams. When streams are
|
|
350
|
-
// piped, they maintain internal references in Node's event loop. Without
|
|
351
|
-
// unreferencing them, the parent process will wait for the worker to exit
|
|
352
|
-
// even after worker.unref() is called. This causes e2e tests to hang on CI
|
|
353
|
-
// where test frameworks wait for all handles to be released.
|
|
354
|
-
//
|
|
355
|
-
// Although TypeScript types these as Readable/Writable, they are actually
|
|
356
|
-
// net.Socket instances at runtime. Node.js internally creates sockets for
|
|
357
|
-
// stdio pipes (see lib/internal/child_process.js createSocket function).
|
|
358
|
-
// Socket.unref() allows the event loop to exit if these are the only handles.
|
|
359
352
|
worker.unref();
|
|
360
|
-
if (worker.stdout instanceof net_1.Socket) {
|
|
361
|
-
worker.stdout.unref();
|
|
362
|
-
}
|
|
363
|
-
else {
|
|
364
|
-
throw new Error(`Expected worker.stdout to be an instance of Socket, but got ${getTypeName(worker.stdout)}`);
|
|
365
|
-
}
|
|
366
|
-
if (worker.stderr instanceof net_1.Socket) {
|
|
367
|
-
worker.stderr.unref();
|
|
368
|
-
}
|
|
369
|
-
else {
|
|
370
|
-
throw new Error(`Expected worker.stderr to be an instance of Socket, but got ${getTypeName(worker.stderr)}`);
|
|
371
|
-
}
|
|
372
353
|
let attempts = 0;
|
|
373
354
|
return new Promise((resolve, reject) => {
|
|
374
355
|
const id = setInterval(async () => {
|
|
@@ -376,6 +357,7 @@ async function startPluginWorker(name) {
|
|
|
376
357
|
if (socket) {
|
|
377
358
|
socket.unref();
|
|
378
359
|
clearInterval(id);
|
|
360
|
+
logger_1.logger.verbose(`[plugin-pool] connected to worker for "${name}" (pid: ${worker.pid}) after ${attempts} attempt(s)`);
|
|
379
361
|
resolve({
|
|
380
362
|
worker,
|
|
381
363
|
socket,
|
|
@@ -384,12 +366,16 @@ async function startPluginWorker(name) {
|
|
|
384
366
|
else if (attempts > 10000) {
|
|
385
367
|
// daemon fails to start, the process probably exited
|
|
386
368
|
// we print the logs and exit the client
|
|
387
|
-
|
|
369
|
+
clearInterval(id);
|
|
370
|
+
reject(new Error(`Failed to start plugin worker for plugin ${name}`));
|
|
388
371
|
}
|
|
389
372
|
else {
|
|
390
373
|
attempts++;
|
|
391
374
|
}
|
|
392
375
|
}, 10);
|
|
376
|
+
}).finally(() => {
|
|
377
|
+
performance.mark(`start-plugin-worker-end:${name}`);
|
|
378
|
+
performance.measure(`start-plugin-worker:${name}`, `start-plugin-worker:${name}`, `start-plugin-worker-end:${name}`);
|
|
393
379
|
});
|
|
394
380
|
}
|
|
395
381
|
function isServerAvailable(ipcPath) {
|
|
@@ -420,3 +406,68 @@ function getTypeName(u) {
|
|
|
420
406
|
}
|
|
421
407
|
return u.constructor?.name ?? 'unknown object';
|
|
422
408
|
}
|
|
409
|
+
/**
|
|
410
|
+
* Detects if we're running under an alternative JavaScript runtime (Bun or Deno).
|
|
411
|
+
* Returns the runtime name for helpful error messages, or null if running on Node.js.
|
|
412
|
+
*/
|
|
413
|
+
function detectAlternativeRuntime() {
|
|
414
|
+
// Check for Bun runtime - the Bun global is only available in Bun
|
|
415
|
+
if ('Bun' in globalThis && typeof globalThis.Bun !== 'undefined') {
|
|
416
|
+
return 'bun';
|
|
417
|
+
}
|
|
418
|
+
// Check for Deno runtime - the Deno global is only available in Deno
|
|
419
|
+
if ('Deno' in globalThis && typeof globalThis.Deno !== 'undefined') {
|
|
420
|
+
return 'deno';
|
|
421
|
+
}
|
|
422
|
+
return null;
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Pipes a child process stream to a destination and attempts to unref it to prevent
|
|
426
|
+
* the stream from keeping the parent process alive.
|
|
427
|
+
*
|
|
428
|
+
* In Node.js, child process stdio streams are actually net.Socket instances when
|
|
429
|
+
* using 'pipe' stdio option. However, alternative runtimes like Bun and Deno may
|
|
430
|
+
* use standard Readable/Writable streams instead.
|
|
431
|
+
*
|
|
432
|
+
* This function:
|
|
433
|
+
* 1. Pipes the source to the destination
|
|
434
|
+
* 2. Attempts to unref the source stream to allow the parent process to exit
|
|
435
|
+
* 3. Uses duck-typing to check for unref support when not a Socket instance
|
|
436
|
+
* 4. Emits helpful warnings for alternative runtimes if unref is not available
|
|
437
|
+
*
|
|
438
|
+
* @param source - The child process stream (stdout or stderr)
|
|
439
|
+
* @param destination - The process stream to pipe to (process.stdout or process.stderr)
|
|
440
|
+
* @param streamName - Name of the stream for warning messages ('stdout' or 'stderr')
|
|
441
|
+
*/
|
|
442
|
+
function pipeAndUnrefChildStream(source, destination, streamName) {
|
|
443
|
+
if (!source) {
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
source.pipe(destination);
|
|
447
|
+
// Node.js creates net.Socket instances for stdio pipes. Use instanceof check first.
|
|
448
|
+
if (source instanceof net_1.Socket) {
|
|
449
|
+
source.unref();
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
// For non-Socket streams (e.g., in Bun/Deno), use duck-typing to check for unref
|
|
453
|
+
// NOTE: These should also be a Socket, but alternative runtimes may implement differently...
|
|
454
|
+
// See:
|
|
455
|
+
// - https://github.com/denoland/deno/issues/31961
|
|
456
|
+
// - https://github.com/oven-sh/bun/issues/26505
|
|
457
|
+
if (typeof source.unref === 'function') {
|
|
458
|
+
source.unref();
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
// Stream doesn't support unref - emit a warning with runtime-specific guidance
|
|
462
|
+
const runtime = detectAlternativeRuntime();
|
|
463
|
+
if (runtime) {
|
|
464
|
+
console.warn(`[NX] worker.${streamName} does not support unref() in ${runtime}. ` +
|
|
465
|
+
`This may cause the process to hang when waiting for plugin workers to exit. ` +
|
|
466
|
+
`This is a known limitation of ${runtime}'s Node.js compatibility layer.`);
|
|
467
|
+
}
|
|
468
|
+
else {
|
|
469
|
+
console.warn(`[NX] worker.${streamName} is not a net.Socket and does not have an unref() method. ` +
|
|
470
|
+
`Expected Socket, got ${getTypeName(source)}. ` +
|
|
471
|
+
`This may cause the process to hang when waiting for plugin workers to exit.`);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
@@ -2,30 +2,35 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const node_perf_hooks_1 = require("node:perf_hooks");
|
|
4
4
|
node_perf_hooks_1.performance.mark(`plugin worker ${process.pid} code loading -- start`);
|
|
5
|
-
const messaging_1 = require("./messaging");
|
|
6
|
-
const serializable_error_1 = require("../../../utils/serializable-error");
|
|
7
5
|
const consume_messages_from_socket_1 = require("../../../utils/consume-messages-from-socket");
|
|
8
|
-
const
|
|
6
|
+
const logger_1 = require("../../../utils/logger");
|
|
7
|
+
const serializable_error_1 = require("../../../utils/serializable-error");
|
|
8
|
+
const messaging_1 = require("./messaging");
|
|
9
9
|
const fs_1 = require("fs");
|
|
10
|
-
|
|
10
|
+
const net_1 = require("net");
|
|
11
|
+
const environment = process.env;
|
|
12
|
+
if (environment.NX_PERF_LOGGING === 'true') {
|
|
11
13
|
require('../../../utils/perf-logging');
|
|
12
14
|
}
|
|
13
15
|
node_perf_hooks_1.performance.mark(`plugin worker ${process.pid} code loading -- end`);
|
|
14
16
|
node_perf_hooks_1.performance.measure(`plugin worker ${process.pid} code loading`, `plugin worker ${process.pid} code loading -- start`, `plugin worker ${process.pid} code loading -- end`);
|
|
15
17
|
global.NX_GRAPH_CREATION = true;
|
|
16
18
|
global.NX_PLUGIN_WORKER = true;
|
|
17
|
-
let connected = false;
|
|
18
19
|
let plugin;
|
|
19
20
|
const socketPath = process.argv[2];
|
|
21
|
+
const expectedPluginName = process.argv[3];
|
|
22
|
+
let connectErrorTimeout = setErrorTimeout(5000, `The plugin worker for ${expectedPluginName} is exiting as it was not connected to within 5 seconds. ` +
|
|
23
|
+
'Plugin workers expect to receive a socket connection from the parent process shortly after being started. ' +
|
|
24
|
+
'If you are seeing this issue, please report it to the Nx team at https://github.com/nrwl/nx/issues.');
|
|
20
25
|
const server = (0, net_1.createServer)((socket) => {
|
|
21
|
-
|
|
26
|
+
connectErrorTimeout?.clear();
|
|
27
|
+
logger_1.logger.verbose(`[plugin-worker] "${expectedPluginName}" (pid: ${process.pid}) connected`);
|
|
22
28
|
// This handles cases where the host process was killed
|
|
23
29
|
// after the worker connected but before the worker was
|
|
24
30
|
// instructed to load the plugin.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}, 10000).unref();
|
|
31
|
+
let loadErrorTimeout = setErrorTimeout(10_000, `Plugin Worker for ${expectedPluginName} is exiting as it did not receive a load message within 10 seconds of connecting. ` +
|
|
32
|
+
'This likely indicates that the host process was terminated before the worker could be instructed to load the plugin. ' +
|
|
33
|
+
'If you are seeing this issue, please report it to the Nx team at https://github.com/nrwl/nx/issues.');
|
|
29
34
|
socket.on('data', (0, consume_messages_from_socket_1.consumeMessagesFromSocket)((raw) => {
|
|
30
35
|
const message = JSON.parse(raw.toString());
|
|
31
36
|
if (!(0, messaging_1.isPluginWorkerMessage)(message)) {
|
|
@@ -33,8 +38,7 @@ const server = (0, net_1.createServer)((socket) => {
|
|
|
33
38
|
}
|
|
34
39
|
return (0, messaging_1.consumeMessage)(socket, message, {
|
|
35
40
|
load: async ({ plugin: pluginConfiguration, root, name, pluginPath, shouldRegisterTSTranspiler, }) => {
|
|
36
|
-
|
|
37
|
-
clearTimeout(loadTimeout);
|
|
41
|
+
loadErrorTimeout?.clear();
|
|
38
42
|
process.chdir(root);
|
|
39
43
|
try {
|
|
40
44
|
const { loadResolvedNxPluginAsync } = await Promise.resolve().then(() => require('../load-resolved-plugin'));
|
|
@@ -44,6 +48,7 @@ const server = (0, net_1.createServer)((socket) => {
|
|
|
44
48
|
require('../transpiler').registerPluginTSTranspiler();
|
|
45
49
|
}
|
|
46
50
|
plugin = await loadResolvedNxPluginAsync(pluginConfiguration, pluginPath, name);
|
|
51
|
+
logger_1.logger.verbose(`[plugin-worker] "${name}" (pid: ${process.pid}) loaded successfully`);
|
|
47
52
|
return {
|
|
48
53
|
type: 'load-result',
|
|
49
54
|
payload: {
|
|
@@ -186,13 +191,24 @@ const server = (0, net_1.createServer)((socket) => {
|
|
|
186
191
|
});
|
|
187
192
|
});
|
|
188
193
|
server.listen(socketPath);
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
194
|
+
logger_1.logger.verbose(`[plugin-worker] "${expectedPluginName}" (pid: ${process.pid}) listening on ${socketPath}`);
|
|
195
|
+
function setErrorTimeout(timeoutMs, errorMessage) {
|
|
196
|
+
if (environment.NX_PLUGIN_NO_TIMEOUTS === 'true') {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
let cleared = false;
|
|
200
|
+
const timeout = setTimeout(() => {
|
|
201
|
+
if (!cleared) {
|
|
202
|
+
console.error(errorMessage);
|
|
193
203
|
process.exit(1);
|
|
194
204
|
}
|
|
195
|
-
},
|
|
205
|
+
}, timeoutMs).unref();
|
|
206
|
+
return {
|
|
207
|
+
clear: () => {
|
|
208
|
+
cleared = true;
|
|
209
|
+
clearTimeout(timeout);
|
|
210
|
+
},
|
|
211
|
+
};
|
|
196
212
|
}
|
|
197
213
|
const exitHandler = (exitCode) => () => {
|
|
198
214
|
server.close();
|
|
@@ -40,7 +40,7 @@ function readCachedProjectGraph(minimumComputedAt) {
|
|
|
40
40
|
? (0, strip_indents_1.stripIndents) `
|
|
41
41
|
Make sure invoke 'node ./decorate-angular-cli.js' in your postinstall script.
|
|
42
42
|
The decorated CLI will compute the project graph.
|
|
43
|
-
'ng --help' should say 'Smart
|
|
43
|
+
'ng --help' should say 'Smart Monorepos · Fast Builds'.
|
|
44
44
|
`
|
|
45
45
|
: '';
|
|
46
46
|
throw new Error((0, strip_indents_1.stripIndents) `
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consume-messages-from-socket.d.ts","sourceRoot":"","sources":["../../../../../packages/nx/src/utils/consume-messages-from-socket.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"consume-messages-from-socket.d.ts","sourceRoot":"","sources":["../../../../../packages/nx/src/utils/consume-messages-from-socket.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,eAAe,QACuB,CAAC;AAEpD,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,IAGnE,SAAI,UA4Bb;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAYtD"}
|
|
@@ -3,12 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.MESSAGE_END_SEQ = void 0;
|
|
4
4
|
exports.consumeMessagesFromSocket = consumeMessagesFromSocket;
|
|
5
5
|
exports.isJsonMessage = isJsonMessage;
|
|
6
|
+
const string_decoder_1 = require("string_decoder");
|
|
6
7
|
const VERY_END_CODE = 4;
|
|
7
8
|
exports.MESSAGE_END_SEQ = 'NX_MSG_END' + String.fromCharCode(VERY_END_CODE);
|
|
8
9
|
function consumeMessagesFromSocket(callback) {
|
|
9
10
|
let message = '';
|
|
11
|
+
const decoder = new string_decoder_1.StringDecoder('utf8');
|
|
10
12
|
return (data) => {
|
|
11
|
-
const chunk =
|
|
13
|
+
const chunk = decoder.write(data);
|
|
12
14
|
message += chunk;
|
|
13
15
|
// Check if accumulated message ends with MESSAGE_END_SEQ (not just the chunk)
|
|
14
16
|
// This handles TCP packet fragmentation where MESSAGE_END_SEQ may be split across packets
|
|
@@ -3,12 +3,5 @@ export declare class PromisedBasedQueue {
|
|
|
3
3
|
private promise;
|
|
4
4
|
sendToQueue(fn: () => Promise<any>): Promise<any>;
|
|
5
5
|
isEmpty(): boolean;
|
|
6
|
-
/**
|
|
7
|
-
* Used to decrement the internal counter representing the number of active promises in the queue.
|
|
8
|
-
* This is useful for retrying a failed daemon message, as we want to be able to shut the daemon down
|
|
9
|
-
* without marking the promise that represents the failed message as settled. To do so, we store
|
|
10
|
-
* the promise in a separate variable and only resolve or reject it later.
|
|
11
|
-
*/
|
|
12
|
-
decrementQueueCounter(): void;
|
|
13
6
|
}
|
|
14
7
|
//# sourceMappingURL=promised-based-queue.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"promised-based-queue.d.ts","sourceRoot":"","sources":["../../../../../packages/nx/src/utils/promised-based-queue.ts"],"names":[],"mappings":"AAAA,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,OAAO,CAAyB;IAExC,WAAW,CAAC,EAAE,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC;IA8BjD,OAAO;
|
|
1
|
+
{"version":3,"file":"promised-based-queue.d.ts","sourceRoot":"","sources":["../../../../../packages/nx/src/utils/promised-based-queue.ts"],"names":[],"mappings":"AAAA,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,OAAO,CAAyB;IAExC,WAAW,CAAC,EAAE,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC;IA8BjD,OAAO;CAGR"}
|
|
@@ -39,14 +39,5 @@ class PromisedBasedQueue {
|
|
|
39
39
|
isEmpty() {
|
|
40
40
|
return this.counter === 0;
|
|
41
41
|
}
|
|
42
|
-
/**
|
|
43
|
-
* Used to decrement the internal counter representing the number of active promises in the queue.
|
|
44
|
-
* This is useful for retrying a failed daemon message, as we want to be able to shut the daemon down
|
|
45
|
-
* without marking the promise that represents the failed message as settled. To do so, we store
|
|
46
|
-
* the promise in a separate variable and only resolve or reject it later.
|
|
47
|
-
*/
|
|
48
|
-
decrementQueueCounter() {
|
|
49
|
-
this.counter--;
|
|
50
|
-
}
|
|
51
42
|
}
|
|
52
43
|
exports.PromisedBasedQueue = PromisedBasedQueue;
|