diff --git a/gitnexus/src/core/ingestion/pipeline-phases/cross-file-impl.ts b/gitnexus/src/core/ingestion/pipeline-phases/cross-file-impl.ts index 717d2dcd7..ca0c1b1fb 100644 --- a/gitnexus/src/core/ingestion/pipeline-phases/cross-file-impl.ts +++ b/gitnexus/src/core/ingestion/pipeline-phases/cross-file-impl.ts @@ -37,19 +37,6 @@ const CROSS_FILE_SKIP_THRESHOLD = 0.03; /** Hard cap on files re-processed during cross-file propagation. */ const MAX_CROSS_FILE_REPROCESS = 2000; -/** - * Default wall-clock time limit (ms) for cross-file propagation. - * Override via `GITNEXUS_CROSS_FILE_TIMEOUT_MS` env var. - * Prevents the phase from stalling for hours on very large repositories - * where per-file re-resolution is expensive. - */ -const DEFAULT_CROSS_FILE_ELAPSED_MS = 120_000; // 2 minutes - -function getCrossFileTimeoutMs(): number { - const raw = Number(process.env.GITNEXUS_CROSS_FILE_TIMEOUT_MS); - return raw > 0 && Number.isFinite(raw) ? raw : DEFAULT_CROSS_FILE_ELAPSED_MS; -} - /** * Cross-file binding propagation. * Returns the number of files re-processed. @@ -131,13 +118,11 @@ export async function runCrossFileBindingPropagation( let crossFileResolved = 0; const crossFileStart = Date.now(); - const crossFileDeadlineMs = getCrossFileTimeoutMs(); const astCache = createASTCache(AST_CACHE_CAP); // Compiled query objects keyed by language name. Shared across all processCalls // invocations in this phase so the same tree-sitter query string is only // compiled once per language instead of once per file (O(1) vs O(N)). const compiledQueryCache = new Map(); - let timedOut = false; // Snapshot total topological candidates for progress math. We walk the // levels once more here (fast — no I/O) so we can report meaningful @@ -161,8 +146,6 @@ export async function runCrossFileBindingPropagation( const PROGRESS_INTERVAL = 25; for (const level of levels) { - if (timedOut) break; - const levelCandidates: { filePath: string; seeded: Map; @@ -208,15 +191,6 @@ export async function runCrossFileBindingPropagation( const contentMap = await readFileContents(repoPath, levelPaths); for (const { filePath, seeded, importedReturns, importedRawReturns } of levelCandidates) { - if (Date.now() - crossFileStart >= crossFileDeadlineMs) { - timedOut = true; - logger.warn( - `⏱️ Cross-file type propagation timed out after ${crossFileDeadlineMs}ms` + - ` (${crossFileResolved} files processed). Override with GITNEXUS_CROSS_FILE_TIMEOUT_MS env var.`, - ); - break; - } - const content = contentMap.get(filePath); if (!content) continue; diff --git a/gitnexus/test/unit/cross-file-impl.test.ts b/gitnexus/test/unit/cross-file-impl.test.ts index b32cb9006..55a47a5b5 100644 --- a/gitnexus/test/unit/cross-file-impl.test.ts +++ b/gitnexus/test/unit/cross-file-impl.test.ts @@ -162,72 +162,6 @@ describe('runCrossFileBindingPropagation', () => { } }); - it('stops processing when time deadline is exceeded', async () => { - const graph = createKnowledgeGraph(); - const ctx = createResolutionContext(); - - const exportedTypeMap: ExportedTypeMap = new Map([ - ['upstream.ts', new Map([['User', 'User']])], - ]); - - const allPaths: string[] = ['upstream.ts']; - // Create 50 downstream importers - ctx.importMap.set('upstream.ts', new Set()); - for (let i = 0; i < 50; i++) { - const file = `downstream${i}.ts`; - allPaths.push(file); - const bindings = new Map(); - bindings.set('User', { sourcePath: 'upstream.ts', exportedName: 'User' }); - ctx.namedImportMap.set(file, bindings); - ctx.importMap.set(file, new Set(['upstream.ts'])); - } - - // Set a very short timeout via env var. The processCalls mock below - // advances Date.now past this deadline after the first invocation. - const origEnv = process.env.GITNEXUS_CROSS_FILE_TIMEOUT_MS; - process.env.GITNEXUS_CROSS_FILE_TIMEOUT_MS = '50'; - - let callCount = 0; - processCallsMock.mockImplementation(async () => { - callCount++; - // After the first call, busy-wait past the 50ms deadline so the - // time check before the next candidate triggers. - if (callCount === 1) { - const start = Date.now(); - while (Date.now() - start < 60) { - /* spin */ - } - } - return []; - }); - - try { - const result = await runCrossFileBindingPropagation( - graph, - ctx, - exportedTypeMap, - new Set(allPaths), - allPaths.length, - '/repo', - Date.now(), - () => {}, - ); - - // Should have processed at least 1 file (the first one goes through - // before the deadline check), but NOT all 50. - expect(result).toBeGreaterThan(0); - expect(result).toBeLessThan(50); - expect(processCallsMock.mock.calls.length).toBeLessThan(50); - } finally { - if (origEnv === undefined) { - delete process.env.GITNEXUS_CROSS_FILE_TIMEOUT_MS; - } else { - process.env.GITNEXUS_CROSS_FILE_TIMEOUT_MS = origEnv; - } - processCallsMock.mockImplementation(async () => []); - } - }); - it('caps processing at MAX_CROSS_FILE_REPROCESS (2000)', async () => { const graph = createKnowledgeGraph(); const ctx = createResolutionContext();