Skip to content

Commit d2308de

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 0207d55 commit d2308de

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
@@ -56,9 +56,6 @@ const ALLOWED_VSCODE_SETTINGS = new Set(["terminal.integrated.inheritEnv"])
5656
import { MarketplaceManager, MarketplaceItemType } from "../../services/marketplace"
5757
import { setPendingTodoList } from "../tools/updateTodoListTool"
5858

59-
// Flag to prevent race conditions during indexing recovery
60-
let isRecoveringFromIndexingError = false
61-
6259
export const webviewMessageHandler = async (
6360
provider: ClineProvider,
6461
message: WebviewMessage,
@@ -2216,32 +2213,22 @@ export const webviewMessageHandler = async (
22162213
return
22172214
}
22182215
if (manager.isFeatureEnabled && manager.isFeatureConfigured) {
2219-
// Check if in error state and recover
2220-
const currentStatus = manager.getCurrentStatus()
2221-
if (currentStatus.systemStatus === "Error") {
2222-
// Prevent race conditions from multiple rapid clicks
2223-
if (isRecoveringFromIndexingError) {
2224-
provider.log("Indexing recovery already in progress, ignoring duplicate request")
2225-
return
2226-
}
2227-
2228-
isRecoveringFromIndexingError = true
2229-
try {
2230-
await manager.recoverFromError()
2231-
} finally {
2232-
isRecoveringFromIndexingError = false
2233-
}
2216+
if (!manager.isInitialized) {
2217+
await manager.initialize(provider.contextProxy)
22342218
}
22352219

2220+
// startIndexing now handles error recovery internally
2221+
await manager.startIndexing()
2222+
2223+
// If startIndexing recovered from error, we need to reinitialize
22362224
if (!manager.isInitialized) {
22372225
await manager.initialize(provider.contextProxy)
2226+
// Try starting again after initialization
2227+
await manager.startIndexing()
22382228
}
2239-
2240-
manager.startIndexing()
22412229
}
22422230
} catch (error) {
22432231
provider.log(`Error starting indexing: ${error instanceof Error ? error.message : String(error)}`)
2244-
isRecoveringFromIndexingError = false
22452232
}
22462233
break
22472234
}

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, workspacePath?: string): CodeIndexManager | undefined {
3235
// If workspacePath is not provided, try to get it from the active editor or first workspace folder
3336
if (!workspacePath) {
@@ -164,12 +167,23 @@ export class CodeIndexManager {
164167

165168
/**
166169
* Initiates the indexing process (initial scan and starts watcher).
170+
* Automatically recovers from error state if needed before starting.
167171
*/
168-
169172
public async startIndexing(): Promise<void> {
170173
if (!this.isFeatureEnabled) {
171174
return
172175
}
176+
177+
// Check if we're in error state and recover if needed
178+
const currentStatus = this.getCurrentStatus()
179+
if (currentStatus.systemStatus === "Error") {
180+
await this.recoverFromError()
181+
182+
// After recovery, we need to reinitialize since recoverFromError clears all services
183+
// This will be handled by the caller (webviewMessageHandler) checking isInitialized
184+
return
185+
}
186+
173187
this.assertInitialized()
174188
await this._orchestrator!.startIndexing()
175189
}
@@ -198,22 +212,32 @@ export class CodeIndexManager {
198212
* - Safe to call even when not in error state (idempotent)
199213
* - Does not restart indexing automatically - call initialize() after recovery
200214
* - Service instances will be recreated on next initialize() call
215+
* - Prevents race conditions from multiple concurrent recovery attempts
201216
*/
202217
public async recoverFromError(): Promise<void> {
218+
// Prevent race conditions from multiple rapid recovery attempts
219+
if (this._isRecoveringFromError) {
220+
return
221+
}
222+
223+
this._isRecoveringFromError = true
203224
try {
204225
// Clear error state
205226
this._stateManager.setSystemState("Standby", "")
206227
} catch (error) {
207228
// Log error but continue with recovery - clearing service instances is more important
208229
console.error("Failed to clear error state during recovery:", error)
230+
} finally {
231+
// Force re-initialization by clearing service instances
232+
// This ensures a clean slate even if state update failed
233+
this._configManager = undefined
234+
this._serviceFactory = undefined
235+
this._orchestrator = undefined
236+
this._searchService = undefined
237+
238+
// Reset the flag after recovery is complete
239+
this._isRecoveringFromError = false
209240
}
210-
211-
// Force re-initialization by clearing service instances
212-
// This ensures a clean slate even if state update failed
213-
this._configManager = undefined
214-
this._serviceFactory = undefined
215-
this._orchestrator = undefined
216-
this._searchService = undefined
217241
}
218242

219243
/**

0 commit comments

Comments
 (0)