feat(main): bound graceful shutdown with a 30s timeout

The stop sequence awaited the queue workers, which can be mid-download
(30s client timeout) or mid-ugoira encode (minutes). A stuck worker would
hold shutdown forever; now the process logs and exits after 30s.
This commit is contained in:
2026-08-13 22:26:16 +08:00
parent 2e2d1b3506
commit 246fc989f0
+10 -1
View File
@@ -178,13 +178,22 @@ async fn main() {
.await; .await;
} }
// Graceful stop (Ctrl+C / SIGTERM): stop the sweep, notify the admin, drain the queue. // Graceful stop (Ctrl+C / SIGTERM): stop the sweep, notify the admin,
// drain the queue. Bounded: a worker mid-download (30 s timeout) or a
// long ugoira encode must not hold the shutdown hostage forever.
log::info!("Stopping bot"); log::info!("Stopping bot");
const SHUTDOWN_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(30);
let shutdown = async {
let _ = stop_tx.send(true); let _ = stop_tx.send(true);
handlers::stop_url_workers(); handlers::stop_url_workers();
if let Some(admin) = CONFIG.admin_ids.first() { if let Some(admin) = CONFIG.admin_ids.first() {
let _ = bot.send_message(ChatId(*admin), "Shutting down...").await; let _ = bot.send_message(ChatId(*admin), "Shutting down...").await;
} }
TASK_QUEUE.stop().await; TASK_QUEUE.stop().await;
};
if tokio::time::timeout(SHUTDOWN_TIMEOUT, shutdown).await.is_err() {
log::warn!("graceful shutdown timed out after {SHUTDOWN_TIMEOUT:?}; exiting");
} else {
log::info!("Bot stopped"); log::info!("Bot stopped");
}
} }