refactor(structure): share chunk-size statement cache with builder helpers#1951
Conversation
…lpers batchUpdateRoles in features/structure.ts duplicated the WeakMap<db, Map<chunkSize, stmt>> cache-getter shape already extracted as getOrCreateBatchStmt in domain/graph/builder/helpers.ts. Extract the generic helper as cachedChunkStmt in db/repository/cached-stmt.ts (alongside the existing single-statement cachedStmt) and have both builder/helpers.ts and features/structure.ts depend on it, avoiding an awkward features/ -> domain/graph/builder/ dependency direction. As a side effect, the role statement cache is now module-scoped and keyed per-db like the node/edge/export caches, so repeated classifyNodeRoles calls against the same long-lived db connection (watch mode, MCP server) reuse compiled statements instead of recompiling them on every call. Impact: 6 functions changed, 21 affected
Greptile SummaryThis PR extracts the
Confidence Score: 5/5Safe to merge — focused extraction of a duplicated pattern with no new logic and a real statement-reuse bug fixed. The refactoring is mechanical: cachedChunkStmt is a verbatim lift of getOrCreateBatchStmt, all callers are updated consistently, and the only behavioral change (module-scoped roleStmtCache) is the intended fix backed by two new regression tests. No existing logic paths are altered. Both structure.ts and builder/helpers.ts import cachedChunkStmt directly from the implementation file rather than through the db barrel — a minor style inconsistency worth tidying up. Important Files Changed
Reviews (1): Last reviewed commit: "refactor(structure): share chunk-size st..." | Re-trigger Greptile |
| import { getBuildMeta, getNodeId, setBuildMeta, testFilterSQL } from '../db/index.js'; | ||
| import { cachedChunkStmt } from '../db/repository/cached-stmt.js'; |
There was a problem hiding this comment.
Both
structure.ts and builder/helpers.ts already import other symbols from the db barrel (../db/index.js), which now re-exports cachedChunkStmt. Adding a second import line that reaches into the implementation file directly (../db/repository/cached-stmt.js) creates two entry-points for the same module and diverges from the pattern used for every other db/ symbol in this file.
| import { getBuildMeta, getNodeId, setBuildMeta, testFilterSQL } from '../db/index.js'; | |
| import { cachedChunkStmt } from '../db/repository/cached-stmt.js'; | |
| import { cachedChunkStmt, getBuildMeta, getNodeId, setBuildMeta, testFilterSQL } from '../db/index.js'; |
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| import { purgeFilesData } from '../../../db/index.js'; | ||
| import { cachedChunkStmt } from '../../../db/repository/cached-stmt.js'; |
There was a problem hiding this comment.
cachedChunkStmt is now re-exported from the db barrel (db/index.js), which this file already imports for purgeFilesData. Keeping the direct sub-path import (db/repository/cached-stmt.js) as a separate line is inconsistent with how every other db/ helper is consumed here.
| import { purgeFilesData } from '../../../db/index.js'; | |
| import { cachedChunkStmt } from '../../../db/repository/cached-stmt.js'; | |
| import { cachedChunkStmt, purgeFilesData } from '../../../db/index.js'; |
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Codegraph Impact Analysis6 functions changed → 26 callers affected across 5 files
|
Fixes #1767
batchUpdateRolesinsrc/features/structure.tsduplicated theWeakMap<db, Map<chunkSize, stmt>>cache-getter shape already extracted asgetOrCreateBatchStmtinsrc/domain/graph/builder/helpers.tsduring a prior Titan grind pass.Since
features/is a different domain thandomain/graph/builder/, this extracts the generic helper intosrc/db/repository/cached-stmt.tsascachedChunkStmt— a natural sibling of the existing single-statementcachedStmthelper already used acrossdb/,domain/analysis/, etc. Bothbuilder/helpers.tsandfeatures/structure.tsnow depend on this lower-leveldb/module instead of crossing feature/domain boundaries directly. A matchingChunkStmtCache<TRow>type was added next toStmtCache<TRow>intypes.ts.As a side effect, the role statement cache in
batchUpdateRolesis now module-scoped and keyed per-db (previously a freshMapwas allocated on every call), matching the semantics of the node/edge/export batch caches — repeatedclassifyNodeRolescalls against the same long-lived db connection (watch mode, MCP server) now reuse compiled statements instead of recompiling them every time.No Rust changes: the native engine's role classification (
crates/codegraph-core/src/graph/classifiers/roles.rs) already uses rusqlite's built-inprepare_cached, so this duplicate-cache pattern only existed on the TypeScript side.Validation
npx vitest run tests/unit/roles.test.ts— added two regression tests covering (1) a single role spanning multiple statement chunk sizes (500 + remainder), and (2) cache isolation across two separate db instances — all 22 tests passnpm test— full suite: 215 files / 3562 tests passednpm run lint— cleannpm run build— clean (tsc)codegraph diff-impact --staged -T— blast radius confined to the 6 changed statement-cache/role-classification functions, 21 transitive callers across 5 filescodegraph check --cycles— no cycles introduced