Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ export async function activate(context: vscode.ExtensionContext) {
const contextProxy = await ContextProxy.getInstance(context)

// Initialize code index managers for all workspace folders.
// Make initialization non-blocking to prevent extension activation from hanging
const codeIndexManagers: CodeIndexManager[] = []

if (vscode.workspace.workspaceFolders) {
Expand All @@ -108,16 +109,15 @@ export async function activate(context: vscode.ExtensionContext) {

if (manager) {
codeIndexManagers.push(manager)
context.subscriptions.push(manager)

try {
await manager.initialize(contextProxy)
} catch (error) {
// Initialize in the background without blocking extension activation
// This prevents the extension from getting stuck if the embedder service is unavailable
manager.initialize(contextProxy).catch((error) => {
outputChannel.appendLine(
`[CodeIndexManager] Error during background CodeIndexManager configuration/indexing for ${folder.uri.fsPath}: ${error.message || error}`,
)
}

context.subscriptions.push(manager)
})
}
}
}
Expand Down
18 changes: 17 additions & 1 deletion src/services/code-index/service-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,23 @@ export class CodeIndexServiceFactory {
*/
public async validateEmbedder(embedder: IEmbedder): Promise<{ valid: boolean; error?: string }> {
try {
return await embedder.validateConfiguration()
// Add a timeout to prevent hanging when the embedder service is unavailable
const VALIDATION_TIMEOUT_MS = 5000 // 5 seconds timeout

const timeoutPromise = new Promise<{ valid: boolean; error: string }>((_, reject) => {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The timeout promise is typed as Promise<{ valid: boolean; error: string }> but only ever calls reject(), never resolve(). The type annotation is misleading since this promise will never successfully resolve to that type. Consider using Promise<never> or removing the type annotation entirely to let TypeScript infer it correctly, since the promise only rejects.

setTimeout(() => {
reject(
new Error(
"Failed to connect to the embedder service. Please check your connection settings and ensure the service is running.",
),
)
}, VALIDATION_TIMEOUT_MS)
})

const validationPromise = embedder.validateConfiguration()

// Race between validation and timeout
return await Promise.race([validationPromise, timeoutPromise])
} catch (error) {
// Capture telemetry for the error
TelemetryService.instance.captureEvent(TelemetryEventName.CODE_INDEX_ERROR, {
Expand Down