Add server-side timeout handling to Ollama Cloud streaming

- Added 60 second timeout per chunk in parseStreamingResponse
- Added 120 second timeout to makeRequest with AbortController
- This prevents the server from hanging indefinitely on slow/unresponsive API

This should fix the UI freeze when sending messages to Ollama Cloud models.
This commit is contained in:
Gemini AI
2025-12-24 21:53:00 +04:00
Unverified
parent fd6c563f71
commit 2cb9fea514

View File

@@ -338,12 +338,39 @@ export class OllamaCloudClient {
const reader = response.body.getReader()
const decoder = new TextDecoder()
const STREAM_TIMEOUT_MS = 60000 // 60 second timeout per chunk
let lastActivity = Date.now()
const checkTimeout = () => {
if (Date.now() - lastActivity > STREAM_TIMEOUT_MS) {
reader.cancel().catch(() => { })
throw new Error("Stream timeout - no data received for 60 seconds")
}
}
try {
while (true) {
const { done, value } = await reader.read()
checkTimeout()
// Create a timeout promise
const timeoutPromise = new Promise<never>((_, reject) => {
setTimeout(() => reject(new Error("Read timeout")), STREAM_TIMEOUT_MS)
})
// Race the read against the timeout
let result: ReadableStreamReadResult<Uint8Array>
try {
result = await Promise.race([reader.read(), timeoutPromise])
} catch (timeoutError) {
reader.cancel().catch(() => { })
throw new Error("Stream read timeout")
}
const { done, value } = result
if (done) break
lastActivity = Date.now()
const lines = decoder.decode(value, { stream: true }).split('\n').filter(line => line.trim())
for (const line of lines) {
@@ -371,7 +398,7 @@ export class OllamaCloudClient {
}
}
private async makeRequest(endpoint: string, options: RequestInit): Promise<Response> {
private async makeRequest(endpoint: string, options: RequestInit, timeoutMs: number = 120000): Promise<Response> {
// Ensure endpoint starts with /api
const apiEndpoint = endpoint.startsWith('/api') ? endpoint : `/api${endpoint}`
const url = `${this.baseUrl}${apiEndpoint}`
@@ -386,10 +413,19 @@ export class OllamaCloudClient {
console.log(`[OllamaCloud] Making request to: ${url}`)
return fetch(url, {
...options,
headers
})
// Add timeout to prevent indefinite hangs
const controller = new AbortController()
const timeoutId = setTimeout(() => controller.abort(), timeoutMs)
try {
return await fetch(url, {
...options,
headers,
signal: controller.signal
})
} finally {
clearTimeout(timeoutId)
}
}
async getCloudModels(): Promise<OllamaModel[]> {