mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
fix: prevent Ollama indexing from freezing at 69%
- Add dynamic timeout for batch embedding operations based on batch size - Improve error handling and recovery in batch processing - Ensure errors are properly thrown to prevent silent failures - Add immediate error state updates when batch processing fails - Add better logging for debugging timeout and retry scenarios Fixes #6849
This commit is contained in:
parent
ad0e33e2d9
commit
2eb26fcd96
4 changed files with 46 additions and 6 deletions
|
|
@ -15,7 +15,8 @@
|
|||
"serviceUnavailable": "Ollama service is unavailable (status: {{status}})",
|
||||
"modelNotFound": "Ollama model not found: {{modelId}}",
|
||||
"modelNotEmbeddingCapable": "Ollama model is not embedding capable: {{modelId}}",
|
||||
"hostNotFound": "Ollama host not found: {{baseUrl}}"
|
||||
"hostNotFound": "Ollama host not found: {{baseUrl}}",
|
||||
"batchTimeoutError": "Ollama embedding timed out after {{timeout}} seconds while processing {{count}} texts. Consider reducing batch size or increasing timeout."
|
||||
},
|
||||
"scanner": {
|
||||
"unknownErrorProcessingFile": "Unknown error processing file {{filePath}}",
|
||||
|
|
|
|||
|
|
@ -69,8 +69,10 @@ export class CodeIndexOllamaEmbedder implements IEmbedder {
|
|||
// Implementing based on user's specific request structure.
|
||||
|
||||
// Add timeout to prevent indefinite hanging
|
||||
// Use a longer timeout for batch operations as they can take more time
|
||||
const batchTimeout = Math.max(OLLAMA_EMBEDDING_TIMEOUT_MS, texts.length * 2000) // At least 2 seconds per text
|
||||
const controller = new AbortController()
|
||||
const timeoutId = setTimeout(() => controller.abort(), OLLAMA_EMBEDDING_TIMEOUT_MS)
|
||||
const timeoutId = setTimeout(() => controller.abort(), batchTimeout)
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: "POST",
|
||||
|
|
@ -125,7 +127,15 @@ export class CodeIndexOllamaEmbedder implements IEmbedder {
|
|||
|
||||
// Handle specific error types with better messages
|
||||
if (error.name === "AbortError") {
|
||||
throw new Error(t("embeddings:validation.connectionFailed"))
|
||||
// More specific timeout error message for batch operations
|
||||
const timeoutMessage =
|
||||
texts.length > 1
|
||||
? t("embeddings:ollama.batchTimeoutError", {
|
||||
count: texts.length,
|
||||
timeout: Math.round(Math.max(OLLAMA_EMBEDDING_TIMEOUT_MS, texts.length * 2000) / 1000),
|
||||
})
|
||||
: t("embeddings:validation.connectionFailed")
|
||||
throw new Error(timeoutMessage)
|
||||
} else if (error.message?.includes("fetch failed") || error.code === "ECONNREFUSED") {
|
||||
throw new Error(t("embeddings:ollama.serviceNotRunning", { baseUrl: this.baseUrl }))
|
||||
} else if (error.code === "ENOTFOUND") {
|
||||
|
|
|
|||
|
|
@ -138,11 +138,13 @@ export class CodeIndexOrchestrator {
|
|||
|
||||
const handleFileParsed = (fileBlockCount: number) => {
|
||||
cumulativeBlocksFoundSoFar += fileBlockCount
|
||||
// Update progress immediately when blocks are found
|
||||
this.stateManager.reportBlockIndexingProgress(cumulativeBlocksIndexed, cumulativeBlocksFoundSoFar)
|
||||
}
|
||||
|
||||
const handleBlocksIndexed = (indexedCount: number) => {
|
||||
cumulativeBlocksIndexed += indexedCount
|
||||
// Update progress immediately when blocks are indexed
|
||||
this.stateManager.reportBlockIndexingProgress(cumulativeBlocksIndexed, cumulativeBlocksFoundSoFar)
|
||||
}
|
||||
|
||||
|
|
@ -154,6 +156,8 @@ export class CodeIndexOrchestrator {
|
|||
batchError,
|
||||
)
|
||||
batchErrors.push(batchError)
|
||||
// Update state to show error immediately
|
||||
this.stateManager.setSystemState("Error", `Indexing error: ${batchError.message}`)
|
||||
},
|
||||
handleBlocksIndexed,
|
||||
handleFileParsed,
|
||||
|
|
|
|||
|
|
@ -385,8 +385,29 @@ export class DirectoryScanner implements IDirectoryScanner {
|
|||
}
|
||||
// --- End Deletion Step ---
|
||||
|
||||
// Create embeddings for batch
|
||||
const { embeddings } = await this.embedder.createEmbeddings(batchTexts)
|
||||
// Create embeddings for batch with better error context
|
||||
let embeddings: number[][]
|
||||
try {
|
||||
const response = await this.embedder.createEmbeddings(batchTexts)
|
||||
embeddings = response.embeddings
|
||||
} catch (embeddingError: any) {
|
||||
// Log specific details about the embedding failure
|
||||
console.error(
|
||||
`[DirectoryScanner] Embedding creation failed for batch of ${batchTexts.length} texts:`,
|
||||
embeddingError,
|
||||
)
|
||||
|
||||
// Check if it's a timeout error and provide more context
|
||||
if (embeddingError.message?.includes("timed out") || embeddingError.message?.includes("timeout")) {
|
||||
throw new Error(
|
||||
`Embedding timeout for batch of ${batchTexts.length} texts. This may indicate the Ollama service is overloaded or the model is too slow. ${embeddingError.message}`,
|
||||
{ cause: embeddingError },
|
||||
)
|
||||
}
|
||||
|
||||
// Re-throw with additional context
|
||||
throw embeddingError
|
||||
}
|
||||
|
||||
// Prepare points for Qdrant
|
||||
const points = batchBlocks.map((block, index) => {
|
||||
|
|
@ -420,7 +441,7 @@ export class DirectoryScanner implements IDirectoryScanner {
|
|||
} catch (error) {
|
||||
lastError = error as Error
|
||||
console.error(
|
||||
`[DirectoryScanner] Error processing batch (attempt ${attempts}) in workspace ${scanWorkspace}:`,
|
||||
`[DirectoryScanner] Error processing batch (attempt ${attempts}/${MAX_BATCH_RETRIES}) in workspace ${scanWorkspace}:`,
|
||||
error,
|
||||
)
|
||||
TelemetryService.instance.captureEvent(TelemetryEventName.CODE_INDEX_ERROR, {
|
||||
|
|
@ -433,6 +454,7 @@ export class DirectoryScanner implements IDirectoryScanner {
|
|||
|
||||
if (attempts < MAX_BATCH_RETRIES) {
|
||||
const delay = INITIAL_RETRY_DELAY_MS * Math.pow(2, attempts - 1)
|
||||
console.log(`[DirectoryScanner] Retrying batch processing in ${delay}ms...`)
|
||||
await new Promise((resolve) => setTimeout(resolve, delay))
|
||||
}
|
||||
}
|
||||
|
|
@ -454,6 +476,9 @@ export class DirectoryScanner implements IDirectoryScanner {
|
|||
),
|
||||
)
|
||||
}
|
||||
// CRITICAL: Throw the error to ensure it's caught by the orchestrator
|
||||
// This prevents the indexing from appearing to succeed when it actually failed
|
||||
throw lastError
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue