mirror of
https://github.com/Xevion/banner.git
synced 2025-12-06 01:14:22 -06:00
feat: implement proper SIGTERM handling for container shutdown
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -168,7 +168,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "banner"
|
||||
version = "0.2.0"
|
||||
version = "0.2.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "banner"
|
||||
version = "0.2.0"
|
||||
version = "0.2.1"
|
||||
edition = "2024"
|
||||
default-run = "banner"
|
||||
|
||||
|
||||
51
src/main.rs
51
src/main.rs
@@ -1,6 +1,6 @@
|
||||
use figment::value::UncasedStr;
|
||||
use num_format::{Locale, ToFormattedString};
|
||||
use serenity::all::{ActivityData, ClientBuilder, GatewayIntents};
|
||||
use serenity::all::{ActivityData, ClientBuilder, Context, GatewayIntents};
|
||||
use tokio::signal;
|
||||
use tracing::{error, info, warn};
|
||||
use tracing_subscriber::{EnvFilter, FmtSubscriber};
|
||||
@@ -28,10 +28,7 @@ mod services;
|
||||
mod state;
|
||||
mod web;
|
||||
|
||||
async fn update_bot_status(
|
||||
ctx: &serenity::all::Context,
|
||||
app_state: &AppState,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
async fn update_bot_status(ctx: &Context, app_state: &AppState) -> Result<(), anyhow::Error> {
|
||||
let course_count = app_state.get_course_count().await?;
|
||||
|
||||
ctx.set_activity(Some(ActivityData::playing(format!(
|
||||
@@ -239,7 +236,7 @@ async fn main() {
|
||||
// Spawn all registered services
|
||||
service_manager.spawn_all();
|
||||
|
||||
// Set up CTRL+C signal handling
|
||||
// Set up signal handling for both SIGINT (Ctrl+C) and SIGTERM
|
||||
let ctrl_c = async {
|
||||
signal::ctrl_c()
|
||||
.await
|
||||
@@ -247,7 +244,23 @@ async fn main() {
|
||||
info!("received ctrl+c, gracefully shutting down...");
|
||||
};
|
||||
|
||||
// Main application loop - wait for services or CTRL+C
|
||||
#[cfg(unix)]
|
||||
let sigterm = async {
|
||||
use tokio::signal::unix::{SignalKind, signal};
|
||||
let mut sigterm_stream =
|
||||
signal(SignalKind::terminate()).expect("Failed to install SIGTERM signal handler");
|
||||
sigterm_stream.recv().await;
|
||||
info!("received SIGTERM, gracefully shutting down...");
|
||||
};
|
||||
|
||||
#[cfg(not(unix))]
|
||||
let sigterm = async {
|
||||
// On non-Unix systems, create a future that never completes
|
||||
// This ensures the select! macro works correctly
|
||||
std::future::pending::<()>().await;
|
||||
};
|
||||
|
||||
// Main application loop - wait for services or signals
|
||||
let mut exit_code = 0;
|
||||
|
||||
tokio::select! {
|
||||
@@ -289,7 +302,7 @@ async fn main() {
|
||||
}
|
||||
}
|
||||
_ = ctrl_c => {
|
||||
// User requested shutdown
|
||||
// User requested shutdown via Ctrl+C
|
||||
info!("user requested shutdown via ctrl+c");
|
||||
match service_manager.shutdown(shutdown_timeout).await {
|
||||
Ok(elapsed) => {
|
||||
@@ -310,6 +323,28 @@ async fn main() {
|
||||
}
|
||||
}
|
||||
}
|
||||
_ = sigterm => {
|
||||
// System requested shutdown via SIGTERM
|
||||
info!("system requested shutdown via SIGTERM");
|
||||
match service_manager.shutdown(shutdown_timeout).await {
|
||||
Ok(elapsed) => {
|
||||
info!(
|
||||
remaining = format!("{:.2?}", shutdown_timeout - elapsed),
|
||||
"graceful shutdown complete"
|
||||
);
|
||||
info!("graceful shutdown complete");
|
||||
}
|
||||
Err(pending_services) => {
|
||||
warn!(
|
||||
pending_count = pending_services.len(),
|
||||
pending_services = ?pending_services,
|
||||
"graceful shutdown elapsed - {} service(s) did not complete",
|
||||
pending_services.len()
|
||||
);
|
||||
exit_code = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
info!(exit_code, "application shutdown complete");
|
||||
|
||||
Reference in New Issue
Block a user