tauri run fixes

This commit is contained in:
Peter Steinberger 2025-06-23 06:28:12 +02:00
parent ae4c8f5f1c
commit e526d18959
5 changed files with 114 additions and 49 deletions

View file

@ -1,6 +1,7 @@
use std::path::PathBuf; use std::path::PathBuf;
use std::process::Stdio; use std::process::Stdio;
use std::sync::Arc; use std::sync::Arc;
use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
use tokio::io::{AsyncBufReadExt, BufReader}; use tokio::io::{AsyncBufReadExt, BufReader};
use tokio::process::{Child, Command}; use tokio::process::{Child, Command};
use tokio::sync::RwLock; use tokio::sync::RwLock;
@ -264,6 +265,67 @@ impl NodeJsServer {
matches!(*self.state.read().await, ServerState::Running) matches!(*self.state.read().await, ServerState::Running)
} }
/// Handle server crash with recovery
pub async fn handle_crash(
&self,
exit_code: i32,
consecutive_crashes: Arc<AtomicU32>,
is_handling_crash: Arc<AtomicBool>,
crash_recovery_enabled: Arc<AtomicBool>,
) {
// Mark that we're handling a crash
is_handling_crash.store(true, Ordering::Relaxed);
warn!("Server crashed with exit code: {}", exit_code);
// Update state
*self.state.write().await = ServerState::Idle;
// Check if crash recovery is enabled
if !crash_recovery_enabled.load(Ordering::Relaxed) {
info!("Crash recovery disabled, not restarting");
is_handling_crash.store(false, Ordering::Relaxed);
return;
}
// Increment crash counter
let crashes = consecutive_crashes.fetch_add(1, Ordering::Relaxed) + 1;
// Check if we've crashed too many times
const MAX_CONSECUTIVE_CRASHES: u32 = 5;
if crashes >= MAX_CONSECUTIVE_CRASHES {
error!("Server crashed {} times consecutively, giving up", crashes);
is_handling_crash.store(false, Ordering::Relaxed);
return;
}
// Calculate backoff delay
let delay_secs = match crashes {
1 => 2,
2 => 4,
3 => 8,
4 => 16,
_ => 32,
};
info!("Restarting server after {} seconds (attempt {})", delay_secs, crashes);
tokio::time::sleep(tokio::time::Duration::from_secs(delay_secs)).await;
// Try to restart
match self.restart().await {
Ok(_) => {
info!("Server restarted successfully");
// Reset crash counter on successful restart
consecutive_crashes.store(0, Ordering::Relaxed);
}
Err(e) => {
error!("Failed to restart server: {}", e);
}
}
is_handling_crash.store(false, Ordering::Relaxed);
}
/// Get server state /// Get server state
pub async fn get_state(&self) -> ServerState { pub async fn get_state(&self) -> ServerState {
*self.state.read().await *self.state.read().await
@ -391,9 +453,9 @@ impl NodeJsServer {
/// Backend manager that handles the Node.js server /// Backend manager that handles the Node.js server
pub struct BackendManager { pub struct BackendManager {
server: Arc<NodeJsServer>, server: Arc<NodeJsServer>,
crash_recovery_enabled: Arc<RwLock<bool>>, crash_recovery_enabled: Arc<AtomicBool>,
consecutive_crashes: Arc<RwLock<u32>>, consecutive_crashes: Arc<AtomicU32>,
is_handling_crash: Arc<RwLock<bool>>, is_handling_crash: Arc<AtomicBool>,
} }
impl BackendManager { impl BackendManager {
@ -404,54 +466,52 @@ impl BackendManager {
"127.0.0.1".to_string(), "127.0.0.1".to_string(),
)); ));
let manager = Self { Self {
server: server.clone(), server,
crash_recovery_enabled: Arc::new(RwLock::new(true)), crash_recovery_enabled: Arc::new(AtomicBool::new(true)),
consecutive_crashes: Arc::new(RwLock::new(0)), consecutive_crashes: Arc::new(AtomicU32::new(0)),
is_handling_crash: Arc::new(RwLock::new(false)), is_handling_crash: Arc::new(AtomicBool::new(false)),
}; }
}
// Set up crash handler /// Start the backend server
let server_for_crash = server.clone(); pub async fn start(&self) -> Result<(), String> {
let consecutive_crashes = manager.consecutive_crashes.clone(); // Start the server first
let is_handling_crash = manager.is_handling_crash.clone(); let result = self.server.start().await;
let crash_recovery_enabled = manager.crash_recovery_enabled.clone();
tokio::spawn(async move { if result.is_ok() {
server_for_crash.set_on_crash(move |exit_code| { // Reset consecutive crashes on successful start
self.consecutive_crashes.store(0, Ordering::Relaxed);
// Set up crash handler after successful start
let consecutive_crashes = self.consecutive_crashes.clone();
let is_handling_crash = self.is_handling_crash.clone();
let crash_recovery_enabled = self.crash_recovery_enabled.clone();
let server = self.server.clone();
self.server.set_on_crash(move |exit_code| {
let consecutive_crashes = consecutive_crashes.clone(); let consecutive_crashes = consecutive_crashes.clone();
let is_handling_crash = is_handling_crash.clone(); let is_handling_crash = is_handling_crash.clone();
let crash_recovery_enabled = crash_recovery_enabled.clone(); let crash_recovery_enabled = crash_recovery_enabled.clone();
let server = server_for_crash.clone(); let server = server.clone();
tokio::spawn(async move { tokio::spawn(async move {
handle_server_crash( server.handle_crash(
exit_code, exit_code,
server,
consecutive_crashes, consecutive_crashes,
is_handling_crash, is_handling_crash,
crash_recovery_enabled, crash_recovery_enabled,
).await; ).await;
}); });
}).await; }).await;
});
manager
} }
/// Start the backend server
pub async fn start(&self) -> Result<(), String> {
// Reset consecutive crashes on successful start
let result = self.server.start().await;
if result.is_ok() {
*self.consecutive_crashes.write().await = 0;
}
result result
} }
/// Enable or disable crash recovery /// Enable or disable crash recovery
pub async fn set_crash_recovery_enabled(&self, enabled: bool) { pub async fn set_crash_recovery_enabled(&self, enabled: bool) {
*self.crash_recovery_enabled.write().await = enabled; self.crash_recovery_enabled.store(enabled, Ordering::Relaxed);
} }
/// Stop the backend server /// Stop the backend server

