use colored::*;
use std::sync::{
Arc,
atomic::{AtomicUsize, Ordering},
};
use tokio::net::TcpListener;
use tokio::sync::broadcast;
use tokio::time::{Duration, sleep};
use crate::core::connection::handle_connection;
use crate::routing::trie::Router;
use crate::utils::reloader::HotReloader;
pub async fn run_server(host: &str, port: &str, router: Router, use_reloader: bool) {
if use_reloader {
HotReloader::start();
if std::env::var("RUNNING_UNDER_RELOADER").is_err() {
std::process::exit(0);
}
}
let listener = TcpListener::bind(format!("{}:{}", host, port))
.await
.unwrap();
println!(
"{} {}:{}",
"[GRITSHIELD] Server Online at".green().bold(),
host,
port
);
let router = Arc::new(router);
let (shutdown_tx, _) = broadcast::channel::<()>(1);
let active_connections = Arc::new(AtomicUsize::new(0));
loop {
tokio::select! {
_ = tokio::signal::ctrl_c() => {
println!(
"{}",
"[GRITSHIELD] Shutdown signal received"
.yellow()
.bold()
);
let _ = shutdown_tx.send(());
break;
}
accept_result = listener.accept() => {
match accept_result {
Ok((stream, peer_addr)) => {
active_connections
.fetch_add(1, Ordering::SeqCst);
let router =
Arc::clone(&router);
let active_connections =
Arc::clone(&active_connections);
let mut shutdown_rx =
shutdown_tx.subscribe();
tokio::spawn(async move {
tokio::select! {
_ = shutdown_rx.recv() => {
}
_ = handle_connection(
stream,
peer_addr,
router
) => {
}
}
active_connections.fetch_sub(
1,
Ordering::SeqCst
);
});
}
Err(e) => {
eprintln!(
"Accept error: {}",
e
);
}
}
}
}
}
println!("{}", "[GRITSHIELD] Draining active connections...".yellow());
while active_connections.load(Ordering::SeqCst) > 0 {
sleep(Duration::from_millis(100)).await;
}
println!("{}", "[GRITSHIELD] Shutdown complete".green().bold());
}