Skip to content

Commit

Permalink
feat(core): remove parcel/watcher (#19751)
Browse files Browse the repository at this point in the history
  • Loading branch information
Cammisuli authored Oct 20, 2023
1 parent 3942332 commit f19d1db
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 310 deletions.
1 change: 0 additions & 1 deletion packages/nx/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
},
"homepage": "https://nx.dev",
"dependencies": {
"@parcel/watcher": "2.0.4",
"@yarnpkg/lockfile": "^1.1.0",
"@yarnpkg/parsers": "3.0.0-rc.46",
"@zkochan/js-yaml": "0.0.6",
Expand Down
6 changes: 0 additions & 6 deletions packages/nx/src/daemon/client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -366,12 +366,6 @@ export class DaemonClient {
this._out = await open(DAEMON_OUTPUT_LOG_FILE, 'a');
this._err = await open(DAEMON_OUTPUT_LOG_FILE, 'a');

if (this.nxJson.tasksRunnerOptions?.default?.options?.useParcelWatcher) {
DAEMON_ENV_SETTINGS['NX_NATIVE_WATCHER'] = 'false';
} else {
DAEMON_ENV_SETTINGS['NX_NATIVE_WATCHER'] = 'true';
}

const backgroundProcess = spawn(
process.execPath,
[join(__dirname, '../server/start.js')],
Expand Down
15 changes: 11 additions & 4 deletions packages/nx/src/daemon/server/outputs-tracking.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { EventType } from '../../native';
import {
_outputsHashesMatch,
_recordOutputsHash,
Expand All @@ -19,7 +20,7 @@ describe('outputs tracking', () => {
it('should invalidate output when it is exact match', () => {
_recordOutputsHash(['dist/app/app1'], '123');
processFileChangesInOutputs(
[{ path: 'dist/app/app1', type: 'update' }],
[{ path: 'dist/app/app1', type: EventType.update }],
now
);
expect(recordedHash('dist/app/app1')).toBeUndefined();
Expand All @@ -28,21 +29,27 @@ describe('outputs tracking', () => {
it('should invalidate output when it is a child', () => {
_recordOutputsHash(['dist/app/app1'], '123');
processFileChangesInOutputs(
[{ path: 'dist/app/app1/child', type: 'update' }],
[{ path: 'dist/app/app1/child', type: EventType.update }],
now
);
expect(recordedHash('dist/app/app1')).toBeUndefined();
});

it('should invalidate output when it is a parent', () => {
_recordOutputsHash(['dist/app/app1'], '123');
processFileChangesInOutputs([{ path: 'dist/app', type: 'update' }], now);
processFileChangesInOutputs(
[{ path: 'dist/app', type: EventType.update }],
now
);
expect(recordedHash('dist/app/app1')).toBeUndefined();
});

it('should not invalidate anything when no match', () => {
_recordOutputsHash(['dist/app/app1'], '123');
processFileChangesInOutputs([{ path: 'dist/app2', type: 'update' }], now);
processFileChangesInOutputs(
[{ path: 'dist/app2', type: EventType.update }],
now
);
expect(recordedHash('dist/app/app1')).toEqual('123');
});
});
10 changes: 4 additions & 6 deletions packages/nx/src/daemon/server/outputs-tracking.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { lstat } from 'fs-extra';
import { dirname, join } from 'path';
import { workspaceRoot } from '../../utils/workspace-root';
import { dirname } from 'path';
import { WatchEvent, getFilesForOutputs } from '../../native';
import { collapseExpandedOutputs } from '../../utils/collapse-expanded-outputs';
import type { Event } from '@parcel/watcher';
import { getFilesForOutputs } from '../../native';
import { workspaceRoot } from '../../utils/workspace-root';

let disabled = false;

Expand Down Expand Up @@ -66,7 +64,7 @@ async function normalizeOutputs(outputs: string[]) {
}

export function processFileChangesInOutputs(
changeEvents: Event[],
changeEvents: WatchEvent[],
now: number = undefined
) {
if (!now) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,37 +140,10 @@ function computeWorkspaceConfigHash(
return hashArray(projectConfigurationStrings);
}

/**
* Temporary work around to handle nested gitignores. The parcel file watcher doesn't handle them well,
* so we need to filter them out here.
*
* TODO(Cammisuli): remove after 16.4 - Rust watcher handles nested gitignores
*/
function filterUpdatedFiles(files: string[]) {
if (files.length === 0 || process.env.NX_NATIVE_WATCHER === 'true') {
return files;
}

try {
const quoted = files.map((f) => '"' + f + '"');
const ignored = execSync(`git check-ignore ${quoted.join(' ')}`, {
windowsHide: true,
})
.toString()
.split('\n');
return files.filter((f) => ignored.indexOf(f) === -1);
} catch (e) {
// none of the files were ignored
return files;
}
}

async function processCollectedUpdatedAndDeletedFiles() {
try {
performance.mark('hash-watched-changes-start');
const updatedFiles = filterUpdatedFiles([
...collectedUpdatedFiles.values(),
]);
const updatedFiles = [...collectedUpdatedFiles.values()];
const deletedFiles = [...collectedDeletedFiles.values()];
let updatedFileHashes = updateFilesInContext(updatedFiles, deletedFiles);
performance.mark('hash-watched-changes-end');
Expand Down
139 changes: 41 additions & 98 deletions packages/nx/src/daemon/server/server.ts
Original file line number Diff line number Diff line change
@@ -1,65 +1,57 @@
import { workspaceRoot } from '../../utils/workspace-root';
import { existsSync, statSync } from 'fs';
import { createServer, Server, Socket } from 'net';
import { join } from 'path';
import { PerformanceObserver } from 'perf_hooks';
import { hashArray } from '../../hasher/file-hasher';
import { hashFile } from '../../native';
import { consumeMessagesFromSocket } from '../../utils/consume-messages-from-socket';
import { readJsonFile } from '../../utils/fileutils';
import { PackageJson } from '../../utils/package-json';
import { nxVersion } from '../../utils/versions';
import { setupWorkspaceContext } from '../../utils/workspace-context';
import { workspaceRoot } from '../../utils/workspace-root';
import { writeDaemonJsonProcessCache } from '../cache';
import {
FULL_OS_SOCKET_PATH,
isWindows,
killSocketOrPath,
} from '../socket-utils';
import {
registeredFileWatcherSockets,
removeRegisteredFileWatcherSocket,
} from './file-watching/file-watcher-sockets';
import { handleHashTasks } from './handle-hash-tasks';
import {
handleOutputsHashesMatch,
handleRecordOutputsHash,
} from './handle-outputs-tracking';
import { handleProcessInBackground } from './handle-process-in-background';
import { handleRequestFileData } from './handle-request-file-data';
import { handleRequestProjectGraph } from './handle-request-project-graph';
import { handleRequestShutdown } from './handle-request-shutdown';
import { serverLogger } from './logger';
import {
getOutputsWatcherSubscription,
disableOutputsTracking,
processFileChangesInOutputs,
} from './outputs-tracking';
import { addUpdatedAndDeletedFiles } from './project-graph-incremental-recomputation';
import {
getOutputWatcherInstance,
getSourceWatcherSubscription,
getWatcherInstance,
handleServerProcessTermination,
resetInactivityTimeout,
respondToClient,
respondWithErrorAndExit,
SERVER_INACTIVITY_TIMEOUT_MS,
storeOutputsWatcherSubscription,
storeOutputWatcherInstance,
storeProcessJsonSubscription,
storeSourceWatcherSubscription,
storeWatcherInstance,
} from './shutdown-utils';
import {
convertChangeEventsToLogMessage,
subscribeToOutputsChanges,
subscribeToWorkspaceChanges,
FileWatcherCallback,
subscribeToServerProcessJsonChanges,
watchWorkspace,
watchOutputFiles,
watchWorkspace,
} from './watcher';
import { addUpdatedAndDeletedFiles } from './project-graph-incremental-recomputation';
import { existsSync, statSync } from 'fs';
import { handleRequestProjectGraph } from './handle-request-project-graph';
import { handleProcessInBackground } from './handle-process-in-background';
import {
handleOutputsHashesMatch,
handleRecordOutputsHash,
} from './handle-outputs-tracking';
import { consumeMessagesFromSocket } from '../../utils/consume-messages-from-socket';
import {
disableOutputsTracking,
processFileChangesInOutputs,
} from './outputs-tracking';
import { handleRequestShutdown } from './handle-request-shutdown';
import {
registeredFileWatcherSockets,
removeRegisteredFileWatcherSocket,
} from './file-watching/file-watcher-sockets';
import { nxVersion } from '../../utils/versions';
import { readJsonFile } from '../../utils/fileutils';
import { PackageJson } from '../../utils/package-json';
import { getDaemonProcessIdSync, writeDaemonJsonProcessCache } from '../cache';
import { handleHashTasks } from './handle-hash-tasks';
import { hashArray } from '../../hasher/file-hasher';
import { handleRequestFileData } from './handle-request-file-data';
import { setupWorkspaceContext } from '../../utils/workspace-context';
import { hashFile } from '../../native';

let performanceObserver: PerformanceObserver | undefined;
let workspaceWatcherError: Error | undefined;
Expand Down Expand Up @@ -109,7 +101,6 @@ const server = createServer(async (socket) => {
});
});
registerProcessTerminationListeners();
registerProcessServerJsonTracking();

async function handleMessage(socket, data: string) {
if (workspaceWatcherError) {
Expand Down Expand Up @@ -239,23 +230,6 @@ function registerProcessTerminationListeners() {
);
}

async function registerProcessServerJsonTracking() {
if (useNativeWatcher()) {
return;
}

storeProcessJsonSubscription(
await subscribeToServerProcessJsonChanges(async () => {
if (getDaemonProcessIdSync() !== process.pid) {
await handleServerProcessTermination({
server,
reason: 'this process is no longer the current daemon',
});
}
})
);
}

let existingLockHash: string | undefined;

function daemonIsOutdated(): boolean {
Expand Down Expand Up @@ -419,46 +393,20 @@ export async function startServer(): Promise<Server> {
// this triggers the storage of the lock file hash
daemonIsOutdated();

if (useNativeWatcher()) {
if (!getWatcherInstance()) {
storeWatcherInstance(
await watchWorkspace(server, handleWorkspaceChanges)
);
if (!getWatcherInstance()) {
storeWatcherInstance(
await watchWorkspace(server, handleWorkspaceChanges)
);

serverLogger.watcherLog(
`Subscribed to changes within: ${workspaceRoot} (native)`
);
}

if (!getOutputWatcherInstance()) {
storeOutputWatcherInstance(
await watchOutputFiles(handleOutputsChanges)
);
}
} else {
if (!getSourceWatcherSubscription()) {
storeSourceWatcherSubscription(
await subscribeToWorkspaceChanges(
server,
handleWorkspaceChanges
)
);
serverLogger.watcherLog(
`Subscribed to changes within: ${workspaceRoot}`
);
}
serverLogger.watcherLog(
`Subscribed to changes within: ${workspaceRoot} (native)`
);
}

// temporary disable outputs tracking on linux
const outputsTrackingIsEnabled = process.platform != 'linux';
if (outputsTrackingIsEnabled) {
if (!getOutputsWatcherSubscription()) {
storeOutputsWatcherSubscription(
await subscribeToOutputsChanges(handleOutputsChanges)
);
}
} else {
disableOutputsTracking();
}
if (!getOutputWatcherInstance()) {
storeOutputWatcherInstance(
await watchOutputFiles(handleOutputsChanges)
);
}

return resolve(server);
Expand All @@ -471,8 +419,3 @@ export async function startServer(): Promise<Server> {
}
});
}

// TODO(cammisuli): remove with nx 16.6 (only our watcher will be supported)
function useNativeWatcher() {
return process.env.NX_NATIVE_WATCHER === 'true';
}
44 changes: 0 additions & 44 deletions packages/nx/src/daemon/server/shutdown-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,11 @@ import { workspaceRoot } from '../../utils/workspace-root';
import type { Server, Socket } from 'net';
import { serverLogger } from './logger';
import { serializeResult } from '../socket-utils';
import type { AsyncSubscription } from '@parcel/watcher';
import { deleteDaemonJsonProcessCache } from '../cache';
import type { Watcher } from '../../native';

export const SERVER_INACTIVITY_TIMEOUT_MS = 10800000 as const; // 10800000 ms = 3 hours

let sourceWatcherSubscription: AsyncSubscription | undefined;
let outputsWatcherSubscription: AsyncSubscription | undefined;

export function getSourceWatcherSubscription() {
return sourceWatcherSubscription;
}

export function storeSourceWatcherSubscription(s: AsyncSubscription) {
sourceWatcherSubscription = s;
}

export function getOutputsWatcherSubscription() {
return outputsWatcherSubscription;
}

export function storeOutputsWatcherSubscription(s: AsyncSubscription) {
outputsWatcherSubscription = s;
}

let processJsonSubscription: AsyncSubscription | undefined;

export function storeProcessJsonSubscription(s: AsyncSubscription) {
processJsonSubscription = s;
}

let watcherInstance: Watcher | undefined;
export function storeWatcherInstance(instance: Watcher) {
watcherInstance = instance;
Expand Down Expand Up @@ -61,24 +35,6 @@ export async function handleServerProcessTermination({
try {
server.close();
deleteDaemonJsonProcessCache();
if (sourceWatcherSubscription) {
await sourceWatcherSubscription.unsubscribe();
serverLogger.watcherLog(
`Unsubscribed from changes within: ${workspaceRoot} (sources)`
);
}
if (outputsWatcherSubscription) {
await outputsWatcherSubscription.unsubscribe();
serverLogger.watcherLog(
`Unsubscribed from changes within: ${workspaceRoot} (outputs)`
);
}
if (processJsonSubscription) {
await processJsonSubscription.unsubscribe();
serverLogger.watcherLog(
`Unsubscribed from changes within: ${workspaceRoot} (server-process.json)`
);
}

if (watcherInstance) {
await watcherInstance.stop();
Expand Down
Loading

0 comments on commit f19d1db

Please sign in to comment.