Skip to content

Commit

Permalink
Merge pull request #136 from gadget-inc/watcher
Browse files Browse the repository at this point in the history
Switch to watcher from chokidar for better performance
  • Loading branch information
airhorns authored Oct 9, 2024
2 parents 696c1ac + f16104f commit 1c1a5c5
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 65 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@
"dependencies": {
"@swc/core": "^1.7.28",
"@swc/helpers": "^0.5.13",
"chokidar": "^3.6.0",
"find-root": "^1.1.0",
"find-yarn-workspace-root": "^2.0.0",
"fs-extra": "^11.2.0",
"globby": "^11.1.0",
"lodash": "^4.17.20",
"oxc-resolver": "^1.12.0",
"pkg-dir": "^5.0.0",
"watcher": "^2.3.1",
"write-file-atomic": "^6.0.0",
"yargs": "^16.2.0"
},
Expand Down
86 changes: 36 additions & 50 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 24 additions & 0 deletions spec/PathTrie.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { describe, expect, it } from "vitest";
import { PathTrie } from "../src/PathTrie.js";

describe("PathTrie", () => {
it("should insert and search for paths", () => {
const trie = new PathTrie();
trie.insert("foo/bar");
expect(trie.contains("foo/bar")).toBe(true);
expect(trie.contains("foo/baz")).toBe(false);
});

it("should check if any paths in the trie start with a given prefix", () => {
const trie = new PathTrie();
trie.insert("foo/bar");
trie.insert("foo/baz");
trie.insert("foo/qux/corge");
expect(trie.anyStartsWith("foo")).toBe(true);
expect(trie.anyStartsWith("foo/bar")).toBe(true);
expect(trie.anyStartsWith("foo/corge")).toBe(false);
expect(trie.anyStartsWith("qux")).toBe(false);
expect(trie.anyStartsWith("foo/qux")).toBe(true);
expect(trie.anyStartsWith("foo/qux/corge")).toBe(true);
});
});
58 changes: 58 additions & 0 deletions src/PathTrie.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
class TrieNode {
children: Record<string, TrieNode> = {};
isEndOfWord = false;
}

/**
* Prefix matching datastructure for holding paths and seeing if any match a given incoming path
**/
export class PathTrie {
root = new TrieNode();
seen = new Set<string>();

insert(path: string) {
if (this.seen.has(path)) {
return;
}
let node = this.root;
const segments = path.split("/");
for (const segment of segments) {
if (!node.children[segment]) {
node.children[segment] = new TrieNode();
}
node = node.children[segment];
}
this.seen.add(path);
node.isEndOfWord = true;
}

/**
* Has the incoming path been inserted into the trie?
*/
contains(path: string) {
let node = this.root;
const segments = path.split("/");
for (const segment of segments) {
if (!node.children[segment]) {
return false;
}
node = node.children[segment];
}
return node.isEndOfWord;
}

/**
* Do any paths in the trie start with the given prefix?
*/
anyStartsWith(prefix: string) {
let node = this.root;
const segments = prefix.split("/");
for (const segment of segments) {
if (!node.children[segment]) {
return false;
}
node = node.children[segment];
}
return true;
}
}
19 changes: 13 additions & 6 deletions src/Project.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { FSWatcher } from "chokidar";
import _ from "lodash";
import type { Compiler } from "./Compiler.js";
import type { ProjectConfig } from "./Options.js";
import { PathTrie } from "./PathTrie.js";
import type { Supervisor } from "./Supervisor.js";
import { log } from "./utils.js";

Expand All @@ -15,7 +15,7 @@ export class Project {
cleanups: (() => void)[] = [];
currentBatch: ReloadBatch = { paths: [], invalidate: false };
supervisor!: Supervisor;
watcher?: FSWatcher;
watched = new PathTrie();

constructor(readonly workspaceRoot: string, readonly config: ProjectConfig, readonly compiler: Compiler) {}

Expand All @@ -24,10 +24,13 @@ export class Project {
}

enqueueReload(path: string, requiresInvalidation = false) {
this.compiler.invalidate(path);
this.currentBatch.paths.push(path);
this.currentBatch.invalidate = this.currentBatch.invalidate || requiresInvalidation;
this.debouncedReload();
log.debug({ path }, "watch event");
if (this.watched.contains(path)) {
this.compiler.invalidate(path);
this.currentBatch.paths.push(path);
this.currentBatch.invalidate = this.currentBatch.invalidate || requiresInvalidation;
this.debouncedReload();
}
}

debouncedReload = _.debounce(() => {
Expand Down Expand Up @@ -65,4 +68,8 @@ export class Project {
}
process.exit(code);
}

watchFile(path: string) {
this.watched.insert(path);
}
}
Loading

0 comments on commit 1c1a5c5

Please sign in to comment.