Skip to content

Commit

Permalink
fix(core): read socket dir on demand & load .env files on client star…
Browse files Browse the repository at this point in the history
…tup (#23348)

<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

## Current Behavior
The daemon doesn't correctly read the `NX_DAEMON_SOCKET_DIR` env
variable if it's set in `.env`.
Also, the `.env` files aren't loaded if the daemon client is imported &
used directly (like it is in Nx Console).

## Expected Behavior
The daemon should correctly read the `NX_DAEMON_SOCKET_DIR` variable
regardless of where it's specified and setting it shouldn't cause any
issues with Nx Console.

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes nrwl/nx-console#2114

(cherry picked from commit 6c36bef)
  • Loading branch information
MaxKless authored and FrozenPandaz committed May 14, 2024
1 parent d9c5fe9 commit d75bab7
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 27 deletions.
11 changes: 7 additions & 4 deletions packages/nx/src/daemon/client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { connect } from 'net';
import { join } from 'path';
import { performance } from 'perf_hooks';
import { output } from '../../utils/output';
import { FULL_OS_SOCKET_PATH, killSocketOrPath } from '../socket-utils';
import { getFullOsSocketPath, killSocketOrPath } from '../socket-utils';
import {
DAEMON_DIR_FOR_CURRENT_WORKSPACE,
DAEMON_OUTPUT_LOG_FILE,
Expand All @@ -29,6 +29,7 @@ import {
DaemonProjectGraphError,
ProjectGraphError,
} from '../../project-graph/error-types';
import { loadRootEnvFiles } from '../../utils/dotenv';

const DAEMON_ENV_SETTINGS = {
NX_PROJECT_GLOB_CACHE: 'false',
Expand All @@ -50,6 +51,8 @@ enum DaemonStatus {
export class DaemonClient {
private readonly nxJson: NxJsonConfiguration | null;
constructor() {
loadRootEnvFiles(workspaceRoot);

try {
this.nxJson = readNxJson();
} catch (e) {
Expand Down Expand Up @@ -202,7 +205,7 @@ export class DaemonClient {

await this.queue.sendToQueue(() => {
messenger = new DaemonSocketMessenger(
connect(FULL_OS_SOCKET_PATH)
connect(getFullOsSocketPath())
).listen(
(message) => {
try {
Expand Down Expand Up @@ -256,7 +259,7 @@ export class DaemonClient {
async isServerAvailable(): Promise<boolean> {
return new Promise((resolve) => {
try {
const socket = connect(FULL_OS_SOCKET_PATH, () => {
const socket = connect(getFullOsSocketPath(), () => {
socket.destroy();
resolve(true);
});
Expand All @@ -277,7 +280,7 @@ export class DaemonClient {

private setUpConnection() {
this.socketMessenger = new DaemonSocketMessenger(
connect(FULL_OS_SOCKET_PATH)
connect(getFullOsSocketPath())
).listen(
(message) => this.handleMessage(message),
() => {
Expand Down
6 changes: 3 additions & 3 deletions packages/nx/src/daemon/server/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { setupWorkspaceContext } from '../../utils/workspace-context';
import { workspaceRoot } from '../../utils/workspace-root';
import { writeDaemonJsonProcessCache } from '../cache';
import {
FULL_OS_SOCKET_PATH,
getFullOsSocketPath,
isWindows,
killSocketOrPath,
} from '../socket-utils';
Expand Down Expand Up @@ -388,9 +388,9 @@ export async function startServer(): Promise<Server> {

return new Promise(async (resolve, reject) => {
try {
server.listen(FULL_OS_SOCKET_PATH, async () => {
server.listen(getFullOsSocketPath(), async () => {
try {
serverLogger.log(`Started listening on: ${FULL_OS_SOCKET_PATH}`);
serverLogger.log(`Started listening on: ${getFullOsSocketPath()}`);
// this triggers the storage of the lock file hash
daemonIsOutdated();

Expand Down
7 changes: 5 additions & 2 deletions packages/nx/src/daemon/server/watcher.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { workspaceRoot } from '../../utils/workspace-root';
import { dirname, relative } from 'path';
import { FULL_OS_SOCKET_PATH } from '../socket-utils';
import { getFullOsSocketPath } from '../socket-utils';
import { handleServerProcessTermination } from './shutdown-utils';
import { Server } from 'net';
import { normalizePath } from '../../utils/path';
Expand All @@ -13,7 +13,10 @@ import { platform } from 'os';
import { getDaemonProcessIdSync, serverProcessJsonPath } from '../cache';
import type { WatchEvent } from '../../native';

const ALWAYS_IGNORE = [...getAlwaysIgnore(workspaceRoot), FULL_OS_SOCKET_PATH];
const ALWAYS_IGNORE = [
...getAlwaysIgnore(workspaceRoot),
getFullOsSocketPath(),
];

export type FileWatcherCallback = (
err: Error | string | null,
Expand Down
15 changes: 8 additions & 7 deletions packages/nx/src/daemon/socket-utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { unlinkSync } from 'fs';
import { platform } from 'os';
import { join, resolve } from 'path';
import { DAEMON_SOCKET_PATH, socketDir } from './tmp-dir';
import { getDaemonSocketDir, getSocketDir } from './tmp-dir';
import { createSerializableError } from '../utils/serializable-error';

export const isWindows = platform() === 'win32';
Expand All @@ -12,18 +12,19 @@ export const isWindows = platform() === 'win32';
* See https://nodejs.org/dist/latest-v14.x/docs/api/net.html#net_identifying_paths_for_ipc_connections for a full breakdown
* of OS differences between Unix domain sockets and named pipes.
*/
export const FULL_OS_SOCKET_PATH = isWindows
? '\\\\.\\pipe\\nx\\' + resolve(DAEMON_SOCKET_PATH)
: resolve(DAEMON_SOCKET_PATH);
export const getFullOsSocketPath = () =>
isWindows
? '\\\\.\\pipe\\nx\\' + resolve(getDaemonSocketDir())
: resolve(getDaemonSocketDir());

export const FORKED_PROCESS_OS_SOCKET_PATH = (id: string) => {
let path = resolve(join(socketDir, 'fp' + id + '.sock'));
export const getForkedProcessOsSocketPath = (id: string) => {
let path = resolve(join(getSocketDir(), 'fp' + id + '.sock'));
return isWindows ? '\\\\.\\pipe\\nx\\' + resolve(path) : resolve(path);
};

export function killSocketOrPath(): void {
try {
unlinkSync(FULL_OS_SOCKET_PATH);
unlinkSync(getFullOsSocketPath());
} catch {}
}

Expand Down
17 changes: 8 additions & 9 deletions packages/nx/src/daemon/tmp-dir.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,12 @@ export const DAEMON_OUTPUT_LOG_FILE = join(
'daemon.log'
);

export const socketDir = createSocketDir();

export const DAEMON_SOCKET_PATH = join(
socketDir,
// As per notes above on socket/named pipe length limitations, we keep this intentionally short
'd.sock'
);
export const getDaemonSocketDir = () =>
join(
getSocketDir(),
// As per notes above on socket/named pipe length limitations, we keep this intentionally short
'd.sock'
);

export function writeDaemonLogs(error?: string) {
const file = join(DAEMON_DIR_FOR_CURRENT_WORKSPACE, 'daemon-error.log');
Expand Down Expand Up @@ -59,7 +58,7 @@ function socketDirName() {
* We try to create a socket file in a tmp dir, but if it doesn't work because
* for instance we don't have permissions, we create it in DAEMON_DIR_FOR_CURRENT_WORKSPACE
*/
function createSocketDir() {
export function getSocketDir() {
try {
const dir = process.env.NX_DAEMON_SOCKET_DIR ?? socketDirName();
ensureDirSync(dir);
Expand All @@ -71,6 +70,6 @@ function createSocketDir() {

export function removeSocketDir() {
try {
rmSync(socketDir, { recursive: true, force: true });
rmSync(getSocketDir(), { recursive: true, force: true });
} catch (e) {}
}
4 changes: 2 additions & 2 deletions packages/nx/src/tasks-runner/pseudo-terminal.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ChildProcess, RustPseudoTerminal } from '../native';
import { PseudoIPCServer } from './pseudo-ipc';
import { FORKED_PROCESS_OS_SOCKET_PATH } from '../daemon/socket-utils';
import { getForkedProcessOsSocketPath } from '../daemon/socket-utils';
import { Serializable } from 'child_process';
import * as os from 'os';

Expand All @@ -16,7 +16,7 @@ export function getPseudoTerminal(skipSupportCheck: boolean = false) {
}

export class PseudoTerminal {
private pseudoIPCPath = FORKED_PROCESS_OS_SOCKET_PATH(process.pid.toString());
private pseudoIPCPath = getForkedProcessOsSocketPath(process.pid.toString());
private pseudoIPC = new PseudoIPCServer(this.pseudoIPCPath);

private initialized: boolean = false;
Expand Down

0 comments on commit d75bab7

Please sign in to comment.