@@ -17,7 +17,9 @@ use std::net::SocketAddr;
1717use std:: sync:: Arc ;
1818use std:: time:: Duration ;
1919
20- use mea:: latch:: Latch ;
20+ use fastimer:: schedule:: SimpleActionExt ;
21+ use mea:: shutdown:: ShutdownRecv ;
22+ use mea:: shutdown:: ShutdownSend ;
2123use mea:: waitgroup:: WaitGroup ;
2224use percas_core:: ServerConfig ;
2325use percas_metrics:: GlobalMetrics ;
@@ -40,6 +42,9 @@ use poem::web::Path;
4042use poem:: web:: headers:: ContentType ;
4143
4244use crate :: PercasContext ;
45+ use crate :: runtime:: Runtime ;
46+ use crate :: runtime:: timer;
47+ use crate :: scheduled:: ReportMetricsAction ;
4348
4449struct LoggerMiddleware ;
4550
@@ -83,25 +88,28 @@ pub(crate) type ServerFuture<T> = tokio::task::JoinHandle<Result<T, io::Error>>;
8388pub struct ServerState {
8489 server_advertise_addr : SocketAddr ,
8590 server_fut : ServerFuture < ( ) > ,
86- shutdown : Arc < Latch > ,
91+
92+ shutdown_rx_server : ShutdownRecv ,
93+ shutdown_tx_actions : Vec < ShutdownSend > ,
8794}
8895
8996impl ServerState {
9097 pub fn server_advertise_addr ( & self ) -> SocketAddr {
9198 self . server_advertise_addr
9299 }
93100
94- pub fn shutdown_handle ( & self ) -> impl Fn ( ) {
95- let shutdown = self . shutdown . clone ( ) ;
96- move || shutdown. count_down ( )
97- }
101+ pub async fn await_shutdown ( self ) {
102+ self . shutdown_rx_server . is_shutdown ( ) . await ;
98103
99- pub fn shutdown ( & self ) {
100- self . shutdown_handle ( ) ( ) ;
101- }
104+ log:: info!( "percas server is shutting down" ) ;
102105
103- pub async fn await_shutdown ( self ) {
104- self . shutdown . wait ( ) . await ;
106+ for shutdown in self . shutdown_tx_actions . iter ( ) {
107+ shutdown. shutdown ( ) ;
108+ }
109+ for shutdown in self . shutdown_tx_actions {
110+ shutdown. await_shutdown ( ) . await ;
111+ }
112+ log:: info!( "percas actions shutdown" ) ;
105113
106114 match self . server_fut . await {
107115 Ok ( _) => log:: info!( "percas server stopped." ) ,
@@ -111,10 +119,12 @@ impl ServerState {
111119}
112120
113121pub async fn start_server (
122+ rt : & Runtime ,
114123 config : & ServerConfig ,
115124 ctx : Arc < PercasContext > ,
116- ) -> Result < ServerState , io:: Error > {
117- let shutdown = Arc :: new ( Latch :: new ( 1 ) ) ;
125+ ) -> Result < ( ServerState , ShutdownSend ) , io:: Error > {
126+ let ( shutdown_tx_server, shutdown_rx_server) = mea:: shutdown:: new_pair ( ) ;
127+
118128 let wg = WaitGroup :: new ( ) ;
119129
120130 log:: info!( "listening on {}" , config. listen_addr) ;
@@ -130,18 +140,18 @@ pub async fn start_server(
130140 resolve_advertise_addr ( listen_addr, config. advertise_addr . as_deref ( ) ) ?;
131141
132142 let server_fut = {
133- let shutdown_clone = shutdown . clone ( ) ;
143+ let shutdown_clone = shutdown_rx_server . clone ( ) ;
134144 let wg_clone = wg. clone ( ) ;
135145
136146 let route = Route :: new ( )
137147 . at ( "/*key" , poem:: get ( get) . put ( put) . delete ( delete) )
138- . data ( ctx)
148+ . data ( ctx. clone ( ) )
139149 . with ( LoggerMiddleware ) ;
140150 let signal = async move {
141151 log:: info!( "server has started on [{listen_addr}]" ) ;
142152 drop ( wg_clone) ;
143153
144- shutdown_clone. wait ( ) . await ;
154+ shutdown_clone. is_shutdown ( ) . await ;
145155 log:: info!( "server is closing" ) ;
146156 } ;
147157
@@ -153,11 +163,26 @@ pub async fn start_server(
153163 } ;
154164
155165 wg. await ;
156- Ok ( ServerState {
166+
167+ // Scheduled actions
168+ let mut shutdown_tx_actions = vec ! [ ] ;
169+ let ( shutdown_tx, shutdown_rx) = mea:: shutdown:: new_pair ( ) ;
170+ ReportMetricsAction :: new ( ctx. clone ( ) ) . schedule_with_fixed_delay (
171+ async move { shutdown_rx. is_shutdown ( ) . await } ,
172+ rt,
173+ timer ( ) ,
174+ None ,
175+ Duration :: from_secs ( 60 ) ,
176+ ) ;
177+ shutdown_tx_actions. push ( shutdown_tx) ;
178+
179+ let state = ServerState {
157180 server_advertise_addr,
158181 server_fut,
159- shutdown,
160- } )
182+ shutdown_rx_server,
183+ shutdown_tx_actions,
184+ } ;
185+ Ok ( ( state, shutdown_tx_server) )
161186}
162187
163188fn resolve_advertise_addr (
0 commit comments