From 0f3cb12c7ada09d2ad579789bae52e31bd2bfbff Mon Sep 17 00:00:00 2001 From: perf3ct Date: Wed, 2 Jul 2025 02:26:11 +0000 Subject: [PATCH] fix(server): resolve NUMERIC db type and f64 rust type --- src/routes/documents_ocr_retry.rs | 22 ++++++- src/services/ocr_retry_service.rs | 11 +++- tests/integration_ocr_retry_tests.rs | 85 ++++++++++++++++++++++------ 3 files changed, 98 insertions(+), 20 deletions(-) diff --git a/src/routes/documents_ocr_retry.rs b/src/routes/documents_ocr_retry.rs index ffc598b..92baf64 100644 --- a/src/routes/documents_ocr_retry.rs +++ b/src/routes/documents_ocr_retry.rs @@ -335,10 +335,19 @@ pub async fn get_ocr_retry_stats( let failure_reasons: Vec = failure_stats.into_iter() .map(|row| { + // Handle NUMERIC type from database by trying different types + let avg_file_size_mb = if let Ok(val) = row.try_get::("avg_file_size") { + val / 1_048_576.0 + } else if let Ok(val) = row.try_get::("avg_file_size") { + val as f64 / 1_048_576.0 + } else { + 0.0 + }; + serde_json::json!({ "reason": row.get::, _>("ocr_failure_reason").unwrap_or_else(|| "unknown".to_string()), "count": row.get::("count"), - "avg_file_size_mb": row.get::, _>("avg_file_size").unwrap_or(0.0) / 1_048_576.0, + "avg_file_size_mb": avg_file_size_mb, "first_occurrence": row.get::, _>("first_occurrence"), "last_occurrence": row.get::, _>("last_occurrence"), }) @@ -347,10 +356,19 @@ pub async fn get_ocr_retry_stats( let file_types: Vec = type_stats.into_iter() .map(|row| { + // Handle NUMERIC type from database by trying different types + let avg_file_size_mb = if let Ok(val) = row.try_get::("avg_file_size") { + val / 1_048_576.0 + } else if let Ok(val) = row.try_get::("avg_file_size") { + val as f64 / 1_048_576.0 + } else { + 0.0 + }; + serde_json::json!({ "mime_type": row.get::("mime_type"), "count": row.get::("count"), - "avg_file_size_mb": row.get::, _>("avg_file_size").unwrap_or(0.0) / 1_048_576.0, + "avg_file_size_mb": avg_file_size_mb, }) }) .collect(); diff --git a/src/services/ocr_retry_service.rs b/src/services/ocr_retry_service.rs index ff7f957..737720b 100644 --- a/src/services/ocr_retry_service.rs +++ b/src/services/ocr_retry_service.rs @@ -306,7 +306,16 @@ impl OcrRetryService { .map(|row| FailureStatistic { reason: row.get::("reason"), count: row.get::("count"), - avg_file_size_mb: row.get::, _>("avg_file_size").unwrap_or(0.0) / 1_048_576.0, + avg_file_size_mb: { + // Handle NUMERIC type from database by trying different types + if let Ok(val) = row.try_get::("avg_file_size") { + val / 1_048_576.0 + } else if let Ok(val) = row.try_get::("avg_file_size") { + val as f64 / 1_048_576.0 + } else { + 0.0 + } + }, recent_failures: row.get::("recent_failures"), }) .collect(); diff --git a/tests/integration_ocr_retry_tests.rs b/tests/integration_ocr_retry_tests.rs index 878ad2a..b19fccc 100644 --- a/tests/integration_ocr_retry_tests.rs +++ b/tests/integration_ocr_retry_tests.rs @@ -20,16 +20,30 @@ impl OcrRetryTestHelper { async fn new() -> Result> { let client = Client::new(); - // First check if server is running + // First check if server is running with better error handling let health_check = client .get(&format!("{}/api/health", get_base_url())) - .timeout(Duration::from_secs(5)) + .timeout(Duration::from_secs(10)) .send() .await; - if let Err(e) = health_check { - eprintln!("Health check failed: {}. Is the server running at {}?", e, get_base_url()); - return Err(format!("Server not running: {}", e).into()); + match health_check { + Ok(response) => { + if !response.status().is_success() { + let status = response.status(); + let text = response.text().await.unwrap_or_else(|_| "Unable to read response".to_string()); + return Err(format!("Health check failed with status {}: {}. Is the server running at {}?", status, text, get_base_url()).into()); + } + println!("✅ Server health check passed at {}", get_base_url()); + } + Err(e) => { + eprintln!("❌ Cannot connect to server at {}: {}", get_base_url(), e); + eprintln!("💡 To run integration tests, start the server first:"); + eprintln!(" cargo run"); + eprintln!(" Then run tests in another terminal:"); + eprintln!(" cargo test --test integration_ocr_retry_tests"); + return Err(format!("Server not reachable: {}", e).into()); + } } // Create a test admin user @@ -96,12 +110,23 @@ impl OcrRetryTestHelper { .send() .await?; - if !response.status().is_success() { - return Err(format!("Failed to get retry stats: {}", response.text().await?).into()); + let status = response.status(); + let response_text = response.text().await?; + + if !status.is_success() { + return Err(format!("Failed to get retry stats (status {}): {}", status, response_text).into()); } - let result: Value = response.json().await?; - Ok(result) + // Try to parse the JSON and provide better error messages + match serde_json::from_str::(&response_text) { + Ok(result) => Ok(result), + Err(e) => { + eprintln!("JSON parsing failed for retry stats response:"); + eprintln!("Status: {}", status); + eprintln!("Response text: {}", response_text); + Err(format!("Failed to parse JSON response: {}. Raw response: {}", e, response_text).into()) + } + } } async fn get_retry_recommendations(&self) -> Result> { @@ -112,12 +137,23 @@ impl OcrRetryTestHelper { .send() .await?; - if !response.status().is_success() { - return Err(format!("Failed to get retry recommendations: {}", response.text().await?).into()); + let status = response.status(); + let response_text = response.text().await?; + + if !status.is_success() { + return Err(format!("Failed to get retry recommendations (status {}): {}", status, response_text).into()); } - let result: Value = response.json().await?; - Ok(result) + // Try to parse the JSON and provide better error messages + match serde_json::from_str::(&response_text) { + Ok(result) => Ok(result), + Err(e) => { + eprintln!("JSON parsing failed for retry recommendations response:"); + eprintln!("Status: {}", status); + eprintln!("Response text: {}", response_text); + Err(format!("Failed to parse JSON response: {}. Raw response: {}", e, response_text).into()) + } + } } async fn bulk_retry_ocr(&self, mode: &str, document_ids: Option>, preview_only: bool) -> Result> { @@ -138,12 +174,23 @@ impl OcrRetryTestHelper { .send() .await?; - if !response.status().is_success() { - return Err(format!("Failed to bulk retry OCR: {}", response.text().await?).into()); + let status = response.status(); + let response_text = response.text().await?; + + if !status.is_success() { + return Err(format!("Failed to bulk retry OCR (status {}): {}", status, response_text).into()); } - let result: Value = response.json().await?; - Ok(result) + // Try to parse the JSON and provide better error messages + match serde_json::from_str::(&response_text) { + Ok(result) => Ok(result), + Err(e) => { + eprintln!("JSON parsing failed for bulk retry response:"); + eprintln!("Status: {}", status); + eprintln!("Response text: {}", response_text); + Err(format!("Failed to parse JSON response: {}. Raw response: {}", e, response_text).into()) + } + } } async fn get_document_retry_history(&self, document_id: &str) -> Result> { @@ -203,6 +250,7 @@ async fn test_ocr_retry_stats_endpoint() { } Err(e) => { println!("❌ OCR retry stats test failed: {}", e); + println!("💡 This might indicate a server issue or missing endpoint implementation"); panic!("OCR retry stats endpoint failed: {}", e); } } @@ -240,6 +288,7 @@ async fn test_ocr_retry_recommendations_endpoint() { } Err(e) => { println!("❌ OCR retry recommendations test failed: {}", e); + println!("💡 This might indicate a server issue or missing endpoint implementation"); panic!("OCR retry recommendations endpoint failed: {}", e); } } @@ -274,6 +323,7 @@ async fn test_bulk_retry_preview_mode() { } Err(e) => { println!("❌ Bulk retry preview test failed: {}", e); + println!("💡 This might indicate a server issue or missing endpoint implementation"); panic!("Bulk retry preview failed: {}", e); } } @@ -319,6 +369,7 @@ async fn test_document_retry_history() { } Err(e) => { println!("❌ Document retry history test failed: {}", e); + println!("💡 This might indicate a server issue or missing endpoint implementation"); panic!("Document retry history failed: {}", e); } }