From 2026bf53052210ebdbff118a1036db52ab0b7372 Mon Sep 17 00:00:00 2001 From: Leopere Date: Sun, 15 Feb 2026 11:49:37 -0500 Subject: [PATCH] Move startup camera test to background thread Server starts accepting requests immediately instead of blocking on the camera test. If the camera lock is held by a previous process, the server is still reachable and will attempt live camera access on each request independently. Co-authored-by: Cursor --- src/main.rs | 64 ++++++++++++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/src/main.rs b/src/main.rs index e38be6f..5a3dfe4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -53,39 +53,43 @@ async fn main() -> Result<(), Box> { .unwrap_or(DEFAULT_PORT); let config = CameraConfig::from_env(); - // Test camera access at startup (informational only). - println!("Testing camera access..."); - match test_camera(&config) { - Ok((actual_w, actual_h, frame_size)) => { - let conditioned_per_frame = (frame_size / CHUNK_SIZE) * 32; - let throughput_30fps = conditioned_per_frame * 30; - let raw_mbps = (frame_size as f64 * 30.0 * 8.0) / 1_000_000.0; - let conditioned_kbs = throughput_30fps / 1_000; - println!( - "Camera OK: {}x{}, {} KB/frame ({} bytes)", - actual_w, actual_h, frame_size / 1024, frame_size - ); - if raw_mbps >= 1000.0 { - println!("Throughput: {:.1} Gbps raw, ~{} MB/s conditioned @ 30fps", - raw_mbps / 1000.0, throughput_30fps / 1_000_000); - } else { - println!("Throughput: {:.0} Mbps raw, ~{} KB/s conditioned @ 30fps", - raw_mbps, conditioned_kbs); - } - println!("Ensure lens is covered for optimal quantum noise capture"); - } - Err(e) => { - eprintln!( - "Camera error: {}. Requests will fail until camera is available.", - e - ); - if e.contains("Lock Rejected") || e.contains("lock") { - eprintln!( - " → To release camera: ./scripts/release-camera.sh then restart." + // Test camera access at startup (informational only, non-blocking). + // Server starts immediately; the camera test runs in the background. + let startup_config = config.clone(); + std::thread::spawn(move || { + println!("Testing camera access..."); + match test_camera(&startup_config) { + Ok((actual_w, actual_h, frame_size)) => { + let conditioned_per_frame = (frame_size / CHUNK_SIZE) * 32; + let throughput_30fps = conditioned_per_frame * 30; + let raw_mbps = (frame_size as f64 * 30.0 * 8.0) / 1_000_000.0; + let conditioned_kbs = throughput_30fps / 1_000; + println!( + "Camera OK: {}x{}, {} KB/frame ({} bytes)", + actual_w, actual_h, frame_size / 1024, frame_size ); + if raw_mbps >= 1000.0 { + println!("Throughput: {:.1} Gbps raw, ~{} MB/s conditioned @ 30fps", + raw_mbps / 1000.0, throughput_30fps / 1_000_000); + } else { + println!("Throughput: {:.0} Mbps raw, ~{} KB/s conditioned @ 30fps", + raw_mbps, conditioned_kbs); + } + println!("Ensure lens is covered for optimal quantum noise capture"); + } + Err(e) => { + eprintln!( + "Camera warning: {}. Requests will fail until camera is available.", + e + ); + if e.contains("Lock Rejected") || e.contains("lock") { + eprintln!( + " → To release camera: ./scripts/release-camera.sh then restart." + ); + } } } - } + }); let app = Router::new() .route("/", get(index))