mirror of
https://github.com/Xevion/banner.git
synced 2025-12-15 02:11:07 -06:00
feat: implement simple web service, improve ServiceManager encapsulation
This commit is contained in:
79
src/services/web.rs
Normal file
79
src/services/web.rs
Normal file
@@ -0,0 +1,79 @@
|
||||
use super::Service;
|
||||
use crate::web::routes::{BannerState, create_banner_router};
|
||||
use std::net::SocketAddr;
|
||||
use tokio::net::TcpListener;
|
||||
use tokio::sync::broadcast;
|
||||
use tracing::{debug, info, warn};
|
||||
|
||||
/// Web server service implementation
|
||||
pub struct WebService {
|
||||
port: u16,
|
||||
banner_state: BannerState,
|
||||
shutdown_tx: Option<broadcast::Sender<()>>,
|
||||
}
|
||||
|
||||
impl WebService {
|
||||
pub fn new(port: u16, banner_state: BannerState) -> Self {
|
||||
Self {
|
||||
port,
|
||||
banner_state,
|
||||
shutdown_tx: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl Service for WebService {
|
||||
fn name(&self) -> &'static str {
|
||||
"web"
|
||||
}
|
||||
|
||||
async fn run(&mut self) -> Result<(), anyhow::Error> {
|
||||
// Create the main router with Banner API routes
|
||||
let app = create_banner_router(self.banner_state.clone());
|
||||
|
||||
let addr = SocketAddr::from(([0, 0, 0, 0], self.port));
|
||||
info!(
|
||||
service = "web",
|
||||
link = format!("http://localhost:{}", addr.port()),
|
||||
"Starting web server",
|
||||
);
|
||||
|
||||
let listener = TcpListener::bind(addr).await?;
|
||||
debug!(
|
||||
service = "web",
|
||||
"Web server listening on {}",
|
||||
format!("http://{}", addr)
|
||||
);
|
||||
|
||||
// Create internal shutdown channel for axum graceful shutdown
|
||||
let (shutdown_tx, mut shutdown_rx) = broadcast::channel(1);
|
||||
self.shutdown_tx = Some(shutdown_tx);
|
||||
|
||||
// Use axum's graceful shutdown with the internal shutdown signal
|
||||
axum::serve(listener, app)
|
||||
.with_graceful_shutdown(async move {
|
||||
let _ = shutdown_rx.recv().await;
|
||||
debug!(
|
||||
service = "web",
|
||||
"Received shutdown signal, starting graceful shutdown"
|
||||
);
|
||||
})
|
||||
.await?;
|
||||
|
||||
info!(service = "web", "Web server stopped");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn shutdown(&mut self) -> Result<(), anyhow::Error> {
|
||||
if let Some(shutdown_tx) = self.shutdown_tx.take() {
|
||||
let _ = shutdown_tx.send(());
|
||||
} else {
|
||||
warn!(
|
||||
service = "web",
|
||||
"No shutdown channel found, cannot trigger graceful shutdown"
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user