Initial commit: Rust YpDaemon
This commit is contained in:
186
src/main.rs
Normal file
186
src/main.rs
Normal file
@@ -0,0 +1,186 @@
|
||||
mod config;
|
||||
mod db;
|
||||
mod message_broker;
|
||||
mod worker;
|
||||
mod websocket_server;
|
||||
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
use config::Config;
|
||||
use libsystemd::daemon::{self, NotifyState};
|
||||
use message_broker::MessageBroker;
|
||||
use websocket_server::WebSocketServer;
|
||||
use worker::{
|
||||
CharacterCreationWorker, ConnectionPool, DirectorWorker, HouseWorker, PoliticsWorker,
|
||||
ProduceWorker, StockageManager, UndergroundWorker, UserCharacterWorker,
|
||||
ValueRecalculationWorker, Worker,
|
||||
};
|
||||
|
||||
static KEEP_RUNNING: AtomicBool = AtomicBool::new(true);
|
||||
|
||||
fn main() {
|
||||
if let Err(err) = run_daemon() {
|
||||
eprintln!("Fehler im Daemon: {err}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
fn run_daemon() -> Result<(), Box<dyn std::error::Error>> {
|
||||
install_signal_handler()?;
|
||||
|
||||
let config = load_config()?;
|
||||
let pool = create_connection_pool(&config)?;
|
||||
let websocket_config = load_websocket_config(&config)?;
|
||||
|
||||
let broker = MessageBroker::new();
|
||||
let mut websocket_server = WebSocketServer::new(
|
||||
websocket_config.port,
|
||||
pool.clone(),
|
||||
broker.clone(),
|
||||
websocket_config.ssl_enabled,
|
||||
websocket_config.cert_path,
|
||||
websocket_config.key_path,
|
||||
);
|
||||
|
||||
let mut workers = create_workers(pool, broker.clone());
|
||||
|
||||
websocket_server.set_workers(&workers);
|
||||
start_system(&mut websocket_server, &mut workers, &broker);
|
||||
|
||||
// systemd: melden, dass der Dienst jetzt "bereit" ist
|
||||
let _ = daemon::notify(false, &[NotifyState::Ready]);
|
||||
|
||||
run_main_loop();
|
||||
|
||||
shutdown_system(&mut websocket_server, &mut workers, &broker);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn install_signal_handler() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Behandle SIGINT/SIGTERM (z.B. Strg+C) und leite auf das globale Flag um.
|
||||
ctrlc::set_handler(|| {
|
||||
KEEP_RUNNING.store(false, Ordering::SeqCst);
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
struct WebSocketConfig {
|
||||
port: u16,
|
||||
ssl_enabled: bool,
|
||||
cert_path: Option<String>,
|
||||
key_path: Option<String>,
|
||||
}
|
||||
|
||||
fn load_config() -> Result<Config, Box<dyn std::error::Error>> {
|
||||
// Pfad später ggf. konfigurierbar machen
|
||||
let config = Config::from_file("/etc/yourpart/daemon.conf")?;
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
fn create_connection_pool(config: &Config) -> Result<ConnectionPool, Box<dyn std::error::Error>> {
|
||||
let host = config.get("DB_HOST")?;
|
||||
let port = config.get("DB_PORT")?;
|
||||
let name = config.get("DB_NAME")?;
|
||||
let user = config.get("DB_USER")?;
|
||||
let password = config.get("DB_PASSWORD")?;
|
||||
|
||||
let conn_str = format!(
|
||||
"host={} port={} dbname={} user={} password={}",
|
||||
host, port, name, user, password
|
||||
);
|
||||
|
||||
// Pool-Größe analog zur C++-Implementierung
|
||||
let pool = db::ConnectionPool::new(conn_str, 10)?;
|
||||
Ok(pool)
|
||||
}
|
||||
|
||||
fn load_websocket_config(config: &Config) -> Result<WebSocketConfig, Box<dyn std::error::Error>> {
|
||||
let port: u16 = config.get("WEBSOCKET_PORT")?.parse()?;
|
||||
let ssl_enabled =
|
||||
config.get("WEBSOCKET_SSL_ENABLED").unwrap_or_else(|_| "false".into()) == "true";
|
||||
|
||||
let cert_path = if ssl_enabled {
|
||||
Some(config.get("WEBSOCKET_SSL_CERT_PATH")?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let key_path = if ssl_enabled {
|
||||
Some(config.get("WEBSOCKET_SSL_KEY_PATH")?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(WebSocketConfig {
|
||||
port,
|
||||
ssl_enabled,
|
||||
cert_path,
|
||||
key_path,
|
||||
})
|
||||
}
|
||||
|
||||
fn create_workers(pool: ConnectionPool, broker: MessageBroker) -> Vec<Box<dyn Worker>> {
|
||||
vec![
|
||||
Box::new(CharacterCreationWorker::new(pool.clone(), broker.clone())),
|
||||
Box::new(ProduceWorker::new(pool.clone(), broker.clone())),
|
||||
Box::new(StockageManager::new(pool.clone(), broker.clone())),
|
||||
Box::new(DirectorWorker::new(pool.clone(), broker.clone())),
|
||||
Box::new(ValueRecalculationWorker::new(
|
||||
pool.clone(),
|
||||
broker.clone(),
|
||||
)),
|
||||
Box::new(UserCharacterWorker::new(
|
||||
pool.clone(),
|
||||
broker.clone(),
|
||||
)),
|
||||
Box::new(HouseWorker::new(pool.clone(), broker.clone())),
|
||||
Box::new(PoliticsWorker::new(pool.clone(), broker.clone())),
|
||||
Box::new(UndergroundWorker::new(pool, broker)),
|
||||
]
|
||||
}
|
||||
|
||||
fn start_system(
|
||||
websocket_server: &mut WebSocketServer,
|
||||
workers: &mut [Box<dyn Worker>],
|
||||
broker: &MessageBroker,
|
||||
) {
|
||||
broker.start();
|
||||
websocket_server.run();
|
||||
|
||||
for worker in workers {
|
||||
worker.start_worker_thread();
|
||||
worker.enable_watchdog();
|
||||
}
|
||||
}
|
||||
|
||||
fn shutdown_system(
|
||||
websocket_server: &mut WebSocketServer,
|
||||
workers: &mut [Box<dyn Worker>],
|
||||
broker: &MessageBroker,
|
||||
) {
|
||||
// systemd: wir fahren nun kontrolliert herunter
|
||||
let _ = daemon::notify(false, &[NotifyState::Stopping]);
|
||||
|
||||
// 1) Worker stoppen – sie prüfen regelmäßig ihr `running_worker`-Flag und
|
||||
// brechen daher auch bei längeren Work-Intervallen zügig ab.
|
||||
for worker in workers {
|
||||
worker.stop_worker_thread();
|
||||
}
|
||||
|
||||
// 2) WebSocket-Server stoppen (Tokio-Runtime herunterfahren)
|
||||
websocket_server.stop();
|
||||
|
||||
// 3) MessageBroker-Hook – aktuell noch Stub, aber hier zentral ergänzt
|
||||
// für eine spätere interne Queue/Thread-Implementierung.
|
||||
broker.stop();
|
||||
}
|
||||
|
||||
fn run_main_loop() {
|
||||
while KEEP_RUNNING.load(Ordering::Relaxed) {
|
||||
thread::sleep(Duration::from_millis(100));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user