Files
YANPM/apps/container/src/lib.rs
2025-12-22 14:32:57 +08:00

100 lines
2.7 KiB
Rust

pub mod containers;
mod env;
mod util;
use crate::{
containers::{
AgentConfigInfoType, ConfigInfoType, DBConfigInfoType, WithContainer, WithoutContainer,
},
util::{
await_termination_signal, remove_file_if_exists, stop_container, to_absolute_path,
write_env_files,
},
};
#[derive(Clone)]
pub struct Config {
pub database: DBConfigInfoType,
pub agent: Option<AgentConfigInfoType>,
}
// relative to the pwd
const API_CONFIG_PATH: &str = "../api/generated-config.yaml";
const DB_CONFIG_PATH: &str = "../../public/database/.env.generated";
pub struct DetachedHandle<'a> {
stopped: bool,
pub config: &'a Config,
}
impl<'a> DetachedHandle<'a> {
pub fn new(config: &'a Config) -> Self {
DetachedHandle {
stopped: false,
config,
}
}
pub async fn stop(&mut self) {
if self.stopped {
eprintln!("Attempted to stop an already stopped DetachedHandle.");
return;
}
self.stopped = true;
stop(self.config).await;
}
}
impl<'a> Drop for DetachedHandle<'a> {
fn drop(&mut self) {
if self.stopped {
return;
}
eprintln!(
"Warning: DetachedHandle was dropped without calling stop(). The container may still be running."
);
}
}
async fn start(config: &Config) {
// write the config files for the api server and database client
println!("Writing config files...");
write_env_files(&config.database, &config.agent);
println!("Config files written to:");
println!(" - {}", to_absolute_path(API_CONFIG_PATH).display());
println!(" - {}", to_absolute_path(DB_CONFIG_PATH).display());
}
async fn stop(config: &Config) {
// stop the container
println!("Stopping container...");
println!("Stopping database container...");
stop_container(&config.database, "database".to_string()).await;
if let Some(agent) = &config.agent {
println!("Stopping agent container...");
stop_container(agent, "agent".to_string()).await;
}
println!("Container stopped.");
// remove the generated config file
println!("Removing generated config file...");
remove_file_if_exists(DB_CONFIG_PATH);
remove_file_if_exists(API_CONFIG_PATH);
println!("Generated config files removed.");
}
pub async fn start_attached(config: &Config) {
start(config).await;
// wait for user input, ctrl+c, or other signals before exiting
println!("Press Ctrl+C, or send SIGTERM to stop the container...");
await_termination_signal().await;
stop(config).await;
}
#[must_use]
pub async fn start_detached(config: &'_ Config) -> DetachedHandle<'_> {
start(config).await;
DetachedHandle::new(config)
}