Skip to content

Commit 8d82021

Browse files
committed
fix(cli): eliminate 5-minute invisible stall on 'codegraph index' by dropping and recreating the DB file instead of row-by-row DELETE
- Add CodeGraph.resetDb(): close DB, unlink the file (including -shm/-wal), then re-initialize a fresh empty database and rebuild all internal components (orchestrator, resolver, graphManager, traverser, contextBuilder) - Replace both cg.clear() calls in the index subcommand (quiet and normal modes) with cg.resetDb() - clear() executes DELETE FROM on 4 tables (nodes, edges, files, unresolved_refs) inside a transaction — on a 20GB DB with 10M+ rows this takes 5+ minutes before the progress bar is even created - resetDb() deletes the DB file in milliseconds, giving the same result (empty DB) without the invisible stall
1 parent 5cea5f1 commit 8d82021

2 files changed

Lines changed: 33 additions & 9 deletions

File tree

src/bin/codegraph.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -628,9 +628,7 @@ program
628628
const cg = await CodeGraph.open(projectPath);
629629

630630
if (options.quiet) {
631-
// Quiet mode: no UI, just run. `index` is a full re-index, so clear the
632-
// existing graph and rebuild from scratch (see the note below — #874).
633-
cg.clear();
631+
cg.resetDb();
634632
const result = await cg.indexAll();
635633
if (!result.success) process.exit(1);
636634
cg.destroy();
@@ -640,12 +638,10 @@ program
640638
const clack = await importESM('@clack/prompts');
641639
clack.intro('Indexing project');
642640

643-
// `index` is a FULL re-index: clear the existing graph and rebuild it from
644-
// scratch so the result is identical to a fresh `init`. Without the clear,
645-
// indexAll() skips every unchanged file by its content hash and reports
646-
// "0 nodes, 0 edges" against the already-populated graph — which reads as
647-
// "index wiped my index" (#874). For fast incremental updates use `sync`.
648-
cg.clear();
641+
// `index` is a FULL re-index: drop and recreate the DB from scratch so
642+
// the result is identical to a fresh `init` (much faster than row-by-row
643+
// DELETE on a large DB — see #874). For fast incremental updates use `sync`.
644+
cg.resetDb();
649645

650646
let result: IndexResult;
651647

src/index.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77

88
import * as path from 'path';
9+
import * as fs from 'fs';
910
import {
1011
Node,
1112
Edge,
@@ -1133,6 +1134,33 @@ export class CodeGraph {
11331134
this.queries.clear();
11341135
}
11351136

1137+
/**
1138+
* Drop and recreate the database (much faster than clear() for large DBs).
1139+
* Closes the current connection, deletes the DB file, and re-initializes.
1140+
*/
1141+
resetDb(): void {
1142+
const dbPath = this.db.getPath();
1143+
this.db.close();
1144+
try {
1145+
fs.unlinkSync(dbPath);
1146+
for (const ext of ['-shm', '-wal']) {
1147+
const p = dbPath + ext;
1148+
try { fs.unlinkSync(p); } catch {}
1149+
}
1150+
} catch {}
1151+
this.db = DatabaseConnection.initialize(dbPath);
1152+
this.queries = new QueryBuilder(this.db.getDb());
1153+
this.orchestrator = new ExtractionOrchestrator(this.projectRoot, this.queries);
1154+
this.resolver = createResolver(this.projectRoot, this.queries);
1155+
this.graphManager = new GraphQueryManager(this.queries);
1156+
this.traverser = new GraphTraverser(this.queries);
1157+
this.contextBuilder = createContextBuilder(
1158+
this.projectRoot,
1159+
this.queries,
1160+
this.traverser
1161+
);
1162+
}
1163+
11361164
/**
11371165
* Alias for close() for backwards compatibility.
11381166
* @deprecated Use close() instead

0 commit comments

Comments
 (0)