use std::path::PathBuf;
use std::process;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
#[derive(Debug)]
pub struct ServerResources {
base_dir: PathBuf,
quit_flag: Arc<AtomicBool>,
}
impl ServerResources {
pub fn new(base_dir: PathBuf) -> Self {
log::debug!(
"Creating ServerResources with base_dir: {}",
base_dir.display()
);
Self {
base_dir,
quit_flag: Arc::new(AtomicBool::new(false)),
}
}
pub fn setup_signal_handler(&self) -> Result<(), Box<dyn std::error::Error>> {
let quit = self.quit_flag.clone();
let base_dir = self.base_dir.clone();
ctrlc::set_handler(move || {
log::info!("SIGINT/SIGTERM received, initiating graceful shutdown");
quit.store(true, Ordering::Relaxed);
cleanup_base_dir(&base_dir);
process::exit(0);
})?;
log::debug!("Signal handler installed successfully");
Ok(())
}
pub fn should_quit(&self) -> bool {
self.quit_flag.load(Ordering::Relaxed)
}
pub fn quit_flag(&self) -> Arc<AtomicBool> {
self.quit_flag.clone()
}
}
fn cleanup_base_dir(base_dir: &PathBuf) {
if base_dir.exists() {
if let Err(e) = std::fs::remove_dir_all(base_dir) {
log::warn!("Failed to remove base_dir {}: {}", base_dir.display(), e);
} else {
log::debug!("Removed base_dir: {}", base_dir.display());
}
}
}
impl Drop for ServerResources {
fn drop(&mut self) {
log::info!("Cleaning up server resources");
cleanup_base_dir(&self.base_dir);
log::info!("Server cleanup complete");
}
}