feat(graph): use daemon file watcher instead of chokidar (#13564)

This commit is contained in:
Phillip Barta 2023-01-11 15:35:47 +01:00 committed by GitHub
parent b0c6ca9267
commit b4dbdf60b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 35 additions and 39 deletions

View File

@ -38,7 +38,6 @@
"@zkochan/js-yaml": "0.0.6", "@zkochan/js-yaml": "0.0.6",
"axios": "^1.0.0", "axios": "^1.0.0",
"chalk": "4.1.0", "chalk": "4.1.0",
"chokidar": "^3.5.1",
"cli-cursor": "3.1.0", "cli-cursor": "3.1.0",
"cli-spinners": "2.6.1", "cli-spinners": "2.6.1",
"cliui": "^7.0.2", "cliui": "^7.0.2",

View File

@ -1,5 +1,4 @@
import { workspaceRoot } from '../utils/workspace-root'; import { workspaceRoot } from '../utils/workspace-root';
import { watch } from 'chokidar';
import { createHash } from 'crypto'; import { createHash } from 'crypto';
import { existsSync, readFileSync, statSync, writeFileSync } from 'fs'; import { existsSync, readFileSync, statSync, writeFileSync } from 'fs';
import { copySync, ensureDirSync } from 'fs-extra'; import { copySync, ensureDirSync } from 'fs-extra';
@ -13,7 +12,6 @@ import { readNxJson, workspaceLayout } from '../config/configuration';
import { defaultFileHasher } from '../hasher/file-hasher'; import { defaultFileHasher } from '../hasher/file-hasher';
import { output } from '../utils/output'; import { output } from '../utils/output';
import { writeJsonFile } from '../utils/fileutils'; import { writeJsonFile } from '../utils/fileutils';
import { joinPathFragments } from '../utils/path';
import { import {
ProjectGraph, ProjectGraph,
ProjectGraphDependency, ProjectGraphDependency,
@ -24,6 +22,7 @@ import { createProjectGraphAsync } from '../project-graph/project-graph';
import { createTaskGraph } from '../tasks-runner/create-task-graph'; import { createTaskGraph } from '../tasks-runner/create-task-graph';
import { TargetDefaults, TargetDependencies } from '../config/nx-json'; import { TargetDefaults, TargetDependencies } from '../config/nx-json';
import { TaskGraph } from '../config/task-graph'; import { TaskGraph } from '../config/task-graph';
import { daemonClient } from '../daemon/client/client';
export interface ProjectGraphClientResponse { export interface ProjectGraphClientResponse {
hash: string; hash: string;
@ -326,8 +325,9 @@ async function startServer(
exclude: string[] = [], exclude: string[] = [],
openBrowser: boolean = true openBrowser: boolean = true
) { ) {
let unregisterFileWatcher: (() => void) | undefined;
if (watchForchanges) { if (watchForchanges) {
startWatcher(); unregisterFileWatcher = await createFileWatcher();
} }
currentDepGraphClientResponse = await createDepGraphClientResponse(affected); currentDepGraphClientResponse = await createDepGraphClientResponse(affected);
@ -410,6 +410,15 @@ async function startServer(
open(`${url}?${params.toString()}`); open(`${url}?${params.toString()}`);
} }
const handleTermination = async (exitCode: number) => {
if (unregisterFileWatcher) {
unregisterFileWatcher();
}
process.exit(exitCode);
};
process.on('SIGINT', () => handleTermination(128 + 2));
process.on('SIGTERM', () => handleTermination(128 + 15));
} }
let currentDepGraphClientResponse: ProjectGraphClientResponse = { let currentDepGraphClientResponse: ProjectGraphClientResponse = {
@ -437,22 +446,6 @@ function getIgnoredGlobs(root: string) {
return ig; return ig;
} }
function startWatcher() {
createFileWatcher(workspaceRoot, async () => {
output.note({ title: 'Recalculating project graph...' });
const newGraphClientResponse = await createDepGraphClientResponse();
if (newGraphClientResponse.hash !== currentDepGraphClientResponse.hash) {
output.note({ title: 'Graph changes updated.' });
currentDepGraphClientResponse = newGraphClientResponse;
} else {
output.note({ title: 'No graph changes found.' });
}
});
}
function debounce(fn: (...args) => void, time: number) { function debounce(fn: (...args) => void, time: number) {
let timeout: NodeJS.Timeout; let timeout: NodeJS.Timeout;
@ -465,28 +458,32 @@ function debounce(fn: (...args) => void, time: number) {
}; };
} }
function createFileWatcher(root: string, changeHandler: () => Promise<void>) { function createFileWatcher() {
const ignoredGlobs = getIgnoredGlobs(root); return daemonClient.registerFileWatcher(
const layout = workspaceLayout(); { watchProjects: 'all', includeGlobalWorkspaceFiles: true },
debounce(async (error, { changedFiles }) => {
if (error === 'closed') {
output.error({ title: `Watch error: Daemon closed the connection` });
process.exit(1);
} else if (error) {
output.error({ title: `Watch error: ${error?.message ?? 'Unknown'}` });
} else if (changedFiles.length > 0) {
output.note({ title: 'Recalculating project graph...' });
const watcher = watch( const newGraphClientResponse = await createDepGraphClientResponse();
[
joinPathFragments(layout.appsDir, '**'), if (
joinPathFragments(layout.libsDir, '**'), newGraphClientResponse.hash !== currentDepGraphClientResponse.hash
], ) {
{ output.note({ title: 'Graph changes updated.' });
cwd: root,
ignoreInitial: true, currentDepGraphClientResponse = newGraphClientResponse;
} } else {
); output.note({ title: 'No graph changes found.' });
watcher.on( }
'all', }
debounce(async (event: string, path: string) => {
if (ignoredGlobs.ignores(path)) return;
await changeHandler();
}, 500) }, 500)
); );
return { close: () => watcher.close() };
} }
async function createDepGraphClientResponse( async function createDepGraphClientResponse(