Add automatic daemon startup feature to client
- Client now checks if daemon is running and starts it if needed - Finds daemon binary based on client executable location - Waits for daemon to start up before continuing - Also implements proper handling of --shutdown flag - Improves user experience by removing need to manually start daemonmain
parent
39d7302a4e
commit
16720f5ad2
|
|
@ -3,7 +3,7 @@
|
|||
//! This is the client component of the Cypraea shell. It connects to the daemon,
|
||||
//! sends commands, and displays output to the user.
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use clap::Parser;
|
||||
use cypraea_common::paths;
|
||||
use cypraea_common::protocol::{ClientMessage, DaemonMessage};
|
||||
|
|
@ -66,13 +66,73 @@ async fn main() -> Result<()> {
|
|||
.to_string(),
|
||||
};
|
||||
|
||||
// Connect to the daemon
|
||||
let stream = UnixStream::connect(&socket_path)
|
||||
.await
|
||||
.context("Failed to connect to daemon")?;
|
||||
|
||||
// Handle shutdown request if specified
|
||||
if args.shutdown {
|
||||
// First try to connect to the daemon
|
||||
match UnixStream::connect(&socket_path).await {
|
||||
Ok(stream) => {
|
||||
info!("Connected to daemon at {}", socket_path);
|
||||
|
||||
// Send the shutdown message
|
||||
let mut writer = tokio::io::BufWriter::new(stream);
|
||||
let shutdown_msg = ClientMessage::Shutdown;
|
||||
send_message(&mut writer, &shutdown_msg).await
|
||||
.context("Failed to send shutdown message")?;
|
||||
|
||||
println!("Daemon shutdown requested");
|
||||
return Ok(());
|
||||
},
|
||||
Err(_) => {
|
||||
println!("No daemon running at {}", socket_path);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Try to connect to the daemon
|
||||
let stream = match UnixStream::connect(&socket_path).await {
|
||||
Ok(stream) => {
|
||||
info!("Connected to daemon at {}", socket_path);
|
||||
stream
|
||||
},
|
||||
Err(_e) => {
|
||||
// Daemon not running, try to start it
|
||||
info!("Daemon not running, attempting to start it");
|
||||
|
||||
// Find the daemon binary (should be in the same directory as the client)
|
||||
let current_exe = std::env::current_exe()
|
||||
.context("Failed to get current executable path")?;
|
||||
let daemon_dir = current_exe.parent()
|
||||
.context("Failed to get parent directory of current executable")?;
|
||||
let daemon_path = daemon_dir.join("cypraeadd");
|
||||
|
||||
if !daemon_path.exists() {
|
||||
return Err(anyhow!("Daemon binary not found at {}", daemon_path.display()));
|
||||
}
|
||||
|
||||
// Start the daemon process
|
||||
let _daemon_process = tokio::process::Command::new(&daemon_path)
|
||||
.stdout(std::process::Stdio::null())
|
||||
.stderr(std::process::Stdio::null())
|
||||
.spawn()
|
||||
.context("Failed to start daemon process")?;
|
||||
|
||||
// Give the daemon a moment to start up
|
||||
tokio::time::sleep(tokio::time::Duration::from_millis(500)).await;
|
||||
|
||||
// Try to connect again
|
||||
match UnixStream::connect(&socket_path).await {
|
||||
Ok(stream) => {
|
||||
info!("Successfully connected to newly started daemon");
|
||||
stream
|
||||
},
|
||||
Err(e) => {
|
||||
return Err(anyhow!("Failed to connect to daemon after starting it: {}", e));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Split the stream into reader and writer
|
||||
let (reader, writer) = tokio::io::split(stream);
|
||||
let mut reader = BufReader::new(reader);
|
||||
|
|
|
|||
Loading…
Reference in New Issue