11// REST API handlers and routes
22
3+ use infera_management_core:: ManagementConfig ;
4+ use infera_management_grpc:: ServerApiClient ;
5+ use infera_management_storage:: Backend ;
6+ use std:: sync:: Arc ;
7+ use tracing:: info;
8+
39pub mod audit;
410pub mod handlers;
511pub mod middleware;
@@ -15,3 +21,79 @@ pub use middleware::{
1521} ;
1622pub use pagination:: { Paginated , PaginationMeta , PaginationParams , PaginationQuery } ;
1723pub use routes:: create_router_with_state;
24+
25+ /// Graceful shutdown signal handler
26+ async fn shutdown_signal ( ) {
27+ use tokio:: signal;
28+
29+ let ctrl_c = async {
30+ signal:: ctrl_c ( )
31+ . await
32+ . expect ( "failed to install Ctrl+C handler" ) ;
33+ } ;
34+
35+ #[ cfg( unix) ]
36+ let terminate = async {
37+ signal:: unix:: signal ( signal:: unix:: SignalKind :: terminate ( ) )
38+ . expect ( "failed to install SIGTERM handler" )
39+ . recv ( )
40+ . await ;
41+ } ;
42+
43+ #[ cfg( not( unix) ) ]
44+ let terminate = std:: future:: pending :: < ( ) > ( ) ;
45+
46+ tokio:: select! {
47+ _ = ctrl_c => {
48+ info!( "Received Ctrl+C signal, initiating shutdown" ) ;
49+ }
50+ _ = terminate => {
51+ info!( "Received SIGTERM signal, initiating shutdown" ) ;
52+ }
53+ }
54+ }
55+
56+ /// Start the Management API HTTP server
57+ pub async fn serve (
58+ storage : Arc < Backend > ,
59+ config : Arc < ManagementConfig > ,
60+ server_client : Arc < ServerApiClient > ,
61+ worker_id : u16 ,
62+ leader : Option < Arc < infera_management_core:: LeaderElection < Backend > > > ,
63+ email_service : Option < Arc < infera_management_core:: EmailService > > ,
64+ ) -> anyhow:: Result < ( ) > {
65+ // Create AppState with services
66+ let state = AppState :: new (
67+ storage,
68+ config. clone ( ) ,
69+ server_client,
70+ worker_id,
71+ leader,
72+ email_service,
73+ ) ;
74+
75+ let app = create_router_with_state ( state) ;
76+
77+ let addr = format ! ( "{}:{}" , config. server. http_host, config. server. http_port) ;
78+ info ! ( "Starting Management API HTTP server on {}" , addr) ;
79+
80+ let listener = tokio:: net:: TcpListener :: bind ( & addr) . await ?;
81+
82+ // Setup graceful shutdown
83+ let ( shutdown_tx, shutdown_rx) = tokio:: sync:: oneshot:: channel :: < ( ) > ( ) ;
84+
85+ // Spawn task to handle shutdown signals
86+ tokio:: spawn ( async move {
87+ shutdown_signal ( ) . await ;
88+ let _ = shutdown_tx. send ( ( ) ) ;
89+ } ) ;
90+
91+ // Serve with graceful shutdown
92+ axum:: serve ( listener, app)
93+ . with_graceful_shutdown ( async {
94+ shutdown_rx. await . ok ( ) ;
95+ } )
96+ . await ?;
97+
98+ Ok ( ( ) )
99+ }
0 commit comments