fix(core): propagate errors when daemon isn't able to start
This commit is contained in:
parent
7d13b54216
commit
1e6761ebc3
1
nx-dev/nx-dev/next-env.d.ts
vendored
1
nx-dev/nx-dev/next-env.d.ts
vendored
@ -1,5 +1,4 @@
|
|||||||
/// <reference types="next" />
|
/// <reference types="next" />
|
||||||
/// <reference types="next/types/global" />
|
|
||||||
/// <reference types="next/image-types/global" />
|
/// <reference types="next/image-types/global" />
|
||||||
|
|
||||||
// NOTE: This file should not be edited
|
// NOTE: This file should not be edited
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nrwl/nx-source",
|
"name": "@nrwl/nx-source",
|
||||||
"version": "13.3.0-beta.22",
|
"version": "13.3.0-beta.24",
|
||||||
"description": "Smart, Extensible Build Framework",
|
"description": "Smart, Extensible Build Framework",
|
||||||
"homepage": "https://nx.dev",
|
"homepage": "https://nx.dev",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { logger, ProjectGraph } from '@nrwl/devkit';
|
import { logger, ProjectGraph } from '@nrwl/devkit';
|
||||||
import { ChildProcess, spawn, spawnSync } from 'child_process';
|
import { ChildProcess, spawn, spawnSync } from 'child_process';
|
||||||
import { existsSync, openSync } from 'fs';
|
import { existsSync, openSync, readFileSync } from 'fs';
|
||||||
import { connect } from 'net';
|
import { connect } from 'net';
|
||||||
import { performance } from 'perf_hooks';
|
import { performance } from 'perf_hooks';
|
||||||
import {
|
import {
|
||||||
@ -13,6 +13,7 @@ import {
|
|||||||
killSocketOrPath,
|
killSocketOrPath,
|
||||||
} from '../socket-utils';
|
} from '../socket-utils';
|
||||||
import { DAEMON_OUTPUT_LOG_FILE } from '../tmp-dir';
|
import { DAEMON_OUTPUT_LOG_FILE } from '../tmp-dir';
|
||||||
|
import { output } from '../../../../utilities/output';
|
||||||
|
|
||||||
export async function startInBackground(): Promise<ChildProcess['pid']> {
|
export async function startInBackground(): Promise<ChildProcess['pid']> {
|
||||||
await safelyCleanUpExistingProcess();
|
await safelyCleanUpExistingProcess();
|
||||||
@ -37,17 +38,45 @@ export async function startInBackground(): Promise<ChildProcess['pid']> {
|
|||||||
/**
|
/**
|
||||||
* Ensure the server is actually available to connect to via IPC before resolving
|
* Ensure the server is actually available to connect to via IPC before resolving
|
||||||
*/
|
*/
|
||||||
|
let attempts = 0;
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const id = setInterval(async () => {
|
const id = setInterval(async () => {
|
||||||
if (await isServerAvailable()) {
|
if (await isServerAvailable()) {
|
||||||
clearInterval(id);
|
clearInterval(id);
|
||||||
resolve(backgroundProcess.pid);
|
resolve(backgroundProcess.pid);
|
||||||
|
} else if (attempts > 200) {
|
||||||
|
// daemon fails to start, the process probably exited
|
||||||
|
// we print the logs and exit the client
|
||||||
|
throw daemonProcessException(
|
||||||
|
'Failed to start the Nx Daemon process.'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
attempts++;
|
||||||
}
|
}
|
||||||
}, 500);
|
}, 10);
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error(err);
|
throw err;
|
||||||
process.exit(1);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function daemonProcessException(message: string) {
|
||||||
|
try {
|
||||||
|
let log = readFileSync(DAEMON_OUTPUT_LOG_FILE).toString().split('\n');
|
||||||
|
if (log.length > 20) {
|
||||||
|
log = log.slice(log.length - 20);
|
||||||
|
}
|
||||||
|
return new Error(
|
||||||
|
[
|
||||||
|
message,
|
||||||
|
'Messages from the log:',
|
||||||
|
...log,
|
||||||
|
'\n',
|
||||||
|
`More information: ${DAEMON_OUTPUT_LOG_FILE}`,
|
||||||
|
].join('\n')
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
return new Error(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,7 +100,7 @@ export function stop(): void {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* As noted in the comments above the createServer() call, in order to reliably (meaning it works
|
* As noted in the comments above the createServer() call, in order to reliably (meaning it works
|
||||||
* cross-platform) check whether or not the server is availabe to request a project graph from we
|
* cross-platform) check whether the server is available to request a project graph from we
|
||||||
* need to actually attempt connecting to it.
|
* need to actually attempt connecting to it.
|
||||||
*
|
*
|
||||||
* Because of the behavior of named pipes on Windows, we cannot simply treat them as a file and
|
* Because of the behavior of named pipes on Windows, we cannot simply treat them as a file and
|
||||||
@ -109,18 +138,22 @@ export async function getProjectGraphFromServer(): Promise<ProjectGraph> {
|
|||||||
const socket = connect(FULL_OS_SOCKET_PATH);
|
const socket = connect(FULL_OS_SOCKET_PATH);
|
||||||
|
|
||||||
socket.on('error', (err) => {
|
socket.on('error', (err) => {
|
||||||
let errorMessage: string | undefined;
|
let error: any;
|
||||||
if (err.message.startsWith('connect ENOENT')) {
|
if (err.message.startsWith('connect ENOENT')) {
|
||||||
errorMessage = 'Error: The Daemon Server is not running';
|
error = daemonProcessException('The Daemon Server is not running');
|
||||||
}
|
}
|
||||||
if (err.message.startsWith('connect ECONNREFUSED')) {
|
if (err.message.startsWith('connect ECONNREFUSED')) {
|
||||||
// If somehow the file descriptor had not been released during a previous shut down.
|
error = daemonProcessException(
|
||||||
if (existsSync(FULL_OS_SOCKET_PATH)) {
|
`A server instance had not been fully shut down. Please try running the command again.`
|
||||||
errorMessage = `Error: A server instance had not been fully shut down. Please try running the command again.`;
|
);
|
||||||
killSocketOrPath();
|
killSocketOrPath();
|
||||||
}
|
}
|
||||||
|
if (err.message.startsWith('read ECONNRESET')) {
|
||||||
|
error = daemonProcessException(
|
||||||
|
`Unable to connect to the daemon process.`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return reject(new Error(errorMessage) || err);
|
return reject(error || err);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -268,8 +268,10 @@ export async function startServer(): Promise<Server> {
|
|||||||
if (!isWindows) {
|
if (!isWindows) {
|
||||||
killSocketOrPath();
|
killSocketOrPath();
|
||||||
}
|
}
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
server.listen(FULL_OS_SOCKET_PATH, async () => {
|
server.listen(FULL_OS_SOCKET_PATH, async () => {
|
||||||
|
try {
|
||||||
serverLogger.log(`Started listening on: ${FULL_OS_SOCKET_PATH}`);
|
serverLogger.log(`Started listening on: ${FULL_OS_SOCKET_PATH}`);
|
||||||
// this triggers the storage of the lock file hash
|
// this triggers the storage of the lock file hash
|
||||||
lockFileChanged();
|
lockFileChanged();
|
||||||
@ -278,11 +280,18 @@ export async function startServer(): Promise<Server> {
|
|||||||
watcherSubscription = await subscribeToWorkspaceChanges(
|
watcherSubscription = await subscribeToWorkspaceChanges(
|
||||||
handleWorkspaceChanges
|
handleWorkspaceChanges
|
||||||
);
|
);
|
||||||
serverLogger.watcherLog(`Subscribed to changes within: ${appRootPath}`);
|
serverLogger.watcherLog(
|
||||||
|
`Subscribed to changes within: ${appRootPath}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolve(server);
|
return resolve(server);
|
||||||
|
} catch (err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
} catch (err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
import { logger } from '@nrwl/devkit';
|
import { logger } from '@nrwl/devkit';
|
||||||
import { startServer } from './server';
|
import { startServer } from './server';
|
||||||
|
import * as process from 'process';
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
await startServer();
|
await startServer();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error(err);
|
logger.error(err);
|
||||||
|
process.exit(1);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user