@optave/codegraph 3.9.3 → 3.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -10
- package/dist/ast-analysis/visitor.d.ts.map +1 -1
- package/dist/ast-analysis/visitor.js +14 -0
- package/dist/ast-analysis/visitor.js.map +1 -1
- package/dist/cli/commands/watch.d.ts.map +1 -1
- package/dist/cli/commands/watch.js +2 -0
- package/dist/cli/commands/watch.js.map +1 -1
- package/dist/cli.js +24 -1
- package/dist/cli.js.map +1 -1
- package/dist/domain/graph/builder/context.d.ts +17 -0
- package/dist/domain/graph/builder/context.d.ts.map +1 -1
- package/dist/domain/graph/builder/context.js +7 -0
- package/dist/domain/graph/builder/context.js.map +1 -1
- package/dist/domain/graph/builder/helpers.d.ts +13 -2
- package/dist/domain/graph/builder/helpers.d.ts.map +1 -1
- package/dist/domain/graph/builder/helpers.js +30 -4
- package/dist/domain/graph/builder/helpers.js.map +1 -1
- package/dist/domain/graph/builder/pipeline.d.ts.map +1 -1
- package/dist/domain/graph/builder/pipeline.js +221 -51
- package/dist/domain/graph/builder/pipeline.js.map +1 -1
- package/dist/domain/graph/builder/stages/build-edges.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/build-edges.js +67 -6
- package/dist/domain/graph/builder/stages/build-edges.js.map +1 -1
- package/dist/domain/graph/builder/stages/build-structure.js +2 -2
- package/dist/domain/graph/builder/stages/collect-files.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/collect-files.js +58 -26
- package/dist/domain/graph/builder/stages/collect-files.js.map +1 -1
- package/dist/domain/graph/builder/stages/detect-changes.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/detect-changes.js +105 -55
- package/dist/domain/graph/builder/stages/detect-changes.js.map +1 -1
- package/dist/domain/graph/builder/stages/finalize.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/finalize.js +27 -4
- package/dist/domain/graph/builder/stages/finalize.js.map +1 -1
- package/dist/domain/graph/builder/stages/run-analyses.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/run-analyses.js +5 -20
- package/dist/domain/graph/builder/stages/run-analyses.js.map +1 -1
- package/dist/domain/graph/journal.d.ts +15 -0
- package/dist/domain/graph/journal.d.ts.map +1 -1
- package/dist/domain/graph/journal.js +283 -28
- package/dist/domain/graph/journal.js.map +1 -1
- package/dist/domain/graph/watcher.d.ts +17 -0
- package/dist/domain/graph/watcher.d.ts.map +1 -1
- package/dist/domain/graph/watcher.js +23 -7
- package/dist/domain/graph/watcher.js.map +1 -1
- package/dist/domain/parser.d.ts +13 -4
- package/dist/domain/parser.d.ts.map +1 -1
- package/dist/domain/parser.js +174 -80
- package/dist/domain/parser.js.map +1 -1
- package/dist/domain/search/generator.d.ts.map +1 -1
- package/dist/domain/search/generator.js +28 -2
- package/dist/domain/search/generator.js.map +1 -1
- package/dist/domain/wasm-worker-entry.d.ts +24 -0
- package/dist/domain/wasm-worker-entry.d.ts.map +1 -0
- package/dist/domain/wasm-worker-entry.js +643 -0
- package/dist/domain/wasm-worker-entry.js.map +1 -0
- package/dist/domain/wasm-worker-pool.d.ts +59 -0
- package/dist/domain/wasm-worker-pool.d.ts.map +1 -0
- package/dist/domain/wasm-worker-pool.js +312 -0
- package/dist/domain/wasm-worker-pool.js.map +1 -0
- package/dist/domain/wasm-worker-protocol.d.ts +65 -0
- package/dist/domain/wasm-worker-protocol.d.ts.map +1 -0
- package/dist/domain/wasm-worker-protocol.js +13 -0
- package/dist/domain/wasm-worker-protocol.js.map +1 -0
- package/dist/extractors/javascript.js +265 -1
- package/dist/extractors/javascript.js.map +1 -1
- package/dist/features/boundaries.d.ts +2 -2
- package/dist/features/boundaries.d.ts.map +1 -1
- package/dist/features/boundaries.js +2 -31
- package/dist/features/boundaries.js.map +1 -1
- package/dist/features/snapshot.d.ts.map +1 -1
- package/dist/features/snapshot.js +99 -13
- package/dist/features/snapshot.js.map +1 -1
- package/dist/features/structure.d.ts.map +1 -1
- package/dist/features/structure.js +14 -1
- package/dist/features/structure.js.map +1 -1
- package/dist/graph/algorithms/louvain.d.ts.map +1 -1
- package/dist/graph/algorithms/louvain.js +2 -4
- package/dist/graph/algorithms/louvain.js.map +1 -1
- package/dist/infrastructure/config.d.ts.map +1 -1
- package/dist/infrastructure/config.js +12 -2
- package/dist/infrastructure/config.js.map +1 -1
- package/dist/shared/globs.d.ts +40 -0
- package/dist/shared/globs.d.ts.map +1 -0
- package/dist/shared/globs.js +126 -0
- package/dist/shared/globs.js.map +1 -0
- package/dist/types.d.ts +26 -1
- package/dist/types.d.ts.map +1 -1
- package/grammars/tree-sitter-c_sharp.wasm +0 -0
- package/package.json +7 -7
- package/src/ast-analysis/visitor.ts +15 -0
- package/src/cli/commands/watch.ts +2 -0
- package/src/cli.ts +31 -8
- package/src/domain/graph/builder/context.ts +19 -0
- package/src/domain/graph/builder/helpers.ts +53 -3
- package/src/domain/graph/builder/pipeline.ts +235 -49
- package/src/domain/graph/builder/stages/build-edges.ts +80 -6
- package/src/domain/graph/builder/stages/build-structure.ts +2 -2
- package/src/domain/graph/builder/stages/collect-files.ts +56 -26
- package/src/domain/graph/builder/stages/detect-changes.ts +118 -61
- package/src/domain/graph/builder/stages/finalize.ts +27 -4
- package/src/domain/graph/builder/stages/run-analyses.ts +5 -26
- package/src/domain/graph/journal.ts +284 -27
- package/src/domain/graph/watcher.ts +29 -9
- package/src/domain/parser.ts +166 -73
- package/src/domain/search/generator.ts +34 -2
- package/src/domain/wasm-worker-entry.ts +788 -0
- package/src/domain/wasm-worker-pool.ts +330 -0
- package/src/domain/wasm-worker-protocol.ts +81 -0
- package/src/extractors/javascript.ts +290 -1
- package/src/features/boundaries.ts +2 -27
- package/src/features/snapshot.ts +93 -14
- package/src/features/structure.ts +17 -1
- package/src/graph/algorithms/louvain.ts +2 -4
- package/src/infrastructure/config.ts +12 -2
- package/src/shared/globs.ts +121 -0
- package/src/types.ts +26 -1
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* WASM cleanup, stats logging, drift detection, build metadata, registry, journal.
|
|
5
5
|
*/
|
|
6
|
+
import fs from 'node:fs';
|
|
6
7
|
import { tmpdir } from 'node:os';
|
|
7
8
|
import path from 'node:path';
|
|
8
9
|
import { performance } from 'node:perf_hooks';
|
|
@@ -62,27 +63,49 @@ function persistBuildMetadata(ctx, nodeCount, actualEdgeCount, buildNow) {
|
|
|
62
63
|
const useNativeDb = ctx.engineName === 'native' && !!ctx.nativeDb;
|
|
63
64
|
if (!ctx.isFullBuild && ctx.allSymbols.size <= 3)
|
|
64
65
|
return;
|
|
66
|
+
// When the native engine is active, persist the Rust addon version so that
|
|
67
|
+
// checkEngineSchemaMismatch compares against the same value on the next build.
|
|
68
|
+
// Writing CODEGRAPH_VERSION (the npm package version) here would create a
|
|
69
|
+
// permanent mismatch whenever npm and crate versions diverge, forcing every
|
|
70
|
+
// subsequent build to be a full rebuild.
|
|
71
|
+
const codeVersionToWrite = ctx.engineName === 'native' && ctx.engineVersion ? ctx.engineVersion : CODEGRAPH_VERSION;
|
|
72
|
+
// Persist the repo root so downstream commands (e.g. `codegraph embed`)
|
|
73
|
+
// can resolve relative file paths regardless of the invoking cwd.
|
|
74
|
+
// Use realpathSync (symlink-resolving) to match the Rust engine's
|
|
75
|
+
// std::fs::canonicalize — otherwise the JS write here would overwrite the
|
|
76
|
+
// canonical path Rust wrote for native full builds and could re-introduce
|
|
77
|
+
// a non-canonical path when the project root is behind a symlink.
|
|
78
|
+
const resolvedRootDir = path.resolve(ctx.rootDir);
|
|
79
|
+
let rootDirToWrite = resolvedRootDir;
|
|
80
|
+
try {
|
|
81
|
+
rootDirToWrite = fs.realpathSync(resolvedRootDir);
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
/* realpath can fail (e.g. path no longer exists); fall back to resolve() */
|
|
85
|
+
}
|
|
65
86
|
try {
|
|
66
87
|
if (useNativeDb) {
|
|
67
88
|
ctx.nativeDb.setBuildMeta(Object.entries({
|
|
68
89
|
engine: ctx.engineName,
|
|
69
|
-
engine_version:
|
|
70
|
-
codegraph_version:
|
|
90
|
+
engine_version: codeVersionToWrite,
|
|
91
|
+
codegraph_version: codeVersionToWrite,
|
|
71
92
|
schema_version: String(ctx.schemaVersion),
|
|
72
93
|
built_at: buildNow.toISOString(),
|
|
73
94
|
node_count: String(nodeCount),
|
|
74
95
|
edge_count: String(actualEdgeCount),
|
|
96
|
+
root_dir: rootDirToWrite,
|
|
75
97
|
}).map(([key, value]) => ({ key, value: String(value) })));
|
|
76
98
|
}
|
|
77
99
|
else {
|
|
78
100
|
setBuildMeta(ctx.db, {
|
|
79
101
|
engine: ctx.engineName,
|
|
80
|
-
engine_version:
|
|
81
|
-
codegraph_version:
|
|
102
|
+
engine_version: codeVersionToWrite,
|
|
103
|
+
codegraph_version: codeVersionToWrite,
|
|
82
104
|
schema_version: String(ctx.schemaVersion),
|
|
83
105
|
built_at: buildNow.toISOString(),
|
|
84
106
|
node_count: nodeCount,
|
|
85
107
|
edge_count: actualEdgeCount,
|
|
108
|
+
root_dir: rootDirToWrite,
|
|
86
109
|
});
|
|
87
110
|
}
|
|
88
111
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"finalize.js","sourceRoot":"","sources":["../../../../../src/domain/graph/builder/stages/finalize.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"finalize.js","sourceRoot":"","sources":["../../../../../src/domain/graph/builder/stages/finalize.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-analyses.d.ts","sourceRoot":"","sources":["../../../../../src/domain/graph/builder/stages/run-analyses.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,wBAAsB,WAAW,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"run-analyses.d.ts","sourceRoot":"","sources":["../../../../../src/domain/graph/builder/stages/run-analyses.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,wBAAsB,WAAW,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAerE"}
|
|
@@ -2,30 +2,15 @@
|
|
|
2
2
|
* Stage: runAnalyses
|
|
3
3
|
*
|
|
4
4
|
* Dispatches to the unified AST analysis engine (AST nodes, complexity, CFG, dataflow).
|
|
5
|
-
*
|
|
5
|
+
* Reverse-dep files are no longer in allSymbols (they are not reparsed since #932/#933),
|
|
6
|
+
* so no filtering is needed here.
|
|
6
7
|
*/
|
|
7
|
-
import {
|
|
8
|
+
import { warn } from '../../../../infrastructure/logger.js';
|
|
8
9
|
export async function runAnalyses(ctx) {
|
|
9
|
-
const { db, allSymbols, rootDir, opts, engineOpts
|
|
10
|
-
// For incremental builds, exclude reverse-dep-only files
|
|
11
|
-
let astComplexitySymbols = allSymbols;
|
|
12
|
-
if (!isFullBuild) {
|
|
13
|
-
const reverseDepFiles = new Set(filesToParse
|
|
14
|
-
.filter((item) => item._reverseDepOnly)
|
|
15
|
-
.map((item) => item.relPath));
|
|
16
|
-
if (reverseDepFiles.size > 0) {
|
|
17
|
-
astComplexitySymbols = new Map();
|
|
18
|
-
for (const [relPath, symbols] of allSymbols) {
|
|
19
|
-
if (!reverseDepFiles.has(relPath)) {
|
|
20
|
-
astComplexitySymbols.set(relPath, symbols);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
debug(`AST/complexity/CFG/dataflow: processing ${astComplexitySymbols.size} changed files (skipping ${reverseDepFiles.size} reverse-deps)`);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
10
|
+
const { db, allSymbols, rootDir, opts, engineOpts } = ctx;
|
|
26
11
|
const { runAnalyses: runAnalysesFn } = await import('../../../../ast-analysis/engine.js');
|
|
27
12
|
try {
|
|
28
|
-
const analysisTiming = await runAnalysesFn(db,
|
|
13
|
+
const analysisTiming = await runAnalysesFn(db, allSymbols, rootDir, opts, engineOpts);
|
|
29
14
|
ctx.timing.astMs = analysisTiming.astMs;
|
|
30
15
|
ctx.timing.complexityMs = analysisTiming.complexityMs;
|
|
31
16
|
ctx.timing.cfgMs = analysisTiming.cfgMs;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-analyses.js","sourceRoot":"","sources":["../../../../../src/domain/graph/builder/stages/run-analyses.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"run-analyses.js","sourceRoot":"","sources":["../../../../../src/domain/graph/builder/stages/run-analyses.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,sCAAsC,CAAC;AAG5D,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAoB;IACpD,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,GAAG,CAAC;IAE1D,MAAM,EAAE,WAAW,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,oCAAoC,CAAC,CAAC;IAC1F,IAAI,CAAC;QACH,MAAM,cAAc,GAAG,MAAM,aAAa,CAAC,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;QACtF,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC;QACxC,GAAG,CAAC,MAAM,CAAC,YAAY,GAAG,cAAc,CAAC,YAAY,CAAC;QACtD,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC;QACxC,GAAG,CAAC,MAAM,CAAC,UAAU,GAAG,cAAc,CAAC,UAAU,CAAC;IACpD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CACF,2EAA4E,GAAa,CAAC,OAAO,EAAE,CACpG,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -11,5 +11,20 @@ export declare function appendJournalEntries(rootDir: string, entries: Array<{
|
|
|
11
11
|
deleted?: boolean;
|
|
12
12
|
}>): void;
|
|
13
13
|
export declare function writeJournalHeader(rootDir: string, timestamp: number): void;
|
|
14
|
+
/**
|
|
15
|
+
* Atomically append entries while advancing the header timestamp.
|
|
16
|
+
*
|
|
17
|
+
* Used by the watcher: without this, the header timestamp stays frozen at the
|
|
18
|
+
* last build's finalize time while entries accumulate, so the next build's
|
|
19
|
+
* Tier 0 check sees `journal.timestamp < MAX(file_hashes.mtime)`, rejects the
|
|
20
|
+
* journal, and falls through to the expensive mtime+size / hash scan.
|
|
21
|
+
*
|
|
22
|
+
* Writes a tmp file then renames — a crash mid-rename leaves the previous
|
|
23
|
+
* journal state intact.
|
|
24
|
+
*/
|
|
25
|
+
export declare function appendJournalEntriesAndStampHeader(rootDir: string, entries: Array<{
|
|
26
|
+
file: string;
|
|
27
|
+
deleted?: boolean;
|
|
28
|
+
}>, timestamp: number): void;
|
|
14
29
|
export {};
|
|
15
30
|
//# sourceMappingURL=journal.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"journal.d.ts","sourceRoot":"","sources":["../../../src/domain/graph/journal.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"journal.d.ts","sourceRoot":"","sources":["../../../src/domain/graph/journal.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,gBAAgB,oBAAoB,CAAC;AAyNlD,UAAU,aAAa;IACrB,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CA6C1D;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,GAClD,IAAI,CAeN;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAiB3E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kCAAkC,CAChD,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,EACnD,SAAS,EAAE,MAAM,GAChB,IAAI,CA+BN"}
|
|
@@ -1,8 +1,222 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
1
2
|
import fs from 'node:fs';
|
|
2
3
|
import path from 'node:path';
|
|
3
4
|
import { debug, warn } from '../../infrastructure/logger.js';
|
|
4
5
|
export const JOURNAL_FILENAME = 'changes.journal';
|
|
5
6
|
const HEADER_PREFIX = '# codegraph-journal v1 ';
|
|
7
|
+
const LOCK_SUFFIX = '.lock';
|
|
8
|
+
const LOCK_TIMEOUT_MS = 5_000;
|
|
9
|
+
const LOCK_STALE_MS = 30_000;
|
|
10
|
+
const LOCK_RETRY_MS = 25;
|
|
11
|
+
// Busy-spin sleep avoids blocking the Node.js event loop (unlike Atomics.wait,
|
|
12
|
+
// which freezes all I/O and timer callbacks). The retry interval is short
|
|
13
|
+
// (25ms), so the CPU cost is negligible while keeping unrelated callbacks
|
|
14
|
+
// responsive in watcher processes.
|
|
15
|
+
function sleepSync(ms) {
|
|
16
|
+
const end = process.hrtime.bigint() + BigInt(ms) * 1000000n;
|
|
17
|
+
while (process.hrtime.bigint() < end) {
|
|
18
|
+
/* spin */
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function isPidAlive(pid) {
|
|
22
|
+
if (!Number.isFinite(pid) || pid <= 0)
|
|
23
|
+
return false;
|
|
24
|
+
try {
|
|
25
|
+
process.kill(pid, 0);
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
catch (e) {
|
|
29
|
+
// EPERM means the process exists but we lack permission — still alive.
|
|
30
|
+
return e.code === 'EPERM';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Steal a stale lockfile atomically via write-tmp + rename.
|
|
35
|
+
*
|
|
36
|
+
* Using rename (which is atomic on POSIX and Windows) avoids the TOCTOU race
|
|
37
|
+
* inherent to the unlink + openSync('wx') pattern: if two stealers both
|
|
38
|
+
* observed the same stale holder, one's unlink could cross the other's fresh
|
|
39
|
+
* acquisition, admitting two writers into the critical section.
|
|
40
|
+
*
|
|
41
|
+
* After rename, we re-read the lockfile to confirm our nonce — if another
|
|
42
|
+
* stealer's rename landed after ours, they own the lock and we retry.
|
|
43
|
+
*/
|
|
44
|
+
function trySteal(lockPath) {
|
|
45
|
+
const nonce = `${process.pid}-${crypto.randomBytes(8).toString('hex')}`;
|
|
46
|
+
const tmpPath = `${lockPath}.${nonce}.tmp`;
|
|
47
|
+
try {
|
|
48
|
+
fs.writeFileSync(tmpPath, `${process.pid}\n${nonce}\n`, { flag: 'w' });
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
// Atomic replace: overwrites the stale lockfile.
|
|
55
|
+
fs.renameSync(tmpPath, lockPath);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
try {
|
|
59
|
+
fs.unlinkSync(tmpPath);
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
/* ignore */
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
// Verify the nonce — another stealer's rename may have landed after ours.
|
|
67
|
+
let content;
|
|
68
|
+
try {
|
|
69
|
+
content = fs.readFileSync(lockPath, 'utf-8');
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
if (!content.includes(nonce)) {
|
|
75
|
+
// Lost the race to another stealer; do NOT unlink their live lockfile.
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
let fd;
|
|
79
|
+
try {
|
|
80
|
+
// Re-open r+ so we have a persistent fd the caller can close on release.
|
|
81
|
+
fd = fs.openSync(lockPath, 'r+');
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
return { fd, nonce };
|
|
87
|
+
}
|
|
88
|
+
function acquireJournalLock(lockPath) {
|
|
89
|
+
const start = Date.now();
|
|
90
|
+
for (;;) {
|
|
91
|
+
const nonce = `${process.pid}-${crypto.randomBytes(8).toString('hex')}`;
|
|
92
|
+
try {
|
|
93
|
+
const fd = fs.openSync(lockPath, 'wx');
|
|
94
|
+
try {
|
|
95
|
+
fs.writeSync(fd, `${process.pid}\n${nonce}\n`);
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
// Stamp write failed (ENOSPC, I/O error). An empty lockfile would
|
|
99
|
+
// look stale to concurrent waiters (Number('') === 0, isPidAlive(0)
|
|
100
|
+
// returns false), so they'd steal our live lock. Release and retry.
|
|
101
|
+
try {
|
|
102
|
+
fs.closeSync(fd);
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
/* ignore */
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
fs.unlinkSync(lockPath);
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
/* ignore */
|
|
112
|
+
}
|
|
113
|
+
if (Date.now() - start > LOCK_TIMEOUT_MS) {
|
|
114
|
+
throw new Error(`Failed to acquire journal lock at ${lockPath} within ${LOCK_TIMEOUT_MS}ms`);
|
|
115
|
+
}
|
|
116
|
+
sleepSync(LOCK_RETRY_MS);
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
return { fd, nonce };
|
|
120
|
+
}
|
|
121
|
+
catch (e) {
|
|
122
|
+
if (e.code !== 'EEXIST')
|
|
123
|
+
throw e;
|
|
124
|
+
}
|
|
125
|
+
let holderAlive = true;
|
|
126
|
+
try {
|
|
127
|
+
const pidContent = fs.readFileSync(lockPath, 'utf-8').split('\n')[0].trim();
|
|
128
|
+
holderAlive = isPidAlive(Number(pidContent));
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
/* unreadable — fall through to age check */
|
|
132
|
+
}
|
|
133
|
+
let shouldSteal = !holderAlive;
|
|
134
|
+
if (holderAlive) {
|
|
135
|
+
try {
|
|
136
|
+
const stat = fs.statSync(lockPath);
|
|
137
|
+
if (Date.now() - stat.mtimeMs > LOCK_STALE_MS) {
|
|
138
|
+
shouldSteal = true;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
/* stat failed — keep retrying */
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
if (shouldSteal) {
|
|
146
|
+
const stolen = trySteal(lockPath);
|
|
147
|
+
if (stolen)
|
|
148
|
+
return stolen;
|
|
149
|
+
// Steal failed or lost the race — fall through to timeout check & retry.
|
|
150
|
+
}
|
|
151
|
+
if (Date.now() - start > LOCK_TIMEOUT_MS) {
|
|
152
|
+
throw new Error(`Failed to acquire journal lock at ${lockPath} within ${LOCK_TIMEOUT_MS}ms`);
|
|
153
|
+
}
|
|
154
|
+
sleepSync(LOCK_RETRY_MS);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
function releaseJournalLock(lockPath, lock) {
|
|
158
|
+
try {
|
|
159
|
+
fs.closeSync(lock.fd);
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
/* ignore */
|
|
163
|
+
}
|
|
164
|
+
// Only unlink if the lockfile still carries our nonce — if another stealer
|
|
165
|
+
// decided we were stale and replaced it, we must not unlink their live lock.
|
|
166
|
+
try {
|
|
167
|
+
const content = fs.readFileSync(lockPath, 'utf-8');
|
|
168
|
+
if (content.includes(lock.nonce)) {
|
|
169
|
+
fs.unlinkSync(lockPath);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
/* lockfile gone or unreadable — nothing to unlink */
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
function sweepStaleTmpFiles(dir) {
|
|
177
|
+
// Clean up orphaned .tmp files left behind when a process is killed after
|
|
178
|
+
// writeFileSync(tmpPath, ...) succeeds but before renameSync(tmpPath, lockPath)
|
|
179
|
+
// completes (trySteal path). Without this, tmp files accumulate silently in
|
|
180
|
+
// .codegraph/ across crash cycles. Only sweep ones older than LOCK_STALE_MS
|
|
181
|
+
// so we don't race an in-flight steal on another process.
|
|
182
|
+
let entries;
|
|
183
|
+
try {
|
|
184
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
const now = Date.now();
|
|
190
|
+
const prefix = `${JOURNAL_FILENAME}${LOCK_SUFFIX}.`;
|
|
191
|
+
for (const entry of entries) {
|
|
192
|
+
if (!entry.isFile() || !entry.name.startsWith(prefix) || !entry.name.endsWith('.tmp')) {
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
const tmpPath = path.join(dir, entry.name);
|
|
196
|
+
try {
|
|
197
|
+
const stat = fs.statSync(tmpPath);
|
|
198
|
+
if (now - stat.mtimeMs > LOCK_STALE_MS) {
|
|
199
|
+
fs.unlinkSync(tmpPath);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
/* stat/unlink raced another cleaner or was already removed — ignore */
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function withJournalLock(rootDir, fn) {
|
|
208
|
+
const dir = path.join(rootDir, '.codegraph');
|
|
209
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
210
|
+
sweepStaleTmpFiles(dir);
|
|
211
|
+
const lockPath = path.join(dir, `${JOURNAL_FILENAME}${LOCK_SUFFIX}`);
|
|
212
|
+
const lock = acquireJournalLock(lockPath);
|
|
213
|
+
try {
|
|
214
|
+
return fn();
|
|
215
|
+
}
|
|
216
|
+
finally {
|
|
217
|
+
releaseJournalLock(lockPath, lock);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
6
220
|
export function readJournal(rootDir) {
|
|
7
221
|
const journalPath = path.join(rootDir, '.codegraph', JOURNAL_FILENAME);
|
|
8
222
|
let content;
|
|
@@ -47,40 +261,81 @@ export function readJournal(rootDir) {
|
|
|
47
261
|
return { valid: true, timestamp, changed, removed };
|
|
48
262
|
}
|
|
49
263
|
export function appendJournalEntries(rootDir, entries) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
return e.file;
|
|
264
|
+
withJournalLock(rootDir, () => {
|
|
265
|
+
const journalPath = path.join(rootDir, '.codegraph', JOURNAL_FILENAME);
|
|
266
|
+
if (!fs.existsSync(journalPath)) {
|
|
267
|
+
fs.writeFileSync(journalPath, `${HEADER_PREFIX}0\n`);
|
|
268
|
+
}
|
|
269
|
+
const lines = entries.map((e) => {
|
|
270
|
+
if (e.deleted)
|
|
271
|
+
return `DELETED ${e.file}`;
|
|
272
|
+
return e.file;
|
|
273
|
+
});
|
|
274
|
+
fs.appendFileSync(journalPath, `${lines.join('\n')}\n`);
|
|
62
275
|
});
|
|
63
|
-
fs.appendFileSync(journalPath, `${lines.join('\n')}\n`);
|
|
64
276
|
}
|
|
65
277
|
export function writeJournalHeader(rootDir, timestamp) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if (!fs.existsSync(dir)) {
|
|
70
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
71
|
-
}
|
|
72
|
-
try {
|
|
73
|
-
fs.writeFileSync(tmpPath, `${HEADER_PREFIX}${timestamp}\n`);
|
|
74
|
-
fs.renameSync(tmpPath, journalPath);
|
|
75
|
-
}
|
|
76
|
-
catch (err) {
|
|
77
|
-
warn(`Failed to write journal header: ${err.message}`);
|
|
278
|
+
withJournalLock(rootDir, () => {
|
|
279
|
+
const journalPath = path.join(rootDir, '.codegraph', JOURNAL_FILENAME);
|
|
280
|
+
const tmpPath = `${journalPath}.tmp`;
|
|
78
281
|
try {
|
|
79
|
-
fs.
|
|
282
|
+
fs.writeFileSync(tmpPath, `${HEADER_PREFIX}${timestamp}\n`);
|
|
283
|
+
fs.renameSync(tmpPath, journalPath);
|
|
284
|
+
}
|
|
285
|
+
catch (err) {
|
|
286
|
+
warn(`Failed to write journal header: ${err.message}`);
|
|
287
|
+
try {
|
|
288
|
+
fs.unlinkSync(tmpPath);
|
|
289
|
+
}
|
|
290
|
+
catch {
|
|
291
|
+
/* ignore */
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Atomically append entries while advancing the header timestamp.
|
|
298
|
+
*
|
|
299
|
+
* Used by the watcher: without this, the header timestamp stays frozen at the
|
|
300
|
+
* last build's finalize time while entries accumulate, so the next build's
|
|
301
|
+
* Tier 0 check sees `journal.timestamp < MAX(file_hashes.mtime)`, rejects the
|
|
302
|
+
* journal, and falls through to the expensive mtime+size / hash scan.
|
|
303
|
+
*
|
|
304
|
+
* Writes a tmp file then renames — a crash mid-rename leaves the previous
|
|
305
|
+
* journal state intact.
|
|
306
|
+
*/
|
|
307
|
+
export function appendJournalEntriesAndStampHeader(rootDir, entries, timestamp) {
|
|
308
|
+
withJournalLock(rootDir, () => {
|
|
309
|
+
const journalPath = path.join(rootDir, '.codegraph', JOURNAL_FILENAME);
|
|
310
|
+
const tmpPath = `${journalPath}.tmp`;
|
|
311
|
+
let existingBody = '';
|
|
312
|
+
try {
|
|
313
|
+
const content = fs.readFileSync(journalPath, 'utf-8');
|
|
314
|
+
const newlineIdx = content.indexOf('\n');
|
|
315
|
+
if (newlineIdx >= 0)
|
|
316
|
+
existingBody = content.slice(newlineIdx + 1);
|
|
80
317
|
}
|
|
81
318
|
catch {
|
|
82
|
-
/*
|
|
319
|
+
/* no existing journal — fall through to write header + new entries */
|
|
83
320
|
}
|
|
84
|
-
|
|
321
|
+
if (existingBody && !existingBody.endsWith('\n'))
|
|
322
|
+
existingBody = `${existingBody}\n`;
|
|
323
|
+
const newLines = entries.map((e) => (e.deleted ? `DELETED ${e.file}` : e.file));
|
|
324
|
+
const appended = newLines.length > 0 ? `${newLines.join('\n')}\n` : '';
|
|
325
|
+
const content = `${HEADER_PREFIX}${timestamp}\n${existingBody}${appended}`;
|
|
326
|
+
try {
|
|
327
|
+
fs.writeFileSync(tmpPath, content);
|
|
328
|
+
fs.renameSync(tmpPath, journalPath);
|
|
329
|
+
}
|
|
330
|
+
catch (err) {
|
|
331
|
+
warn(`Failed to update journal: ${err.message}`);
|
|
332
|
+
try {
|
|
333
|
+
fs.unlinkSync(tmpPath);
|
|
334
|
+
}
|
|
335
|
+
catch {
|
|
336
|
+
/* ignore */
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
});
|
|
85
340
|
}
|
|
86
341
|
//# sourceMappingURL=journal.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"journal.js","sourceRoot":"","sources":["../../../src/domain/graph/journal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,gCAAgC,CAAC;AAE7D,MAAM,CAAC,MAAM,gBAAgB,GAAG,iBAAiB,CAAC;AAClD,MAAM,aAAa,GAAG,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"journal.js","sourceRoot":"","sources":["../../../src/domain/graph/journal.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build journal entries for a pending-path set, detecting deletions by
|
|
3
|
+
* existence check.
|
|
4
|
+
*
|
|
5
|
+
* `ctx.pending` is an untyped `Set<string>` — it carries no event-type
|
|
6
|
+
* metadata. Without this check, a file deleted during the watch session
|
|
7
|
+
* would be journaled as "changed", causing the next incremental build to
|
|
8
|
+
* try to re-parse a non-existent file instead of removing it from the graph.
|
|
9
|
+
* Mirrors the deletion detection in `rebuildFile` (see builder/incremental.ts).
|
|
10
|
+
*
|
|
11
|
+
* Exported for unit-testing; prefer `setupShutdownHandler` in production paths.
|
|
12
|
+
*/
|
|
13
|
+
export declare function buildFlushEntriesFromPending(rootDir: string, pending: Iterable<string>): Array<{
|
|
14
|
+
file: string;
|
|
15
|
+
deleted: boolean;
|
|
16
|
+
}>;
|
|
1
17
|
export declare function watchProject(rootDir: string, opts?: {
|
|
2
18
|
engine?: string;
|
|
3
19
|
poll?: boolean;
|
|
4
20
|
pollInterval?: number;
|
|
21
|
+
dbPath?: string;
|
|
5
22
|
}): Promise<void>;
|
|
6
23
|
//# sourceMappingURL=watcher.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../../../src/domain/graph/watcher.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../../../src/domain/graph/watcher.ts"],"names":[],"mappings":"AAoRA;;;;;;;;;;;GAWG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,GACxB,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAK3C;AAqBD,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,EACf,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GACrF,OAAO,CAAC,IAAI,CAAC,CAYf"}
|
|
@@ -7,7 +7,7 @@ import { DbError } from '../../shared/errors.js';
|
|
|
7
7
|
import { createParseTreeCache, getActiveEngine } from '../parser.js';
|
|
8
8
|
import { rebuildFile } from './builder/incremental.js';
|
|
9
9
|
import { appendChangeEvents, buildChangeEvent, diffSymbols } from './change-journal.js';
|
|
10
|
-
import {
|
|
10
|
+
import { appendJournalEntriesAndStampHeader } from './journal.js';
|
|
11
11
|
function shouldIgnorePath(filePath) {
|
|
12
12
|
const parts = filePath.split(path.sep);
|
|
13
13
|
return parts.some((p) => shouldIgnore(p));
|
|
@@ -61,7 +61,7 @@ function writeJournalAndChangeEvents(rootDir, updates) {
|
|
|
61
61
|
deleted: r.deleted || false,
|
|
62
62
|
}));
|
|
63
63
|
try {
|
|
64
|
-
|
|
64
|
+
appendJournalEntriesAndStampHeader(rootDir, entries, Date.now());
|
|
65
65
|
}
|
|
66
66
|
catch (e) {
|
|
67
67
|
debug(`Journal write failed (non-fatal): ${e.message}`);
|
|
@@ -115,7 +115,7 @@ function collectTrackedFiles(dir, result) {
|
|
|
115
115
|
}
|
|
116
116
|
/** Initialize DB, engine, cache, and statements for watch mode. */
|
|
117
117
|
function setupWatcher(rootDir, opts) {
|
|
118
|
-
const dbPath = path.join(rootDir, '.codegraph', 'graph.db');
|
|
118
|
+
const dbPath = opts.dbPath ?? path.join(rootDir, '.codegraph', 'graph.db');
|
|
119
119
|
if (!fs.existsSync(dbPath)) {
|
|
120
120
|
throw new DbError('No graph.db found. Run `codegraph build` first.', { file: dbPath });
|
|
121
121
|
}
|
|
@@ -211,17 +211,33 @@ function startNativeWatcher(ctx) {
|
|
|
211
211
|
});
|
|
212
212
|
return () => watcher.close();
|
|
213
213
|
}
|
|
214
|
+
/**
|
|
215
|
+
* Build journal entries for a pending-path set, detecting deletions by
|
|
216
|
+
* existence check.
|
|
217
|
+
*
|
|
218
|
+
* `ctx.pending` is an untyped `Set<string>` — it carries no event-type
|
|
219
|
+
* metadata. Without this check, a file deleted during the watch session
|
|
220
|
+
* would be journaled as "changed", causing the next incremental build to
|
|
221
|
+
* try to re-parse a non-existent file instead of removing it from the graph.
|
|
222
|
+
* Mirrors the deletion detection in `rebuildFile` (see builder/incremental.ts).
|
|
223
|
+
*
|
|
224
|
+
* Exported for unit-testing; prefer `setupShutdownHandler` in production paths.
|
|
225
|
+
*/
|
|
226
|
+
export function buildFlushEntriesFromPending(rootDir, pending) {
|
|
227
|
+
return [...pending].map((filePath) => ({
|
|
228
|
+
file: normalizePath(path.relative(rootDir, filePath)),
|
|
229
|
+
deleted: !fs.existsSync(filePath),
|
|
230
|
+
}));
|
|
231
|
+
}
|
|
214
232
|
/** Register SIGINT handler to flush journal and clean up. */
|
|
215
233
|
function setupShutdownHandler(ctx, cleanup) {
|
|
216
234
|
process.once('SIGINT', () => {
|
|
217
235
|
info('Stopping watcher...');
|
|
218
236
|
cleanup();
|
|
219
237
|
if (ctx.pending.size > 0) {
|
|
220
|
-
const entries =
|
|
221
|
-
file: normalizePath(path.relative(ctx.rootDir, filePath)),
|
|
222
|
-
}));
|
|
238
|
+
const entries = buildFlushEntriesFromPending(ctx.rootDir, ctx.pending);
|
|
223
239
|
try {
|
|
224
|
-
|
|
240
|
+
appendJournalEntriesAndStampHeader(ctx.rootDir, entries, Date.now());
|
|
225
241
|
}
|
|
226
242
|
catch (e) {
|
|
227
243
|
debug(`Journal flush on exit failed (non-fatal): ${e.message}`);
|