Skip to content

Commit f9605a0

Browse files
committed
refactor: move error recovery logic into startIndexing method
- Moved error recovery from webviewMessageHandler into CodeIndexManager.startIndexing() - This ensures error recovery happens whenever indexing is started, not just from UI - Added race condition prevention flag within CodeIndexManager - Simplified webviewMessageHandler by removing error state checking - The startIndexing method now automatically recovers from error state before proceeding
1 parent fe0d829 commit f9605a0

File tree

2 files changed

+40
-29
lines changed

2 files changed

+40
-29
lines changed

src/core/webview/webviewMessageHandler.ts

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,6 @@ const ALLOWED_VSCODE_SETTINGS = new Set(["terminal.integrated.inheritEnv"])
5555
import { MarketplaceManager, MarketplaceItemType } from "../../services/marketplace"
5656
import { setPendingTodoList } from "../tools/updateTodoListTool"
5757

58-
// Flag to prevent race conditions during indexing recovery
59-
let isRecoveringFromIndexingError = false
60-
6158
export const webviewMessageHandler = async (
6259
provider: ClineProvider,
6360
message: WebviewMessage,
@@ -2202,32 +2199,22 @@ export const webviewMessageHandler = async (
22022199
return
22032200
}
22042201
if (manager.isFeatureEnabled && manager.isFeatureConfigured) {
2205-
// Check if in error state and recover
2206-
const currentStatus = manager.getCurrentStatus()
2207-
if (currentStatus.systemStatus === "Error") {
2208-
// Prevent race conditions from multiple rapid clicks
2209-
if (isRecoveringFromIndexingError) {
2210-
provider.log("Indexing recovery already in progress, ignoring duplicate request")
2211-
return
2212-
}
2213-
2214-
isRecoveringFromIndexingError = true
2215-
try {
2216-
await manager.recoverFromError()
2217-
} finally {
2218-
isRecoveringFromIndexingError = false
2219-
}
2202+
if (!manager.isInitialized) {
2203+
await manager.initialize(provider.contextProxy)
22202204
}
22212205

2206+
// startIndexing now handles error recovery internally
2207+
await manager.startIndexing()
2208+
2209+
// If startIndexing recovered from error, we need to reinitialize
22222210
if (!manager.isInitialized) {
22232211
await manager.initialize(provider.contextProxy)
2212+
// Try starting again after initialization
2213+
await manager.startIndexing()
22242214
}
2225-
2226-
manager.startIndexing()
22272215
}
22282216
} catch (error) {
22292217
provider.log(`Error starting indexing: ${error instanceof Error ? error.message : String(error)}`)
2230-
isRecoveringFromIndexingError = false
22312218
}
22322219
break
22332220
}

src/services/code-index/manager.ts

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ export class CodeIndexManager {
2828
private _searchService: CodeIndexSearchService | undefined
2929
private _cacheManager: CacheManager | undefined
3030

31+
// Flag to prevent race conditions during error recovery
32+
private _isRecoveringFromError = false
33+
3134
public static getInstance(context: vscode.ExtensionContext): CodeIndexManager | undefined {
3235
// Use first workspace folder consistently
3336
const workspaceFolders = vscode.workspace.workspaceFolders
@@ -157,12 +160,23 @@ export class CodeIndexManager {
157160

158161
/**
159162
* Initiates the indexing process (initial scan and starts watcher).
163+
* Automatically recovers from error state if needed before starting.
160164
*/
161-
162165
public async startIndexing(): Promise<void> {
163166
if (!this.isFeatureEnabled) {
164167
return
165168
}
169+
170+
// Check if we're in error state and recover if needed
171+
const currentStatus = this.getCurrentStatus()
172+
if (currentStatus.systemStatus === "Error") {
173+
await this.recoverFromError()
174+
175+
// After recovery, we need to reinitialize since recoverFromError clears all services
176+
// This will be handled by the caller (webviewMessageHandler) checking isInitialized
177+
return
178+
}
179+
166180
this.assertInitialized()
167181
await this._orchestrator!.startIndexing()
168182
}
@@ -191,22 +205,32 @@ export class CodeIndexManager {
191205
* - Safe to call even when not in error state (idempotent)
192206
* - Does not restart indexing automatically - call initialize() after recovery
193207
* - Service instances will be recreated on next initialize() call
208+
* - Prevents race conditions from multiple concurrent recovery attempts
194209
*/
195210
public async recoverFromError(): Promise<void> {
211+
// Prevent race conditions from multiple rapid recovery attempts
212+
if (this._isRecoveringFromError) {
213+
return
214+
}
215+
216+
this._isRecoveringFromError = true
196217
try {
197218
// Clear error state
198219
this._stateManager.setSystemState("Standby", "")
199220
} catch (error) {
200221
// Log error but continue with recovery - clearing service instances is more important
201222
console.error("Failed to clear error state during recovery:", error)
223+
} finally {
224+
// Force re-initialization by clearing service instances
225+
// This ensures a clean slate even if state update failed
226+
this._configManager = undefined
227+
this._serviceFactory = undefined
228+
this._orchestrator = undefined
229+
this._searchService = undefined
230+
231+
// Reset the flag after recovery is complete
232+
this._isRecoveringFromError = false
202233
}
203-
204-
// Force re-initialization by clearing service instances
205-
// This ensures a clean slate even if state update failed
206-
this._configManager = undefined
207-
this._serviceFactory = undefined
208-
this._orchestrator = undefined
209-
this._searchService = undefined
210234
}
211235

212236
/**

0 commit comments

Comments
 (0)