Skip to content

Commit e49f7d0

Browse files
committed
fix: prevent instant green status during index scanning
- Add proper progress reporting during file discovery phase - Validate that actual scanning work was performed before transitioning to "Indexed" state - Provide meaningful completion messages based on scan results - Handle edge cases where no files need processing (all cached) - Add progress callback to scanner interface for better user feedback Fixes #5763
1 parent d513b9c commit e49f7d0

File tree

3 files changed

+66
-2
lines changed

3 files changed

+66
-2
lines changed

src/services/code-index/interfaces/file-processor.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export interface IDirectoryScanner {
3737
onError?: (error: Error) => void,
3838
onBlocksIndexed?: (indexedCount: number) => void,
3939
onFileParsed?: (fileBlockCount: number) => void,
40+
onProgressUpdate?: (message: string) => void,
4041
): Promise<{
4142
codeBlocks: CodeBlock[]
4243
stats: {

src/services/code-index/orchestrator.ts

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ export class CodeIndexOrchestrator {
127127
let cumulativeBlocksIndexed = 0
128128
let cumulativeBlocksFoundSoFar = 0
129129
let batchErrors: Error[] = []
130+
let scanStartTime = Date.now()
130131

131132
const handleFileParsed = (fileBlockCount: number) => {
132133
cumulativeBlocksFoundSoFar += fileBlockCount
@@ -138,6 +139,13 @@ export class CodeIndexOrchestrator {
138139
this.stateManager.reportBlockIndexingProgress(cumulativeBlocksIndexed, cumulativeBlocksFoundSoFar)
139140
}
140141

142+
// Report initial scanning progress
143+
this.stateManager.setSystemState("Indexing", "Discovering files to scan...")
144+
145+
const handleProgressUpdate = (message: string) => {
146+
this.stateManager.setSystemState("Indexing", message)
147+
}
148+
141149
const result = await this.scanner.scanDirectory(
142150
this.workspacePath,
143151
(batchError: Error) => {
@@ -149,13 +157,32 @@ export class CodeIndexOrchestrator {
149157
},
150158
handleBlocksIndexed,
151159
handleFileParsed,
160+
handleProgressUpdate,
152161
)
153162

154163
if (!result) {
155164
throw new Error("Scan failed, is scanner initialized?")
156165
}
157166

158167
const { stats } = result
168+
const scanDuration = Date.now() - scanStartTime
169+
170+
// Validate that actual scanning work was performed
171+
const totalFilesProcessed = stats.processed + stats.skipped
172+
const hasActualWork = totalFilesProcessed > 0
173+
174+
// If no files were found to process, this might indicate a configuration issue
175+
if (!hasActualWork) {
176+
this.stateManager.setSystemState("Indexed", "No supported files found in workspace. Index is empty.")
177+
await this._startWatcher()
178+
return
179+
}
180+
181+
// Report scanning completion with meaningful progress
182+
this.stateManager.setSystemState(
183+
"Indexing",
184+
`Scanned ${totalFilesProcessed} files (${stats.processed} processed, ${stats.skipped} cached). Processing code blocks...`,
185+
)
159186

160187
// Check if any blocks were actually indexed successfully
161188
// If no blocks were indexed but blocks were found, it means all batches failed
@@ -172,7 +199,10 @@ export class CodeIndexOrchestrator {
172199
}
173200

174201
// Check for partial failures - if a significant portion of blocks failed
175-
const failureRate = (cumulativeBlocksFoundSoFar - cumulativeBlocksIndexed) / cumulativeBlocksFoundSoFar
202+
const failureRate =
203+
cumulativeBlocksFoundSoFar > 0
204+
? (cumulativeBlocksFoundSoFar - cumulativeBlocksIndexed) / cumulativeBlocksFoundSoFar
205+
: 0
176206
if (batchErrors.length > 0 && failureRate > 0.1) {
177207
// More than 10% of blocks failed to index
178208
const firstError = batchErrors[0]
@@ -196,9 +226,22 @@ export class CodeIndexOrchestrator {
196226
)
197227
}
198228

229+
// Provide meaningful completion message based on what was actually done
230+
let completionMessage: string
231+
if (stats.processed === 0 && stats.skipped > 0) {
232+
// All files were cached - no actual processing needed
233+
completionMessage = `Index up-to-date. All ${stats.skipped} files were already cached (no changes detected).`
234+
} else if (cumulativeBlocksIndexed > 0) {
235+
// Some blocks were actually indexed
236+
completionMessage = `Indexing complete. Processed ${stats.processed} files and indexed ${cumulativeBlocksIndexed} code blocks in ${Math.round(scanDuration / 1000)}s.`
237+
} else {
238+
// No blocks found to index
239+
completionMessage = `Scan complete. No code blocks found in ${totalFilesProcessed} files.`
240+
}
241+
199242
await this._startWatcher()
200243

201-
this.stateManager.setSystemState("Indexed", "File watcher started.")
244+
this.stateManager.setSystemState("Indexed", completionMessage)
202245
} catch (error: any) {
203246
console.error("[CodeIndexOrchestrator] Error during indexing:", error)
204247
TelemetryService.instance.captureEvent(TelemetryEventName.CODE_INDEX_ERROR, {

src/services/code-index/processors/scanner.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,17 +51,23 @@ export class DirectoryScanner implements IDirectoryScanner {
5151
onError?: (error: Error) => void,
5252
onBlocksIndexed?: (indexedCount: number) => void,
5353
onFileParsed?: (fileBlockCount: number) => void,
54+
onProgressUpdate?: (message: string) => void,
5455
): Promise<{ codeBlocks: CodeBlock[]; stats: { processed: number; skipped: number }; totalBlockCount: number }> {
5556
const directoryPath = directory
5657
// Capture workspace context at scan start
5758
const scanWorkspace = getWorkspacePathForContext(directoryPath)
5859

60+
// Report file discovery progress
61+
onProgressUpdate?.("Discovering files in workspace...")
62+
5963
// Get all files recursively (handles .gitignore automatically)
6064
const [allPaths, _] = await listFiles(directoryPath, true, MAX_LIST_FILES_LIMIT)
6165

6266
// Filter out directories (marked with trailing '/')
6367
const filePaths = allPaths.filter((p) => !p.endsWith("/"))
6468

69+
onProgressUpdate?.(`Found ${filePaths.length} files. Applying filters...`)
70+
6571
// Initialize RooIgnoreController if not provided
6672
const ignoreController = new RooIgnoreController(directoryPath)
6773

@@ -83,6 +89,20 @@ export class DirectoryScanner implements IDirectoryScanner {
8389
return scannerExtensions.includes(ext) && !this.ignoreInstance.ignores(relativeFilePath)
8490
})
8591

92+
onProgressUpdate?.(
93+
`Found ${supportedPaths.length} supported files to scan (filtered from ${filePaths.length} total files).`,
94+
)
95+
96+
// Early return if no files to process
97+
if (supportedPaths.length === 0) {
98+
onProgressUpdate?.("No supported files found to scan.")
99+
return {
100+
codeBlocks: [],
101+
stats: { processed: 0, skipped: 0 },
102+
totalBlockCount: 0,
103+
}
104+
}
105+
86106
// Initialize tracking variables
87107
const processedFiles = new Set<string>()
88108
const codeBlocks: CodeBlock[] = []

0 commit comments

Comments
 (0)