diff --git a/src/routers/http/router.rs b/src/routers/http/router.rs index f68e4b08..d8c72abe 100644 --- a/src/routers/http/router.rs +++ b/src/routers/http/router.rs @@ -338,11 +338,12 @@ impl Router { } fn select_first_worker(&self) -> Result { + // Prefer a healthy worker so proxy GETs (e.g. /v1/models) don't 500 + // when the first registered worker is temporarily down. let workers = self.worker_registry.get_all(); - if workers.is_empty() { - Err("No workers are available".to_string()) - } else { - Ok(workers[0].url().to_string()) + match workers.into_iter().find(|w| w.is_healthy()) { + Some(worker) => Ok(worker.url().to_string()), + None => Err("No healthy workers are available".to_string()), } } @@ -1828,6 +1829,30 @@ mod tests { assert!(url == "http://worker1:8080" || url == "http://worker2:8080"); } + #[test] + fn test_select_first_worker_skips_unhealthy() { + let router = create_test_regular_router(); + // Mark worker1 unhealthy; select_first_worker must not return it. + for w in router.worker_registry.get_all() { + if w.url() == "http://worker1:8080" { + w.set_healthy(false); + } + } + let result = router.select_first_worker(); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), "http://worker2:8080"); + } + + #[test] + fn test_select_first_worker_all_unhealthy() { + let router = create_test_regular_router(); + for w in router.worker_registry.get_all() { + w.set_healthy(false); + } + let result = router.select_first_worker(); + assert!(result.is_err()); + } + #[tokio::test] async fn test_wait_for_healthy_workers_empty_list() { // Empty list will return error immediately