Add timeouts and improve health checks

Changes:
- Health checks now have 5 second timeout (was no timeout)
- Chat requests have 120 second timeout (was no timeout)
- Health checks verify response body structure, not just status code
- Ollama: Verifies 'models' field exists in /api/tags response
- OpenAI: Verifies 'data' field exists in /models response

This prevents false-positive health checks where the endpoint
responds but actual API calls timeout (524 Gateway Timeout).

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
2026-03-19 15:37:21 +01:00
parent 9f1b5f908d
commit dadc178fd6
2 changed files with 23 additions and 3 deletions

View File

@@ -98,9 +98,20 @@ impl Provider for OllamaProvider {
} }
async fn health_check(&self) -> Result<bool> { async fn health_check(&self) -> Result<bool> {
// First check if the API is reachable
let url = format!("{}/api/tags", self.base_url); let url = format!("{}/api/tags", self.base_url);
let response = self.apply_auth(self.client.get(&url)).send().await?; let response = self.apply_auth(self.client.get(&url))
Ok(response.status().is_success()) .timeout(std::time::Duration::from_secs(5))
.send()
.await?;
if !response.status().is_success() {
return Ok(false);
}
// Also verify we can parse the response (deeper health check)
let body: serde_json::Value = response.json().await?;
Ok(body.get("models").is_some())
} }
async fn list_models(&self) -> Result<Vec<String>> { async fn list_models(&self) -> Result<Vec<String>> {
@@ -159,6 +170,7 @@ impl Provider for OllamaProvider {
self.client self.client
.post(&url) .post(&url)
.header("Content-Type", "application/json") .header("Content-Type", "application/json")
.timeout(std::time::Duration::from_secs(120)) // 2 minute timeout for chat
) )
.json(&ollama_request) .json(&ollama_request)
.send() .send()

View File

@@ -49,10 +49,17 @@ impl Provider for OpenAiProvider {
.client .client
.get(&url) .get(&url)
.header("Authorization", format!("Bearer {}", self.api_key)) .header("Authorization", format!("Bearer {}", self.api_key))
.timeout(std::time::Duration::from_secs(5))
.send() .send()
.await?; .await?;
Ok(response.status().is_success()) if !response.status().is_success() {
return Ok(false);
}
// Verify we can parse the response
let body: serde_json::Value = response.json().await?;
Ok(body.get("data").is_some())
} }
async fn list_models(&self) -> Result<Vec<String>> { async fn list_models(&self) -> Result<Vec<String>> {
@@ -152,6 +159,7 @@ impl Provider for OpenAiProvider {
.post(&url) .post(&url)
.header("Authorization", format!("Bearer {}", self.api_key)) .header("Authorization", format!("Bearer {}", self.api_key))
.header("Content-Type", "application/json") .header("Content-Type", "application/json")
.timeout(std::time::Duration::from_secs(120)) // 2 minute timeout for chat
.json(&req_body) .json(&req_body)
.send() .send()
.await?; .await?;