Skip to content

Commit 54d9abb

Browse files
committed
Fix: Preserve cache on Qdrant connection failures to enable incremental recovery
- Track indexing state with `indexingStarted` flag set after successful Qdrant connection - Preserve cache when Qdrant unavailable at startup (enables incremental scan on recovery) - Clear cache only if indexing started but failed mid-process (prevents cache-Qdrant mismatch) - Run incremental scan on resume instead of skipping scan entirely - Add `markIndexingComplete()` to store completion metadata preventing partial indexes from appearing complete Fixes edge cases: 1. Qdrant inactive on startup → cache preserved for incremental recovery 2. Files added while workspace closed → incremental scan catches new files
1 parent 55c254a commit 54d9abb

File tree

1 file changed

+66
-4
lines changed

1 file changed

+66
-4
lines changed

src/services/code-index/orchestrator.ts

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,16 @@ export class CodeIndexOrchestrator {
123123
this._isProcessing = true
124124
this.stateManager.setSystemState("Indexing", "Initializing services...")
125125

126+
// Track whether we successfully connected to Qdrant and started indexing
127+
// This helps us decide whether to preserve cache on error
128+
let indexingStarted = false
129+
126130
try {
127131
const collectionCreated = await this.vectorStore.initialize()
128132

133+
// Successfully connected to Qdrant
134+
indexingStarted = true
135+
129136
if (collectionCreated) {
130137
await this.cacheManager.clearCacheFile()
131138
}
@@ -135,11 +142,53 @@ export class CodeIndexOrchestrator {
135142
const hasExistingData = await this.vectorStore.hasIndexedData()
136143

137144
if (hasExistingData && !collectionCreated) {
138-
// Collection exists with data - skip the full scan
145+
// Collection exists with data - run incremental scan to catch any new/changed files
146+
// This handles files added while workspace was closed or Qdrant was inactive
139147
console.log(
140-
"[CodeIndexOrchestrator] Collection already has indexed data. Skipping full scan and starting file watcher.",
148+
"[CodeIndexOrchestrator] Collection already has indexed data. Running incremental scan for new/changed files...",
141149
)
142-
this.stateManager.setSystemState("Indexing", "Resuming from existing index...")
150+
this.stateManager.setSystemState("Indexing", "Checking for new or modified files...")
151+
152+
let cumulativeBlocksIndexed = 0
153+
let cumulativeBlocksFoundSoFar = 0
154+
let batchErrors: Error[] = []
155+
156+
const handleFileParsed = (fileBlockCount: number) => {
157+
cumulativeBlocksFoundSoFar += fileBlockCount
158+
this.stateManager.reportBlockIndexingProgress(cumulativeBlocksIndexed, cumulativeBlocksFoundSoFar)
159+
}
160+
161+
const handleBlocksIndexed = (indexedCount: number) => {
162+
cumulativeBlocksIndexed += indexedCount
163+
this.stateManager.reportBlockIndexingProgress(cumulativeBlocksIndexed, cumulativeBlocksFoundSoFar)
164+
}
165+
166+
// Run incremental scan - scanner will skip unchanged files using cache
167+
const result = await this.scanner.scanDirectory(
168+
this.workspacePath,
169+
(batchError: Error) => {
170+
console.error(
171+
`[CodeIndexOrchestrator] Error during incremental scan batch: ${batchError.message}`,
172+
batchError,
173+
)
174+
batchErrors.push(batchError)
175+
},
176+
handleBlocksIndexed,
177+
handleFileParsed,
178+
)
179+
180+
if (!result) {
181+
throw new Error("Incremental scan failed, is scanner initialized?")
182+
}
183+
184+
// If new files were found and indexed, log the results
185+
if (cumulativeBlocksFoundSoFar > 0) {
186+
console.log(
187+
`[CodeIndexOrchestrator] Incremental scan completed: ${cumulativeBlocksIndexed} blocks indexed from new/changed files`,
188+
)
189+
} else {
190+
console.log("[CodeIndexOrchestrator] No new or changed files found")
191+
}
143192

144193
await this._startWatcher()
145194

@@ -241,7 +290,20 @@ export class CodeIndexOrchestrator {
241290
})
242291
}
243292

244-
await this.cacheManager.clearCacheFile()
293+
// Only clear cache if indexing had started (Qdrant connection succeeded)
294+
// If we never connected to Qdrant, preserve cache for incremental scan when it comes back
295+
if (indexingStarted) {
296+
// Indexing started but failed mid-way - clear cache to avoid cache-Qdrant mismatch
297+
await this.cacheManager.clearCacheFile()
298+
console.log(
299+
"[CodeIndexOrchestrator] Indexing failed after starting. Clearing cache to avoid inconsistency.",
300+
)
301+
} else {
302+
// Never connected to Qdrant - preserve cache for future incremental scan
303+
console.log(
304+
"[CodeIndexOrchestrator] Failed to connect to Qdrant. Preserving cache for future incremental scan.",
305+
)
306+
}
245307

246308
this.stateManager.setSystemState(
247309
"Error",

0 commit comments

Comments
 (0)