mirror of
https://github.com/jamiepine/voicebox.git
synced 2026-09-18 22:30:40 -07:00
fix: address PR #319 review feedback — health validation, error handling, queryClient decoupling
- Rust: Replace fragile body.contains("status") with proper JSON
deserialization validating status=="healthy", model_loaded (bool),
and gpu_available (bool) to prevent misidentifying non-Voicebox services
- Frontend: Validate health response has Voicebox-specific fields before
marking server as ready during fallback polling
- Frontend: Discriminate port-in-use errors (poll for external server) from
real startup failures (missing sidecar, signing issues) — surface errors
immediately with a startupError state and Retry button in the UI
- Frontend: Set explicit startup-error state when 2-minute polling timeout
expires so the loading screen shows actionable feedback instead of hanging
- Architecture: Extract QueryClient to standalone side-effect-free module
(lib/queryClient.ts) to decouple serverStore from React bootstrap entrypoint
This commit is contained in:
@@ -55,9 +55,11 @@ fn find_voicebox_pid_on_port(port: u16) -> Option<u32> {
|
||||
|
||||
/// Check if a Voicebox server is responding on the given port.
|
||||
///
|
||||
/// Sends an HTTP GET to `/health` and returns `true` if the response
|
||||
/// contains the expected JSON field (`"status"`), confirming it's
|
||||
/// a Voicebox backend rather than an unrelated service.
|
||||
/// Sends an HTTP GET to `/health` and returns `true` only if the response
|
||||
/// is valid JSON matching the Voicebox `HealthResponse` schema — specifically
|
||||
/// `status` must be `"healthy"`, and both `model_loaded` and `gpu_available`
|
||||
/// must be present as booleans. This prevents misidentifying an unrelated
|
||||
/// service that happens to expose a `/health` endpoint.
|
||||
#[allow(dead_code)] // Used in platform-specific cfg blocks
|
||||
fn check_health(port: u16) -> bool {
|
||||
let url = format!("http://127.0.0.1:{}/health", port);
|
||||
@@ -70,9 +72,13 @@ fn check_health(port: u16) -> bool {
|
||||
if !resp.status().is_success() {
|
||||
return false;
|
||||
}
|
||||
// Verify the body looks like a Voicebox health response
|
||||
match resp.text() {
|
||||
Ok(body) => body.contains("status"),
|
||||
// Parse as JSON and validate Voicebox-specific fields
|
||||
match resp.json::<serde_json::Value>() {
|
||||
Ok(body) => {
|
||||
body.get("status").and_then(|v| v.as_str()) == Some("healthy")
|
||||
&& body.get("model_loaded").map(|v| v.is_boolean()).unwrap_or(false)
|
||||
&& body.get("gpu_available").map(|v| v.is_boolean()).unwrap_or(false)
|
||||
}
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user