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::process::Stdio;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
use tokio::io::{AsyncBufReadExt, BufReader};
use tokio::process::{Child, Command};
use tokio::sync::RwLock;
@ -264,6 +265,67 @@ impl NodeJsServer {
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
pub async fn get_state(&self) -> ServerState {
*self.state.read().await
@ -391,9 +453,9 @@ impl NodeJsServer {
/// Backend manager that handles the Node.js server
pub struct BackendManager {
server: Arc<NodeJsServer>,
crash_recovery_enabled: Arc<RwLock<bool>>,
consecutive_crashes: Arc<RwLock<u32>>,
is_handling_crash: Arc<RwLock<bool>>,
crash_recovery_enabled: Arc<AtomicBool>,
consecutive_crashes: Arc<AtomicU32>,
is_handling_crash: Arc<AtomicBool>,
}
impl BackendManager {
@ -404,54 +466,52 @@ impl BackendManager {
"127.0.0.1".to_string(),
));
let manager = Self {
server: server.clone(),
crash_recovery_enabled: Arc::new(RwLock::new(true)),
consecutive_crashes: Arc::new(RwLock::new(0)),
is_handling_crash: Arc::new(RwLock::new(false)),
};
Self {
server,
crash_recovery_enabled: Arc::new(AtomicBool::new(true)),
consecutive_crashes: Arc::new(AtomicU32::new(0)),
is_handling_crash: Arc::new(AtomicBool::new(false)),
}
}
/// Start the backend server
pub async fn start(&self) -> Result<(), String> {
// Start the server first
let result = self.server.start().await;
// Set up crash handler
let server_for_crash = server.clone();
let consecutive_crashes = manager.consecutive_crashes.clone();
let is_handling_crash = manager.is_handling_crash.clone();
let crash_recovery_enabled = manager.crash_recovery_enabled.clone();
tokio::spawn(async move {
server_for_crash.set_on_crash(move |exit_code| {
if result.is_ok() {
// 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 is_handling_crash = is_handling_crash.clone();
let crash_recovery_enabled = crash_recovery_enabled.clone();
let server = server_for_crash.clone();
let server = server.clone();
tokio::spawn(async move {
handle_server_crash(
server.handle_crash(
exit_code,
server,
consecutive_crashes,
is_handling_crash,
crash_recovery_enabled,
).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
}
/// Enable or disable crash recovery
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

View file

@ -1057,6 +1057,9 @@ pub async fn get_update_history(
}
// 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]
pub async fn get_available_backends(
state: State<'_, AppState>,
@ -1177,6 +1180,7 @@ pub async fn get_backend_stats(
health_summary,
})
}
*/
// Debug Features Commands
#[derive(Debug, Serialize, Deserialize)]

View file

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

View file

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

View file

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