View file

@ -1057,6 +1057,9 @@ pub async fn get_update_history(
} }
// Backend Manager Commands // Backend Manager Commands
// Multi-backend commands - not applicable to our Node.js subprocess approach
// These would be used if we supported multiple backend types (Bun, Node, Deno, etc.)
/*
#[tauri::command] #[tauri::command]
pub async fn get_available_backends( pub async fn get_available_backends(
state: State<'_, AppState>, state: State<'_, AppState>,
@ -1177,6 +1180,7 @@ pub async fn get_backend_stats(
health_summary, health_summary,
}) })
} }
*/
// Debug Features Commands // Debug Features Commands
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]

View file

@ -1,12 +1,13 @@
pub mod api_client;
pub mod api_testing; pub mod api_testing;
pub mod app_mover; pub mod app_mover;
pub mod auth;
pub mod auth_cache; pub mod auth_cache;
pub mod auto_launch; pub mod auto_launch;
pub mod backend_manager; pub mod backend_manager;
pub mod cli_installer; pub mod cli_installer;
pub mod commands; pub mod commands;
pub mod debug_features; pub mod debug_features;
pub mod errors;
pub mod fs_api; pub mod fs_api;
pub mod keychain; pub mod keychain;
pub mod network_utils; pub mod network_utils;
@ -14,7 +15,6 @@ pub mod ngrok;
pub mod notification_manager; pub mod notification_manager;
pub mod permissions; pub mod permissions;
pub mod port_conflict; pub mod port_conflict;
pub mod server;
pub mod session_monitor; pub mod session_monitor;
pub mod settings; pub mod settings;
pub mod state; pub mod state;

View file

@ -294,17 +294,18 @@ fn main() {
update_updater_settings, update_updater_settings,
switch_update_channel, switch_update_channel,
get_update_history, get_update_history,
get_available_backends, // Multi-backend commands not applicable to Node.js subprocess
get_backend_config, // get_available_backends,
is_backend_installed, // get_backend_config,
install_backend, // is_backend_installed,
start_backend, // install_backend,
stop_backend, // start_backend,
switch_backend, // stop_backend,
get_active_backend, // switch_backend,
get_backend_instances, // get_active_backend,
check_backend_health, // get_backend_instances,
get_backend_stats, // check_backend_health,
// get_backend_stats,
get_debug_settings, get_debug_settings,
update_debug_settings, update_debug_settings,
log_debug_message, log_debug_message,

View file

@ -28,10 +28,10 @@
"icons/menu-bar-icon@2x.png", "icons/menu-bar-icon@2x.png",
"icons/tray-icon.png", "icons/tray-icon.png",
"icons/tray-icon@2x.png", "icons/tray-icon@2x.png",
"../web/native/vibetunnel*", "../../web/native/vibetunnel",
"../web/native/*.node", "../../web/native/*.node",
"../web/native/spawn-helper", "../../web/native/spawn-helper",
"../web/public/**/*" "../../web/public/**/*"
], ],
"macOS": { "macOS": {
"frameworks": [], "frameworks": [],