Skip to content

Commit 54ab070

Browse files
committed
async: use shutdown to implement server graceful shutdown.
Using shutdown can be used instead of channel composition. Signed-off-by: wllenyj <[email protected]>
1 parent 21b8e1a commit 54ab070

File tree

1 file changed

+38
-41
lines changed

1 file changed

+38
-41
lines changed

src/asynchronous/server.rs

Lines changed: 38 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ use tokio::{
2121
net::UnixListener,
2222
select, spawn,
2323
sync::mpsc::{channel, Receiver, Sender},
24-
sync::watch,
2524
time::timeout,
2625
};
2726
#[cfg(target_os = "linux")]
@@ -33,16 +32,20 @@ use crate::common::{self, Domain};
3332
use crate::context;
3433
use crate::error::{get_status, Error, Result};
3534
use crate::proto::{Code, MessageHeader, Status, MESSAGE_TYPE_REQUEST};
35+
use crate::r#async::shutdown;
3636
use crate::r#async::utils;
3737
use crate::r#async::{MethodHandler, TtrpcContext};
3838

39+
const DEFAULT_CONN_SHUTDOWN_TIMEOUT: Duration = Duration::from_millis(5000);
40+
const DEFAULT_SERVER_SHUTDOWN_TIMEOUT: Duration = Duration::from_millis(10000);
41+
3942
/// A ttrpc Server (async).
4043
pub struct Server {
4144
listeners: Vec<RawFd>,
4245
methods: Arc<HashMap<String, Box<dyn MethodHandler + Send + Sync>>>,
4346
domain: Option<Domain>,
44-
disconnect_tx: Option<watch::Sender<i32>>,
45-
all_conn_done_rx: Option<Receiver<i32>>,
47+
48+
shutdown: shutdown::Notifier,
4649
stop_listen_tx: Option<Sender<Sender<RawFd>>>,
4750
}
4851

@@ -52,8 +55,7 @@ impl Default for Server {
5255
listeners: Vec::with_capacity(1),
5356
methods: Arc::new(HashMap::new()),
5457
domain: None,
55-
disconnect_tx: None,
56-
all_conn_done_rx: None,
58+
shutdown: shutdown::with_timeout(DEFAULT_SERVER_SHUTDOWN_TIMEOUT).0,
5759
stop_listen_tx: None,
5860
}
5961
}
@@ -151,11 +153,7 @@ impl Server {
151153
{
152154
let methods = self.methods.clone();
153155

154-
let (disconnect_tx, close_conn_rx) = watch::channel(0);
155-
self.disconnect_tx = Some(disconnect_tx);
156-
157-
let (conn_done_tx, all_conn_done_rx) = channel::<i32>(1);
158-
self.all_conn_done_rx = Some(all_conn_done_rx);
156+
let shutdown_waiter = self.shutdown.subscribe();
159157

160158
let (stop_listen_tx, mut stop_listen_rx) = channel(1);
161159
self.stop_listen_tx = Some(stop_listen_tx);
@@ -174,8 +172,7 @@ impl Server {
174172
fd,
175173
stream,
176174
methods.clone(),
177-
close_conn_rx.clone(),
178-
conn_done_tx.clone()
175+
shutdown_waiter.clone(),
179176
).await;
180177
}
181178
Err(e) => {
@@ -201,7 +198,6 @@ impl Server {
201198
}
202199
}
203200
}
204-
drop(conn_done_tx);
205201
});
206202
Ok(())
207203
}
@@ -214,13 +210,16 @@ impl Server {
214210
}
215211

216212
pub async fn disconnect(&mut self) {
217-
if let Some(tx) = self.disconnect_tx.take() {
218-
tx.send(1).ok();
219-
}
213+
self.shutdown.shutdown();
220214

221-
if let Some(mut rx) = self.all_conn_done_rx.take() {
222-
rx.recv().await;
223-
}
215+
self.shutdown
216+
.wait_all_exit()
217+
.await
218+
.map_err(|e| {
219+
trace!("wait connection exit error: {}", e);
220+
})
221+
.ok();
222+
trace!("wait connection exit.");
224223
}
225224

226225
pub async fn stop_listen(&mut self) {
@@ -239,17 +238,17 @@ async fn spawn_connection_handler<S>(
239238
fd: RawFd,
240239
stream: S,
241240
methods: Arc<HashMap<String, Box<dyn MethodHandler + Send + Sync>>>,
242-
mut close_conn_rx: watch::Receiver<i32>,
243-
conn_done_tx: Sender<i32>,
241+
shutdown_waiter: shutdown::Waiter,
244242
) where
245243
S: AsyncRead + AsyncWrite + AsRawFd + Send + 'static,
246244
{
247-
let (req_done_tx, mut all_req_done_rx) = channel::<i32>(1);
248-
249245
spawn(async move {
250246
let (mut reader, mut writer) = split(stream);
251247
let (tx, mut rx): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = channel(100);
252-
let (client_disconnected_tx, client_disconnected_rx) = watch::channel(false);
248+
249+
let server_shutdown = shutdown_waiter.clone();
250+
let (disconnect_notifier, disconnect_waiter) =
251+
shutdown::with_timeout(DEFAULT_CONN_SHUTDOWN_TIMEOUT);
253252

254253
spawn(async move {
255254
while let Some(buf) = rx.recv().await {
@@ -262,8 +261,7 @@ async fn spawn_connection_handler<S>(
262261
loop {
263262
let tx = tx.clone();
264263
let methods = methods.clone();
265-
let req_done_tx2 = req_done_tx.clone();
266-
let mut client_disconnected_rx2 = client_disconnected_rx.clone();
264+
let handler_shutdown_waiter = disconnect_waiter.clone();
267265

268266
select! {
269267
resp = receive(&mut reader) => {
@@ -272,33 +270,32 @@ async fn spawn_connection_handler<S>(
272270
spawn(async move {
273271
select! {
274272
_ = handle_request(tx, fd, methods, message) => {}
275-
_ = client_disconnected_rx2.changed() => {}
273+
_ = handler_shutdown_waiter.wait_shutdown() => {}
276274
}
277-
278-
drop(req_done_tx2);
279275
});
280276
}
281277
Err(e) => {
282-
let _ = client_disconnected_tx.send(true);
278+
disconnect_notifier.shutdown();
283279
trace!("error {:?}", e);
284280
break;
285281
}
286282
}
287283
}
288-
v = close_conn_rx.changed() => {
289-
// 0 is the init value of this watch, not a valid signal
290-
// is_err means the tx was dropped.
291-
if v.is_err() || *close_conn_rx.borrow() != 0 {
292-
info!("Stop accepting new connections.");
293-
break;
294-
}
284+
_ = server_shutdown.wait_shutdown() => {
285+
trace!("Receive shutdown.");
286+
break;
295287
}
296288
}
297289
}
298-
299-
drop(req_done_tx);
300-
all_req_done_rx.recv().await;
301-
drop(conn_done_tx);
290+
// TODO: Don't disconnect_notifier.shutdown();
291+
// Wait pedding request/stream to exit.
292+
disconnect_notifier
293+
.wait_all_exit()
294+
.await
295+
.map_err(|e| {
296+
trace!("wait handler exit error: {}", e);
297+
})
298+
.ok();
302299
});
303300
}
304301

0 commit comments

Comments
 (0)