UNPKG

nx

Version:

The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.

152 lines (151 loc) • 6.83 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SERVER_INACTIVITY_TIMEOUT_MS = void 0; exports.storeWatcherInstance = storeWatcherInstance; exports.getWatcherInstance = getWatcherInstance; exports.storeOutputWatcherInstance = storeOutputWatcherInstance; exports.getOutputWatcherInstance = getOutputWatcherInstance; exports.handleServerProcessTermination = handleServerProcessTermination; exports.handleServerProcessTerminationWithRestart = handleServerProcessTerminationWithRestart; exports.resetInactivityTimeout = resetInactivityTimeout; exports.respondToClient = respondToClient; exports.respondWithErrorAndExit = respondWithErrorAndExit; const workspace_root_1 = require("../../utils/workspace-root"); const logger_1 = require("../logger"); const socket_utils_1 = require("../socket-utils"); const cache_1 = require("../cache"); const error_types_1 = require("../../project-graph/error-types"); const db_connection_1 = require("../../utils/db-connection"); const get_plugins_1 = require("../../project-graph/plugins/get-plugins"); const consume_messages_from_socket_1 = require("../../utils/consume-messages-from-socket"); const nx_console_operations_1 = require("./nx-console-operations"); const child_process_1 = require("child_process"); const path_1 = require("path"); const node_fs_1 = require("node:fs"); const promises_1 = require("fs/promises"); const tmp_dir_1 = require("../tmp-dir"); exports.SERVER_INACTIVITY_TIMEOUT_MS = 10800000; // 10800000 ms = 3 hours async function startNewDaemonInBackground() { (0, node_fs_1.mkdirSync)(tmp_dir_1.DAEMON_DIR_FOR_CURRENT_WORKSPACE, { recursive: true }); if (!(0, node_fs_1.existsSync)(tmp_dir_1.DAEMON_OUTPUT_LOG_FILE)) { (0, node_fs_1.writeFileSync)(tmp_dir_1.DAEMON_OUTPUT_LOG_FILE, ''); } const out = await (0, promises_1.open)(tmp_dir_1.DAEMON_OUTPUT_LOG_FILE, 'a'); const err = await (0, promises_1.open)(tmp_dir_1.DAEMON_OUTPUT_LOG_FILE, 'a'); // Use require.resolve to find the currently installed version's start.js // instead of using __dirname which points to the old running daemon's path // Resolve from workspace root to pick up the correct symlink target let startScriptPath; try { startScriptPath = require.resolve('nx/src/daemon/server/start.js', { paths: [workspace_root_1.workspaceRoot], }); } catch (e) { // Fall back to using __dirname if resolution fails logger_1.serverLogger.log(`Failed to resolve nx package, falling back to __dirname: ${e.message}`); startScriptPath = (0, path_1.join)(__dirname, '../server/start.js'); } logger_1.serverLogger.log(`Restarting daemon with script: ${startScriptPath}`); logger_1.serverLogger.log(`Old daemon __dirname: ${__dirname}`); logger_1.serverLogger.log(`Current process.execPath: ${process.execPath}`); const backgroundProcess = (0, child_process_1.spawn)(process.execPath, [startScriptPath], { cwd: workspace_root_1.workspaceRoot, stdio: ['ignore', out.fd, err.fd], detached: true, windowsHide: false, shell: false, env: process.env, }); backgroundProcess.unref(); logger_1.serverLogger.log('Started new daemon process in background'); } let watcherInstance; function storeWatcherInstance(instance) { watcherInstance = instance; } function getWatcherInstance() { return watcherInstance; } let outputWatcherInstance; function storeOutputWatcherInstance(instance) { outputWatcherInstance = instance; } function getOutputWatcherInstance() { return outputWatcherInstance; } async function handleServerProcessTermination({ server, reason, sockets, }) { await performShutdown(server, reason, sockets); } async function handleServerProcessTerminationWithRestart({ server, reason, sockets, }) { // Clean up old daemon cache before starting new instance (0, cache_1.deleteDaemonJsonProcessCache)(); // Start new daemon before shutting down await startNewDaemonInBackground(); await performShutdown(server, reason, sockets); } async function performShutdown(server, reason, sockets) { try { await new Promise((res) => { server.close(() => { res(null); }); for (const socket of sockets) { socket.destroy(); } }); if (watcherInstance) { await watcherInstance.stop(); logger_1.serverLogger.watcherLog(`Stopping the watcher for ${workspace_root_1.workspaceRoot} (sources)`); } if (outputWatcherInstance) { await outputWatcherInstance.stop(); logger_1.serverLogger.watcherLog(`Stopping the watcher for ${workspace_root_1.workspaceRoot} (outputs)`); } (0, cache_1.deleteDaemonJsonProcessCache)(); (0, get_plugins_1.cleanupPlugins)(); (0, db_connection_1.removeDbConnections)(); // Clean up Nx Console latest installation (0, nx_console_operations_1.cleanupLatestNxInstallation)(); logger_1.serverLogger.log(`Server stopped because: "${reason}"`); } finally { process.exit(0); } } let serverInactivityTimerId; function resetInactivityTimeout(cb) { if (serverInactivityTimerId) { clearTimeout(serverInactivityTimerId); } serverInactivityTimerId = setTimeout(cb, exports.SERVER_INACTIVITY_TIMEOUT_MS); } function respondToClient(socket, response, description) { return new Promise(async (res) => { if (description) { logger_1.serverLogger.requestLog(`Responding to the client.`, description); } socket.write(response + consume_messages_from_socket_1.MESSAGE_END_SEQ, (err) => { if (err) { logger_1.serverLogger.log(`Socket write error (client likely disconnected): ${err.message}`); } logger_1.serverLogger.log(`Done responding to the client`, description); res(null); }); }); } async function respondWithErrorAndExit(socket, description, error) { const isProjectGraphError = error instanceof error_types_1.DaemonProjectGraphError; const normalizedError = isProjectGraphError ? error_types_1.ProjectGraphError.fromDaemonProjectGraphError(error) : error; // print some extra stuff in the error message logger_1.serverLogger.requestLog(`Responding to the client with an error.`, description, normalizedError.message); console.error(normalizedError.stack); // Respond with the original error await respondToClient(socket, (0, socket_utils_1.serializeResult)(error, null, null), null); // Project Graph errors are okay. Restarting the daemon won't help with this. if (!isProjectGraphError) { process.exit(1); } }