mirror of
https://github.com/Such-Software/smirk-backend-core.git
synced 2026-10-17 15:31:38 +02:00
feat(config): configurable restart_apply_mode + graceful shutdown (Stage 3b)
- console section: restart_apply_mode (manual | auto), an operator setting (runtime-safe, DB-overridable via /admin/config), env RESTART_APPLY_MODE default manual. - Graceful shutdown: main serve now awaits SIGTERM/Ctrl-C OR an in-app shutdown signal (AppState.shutdown Notify) via with_graceful_shutdown, draining in-flight requests. - PUT /admin/config in `auto` mode self-restarts shortly after responding to apply a restart-required change (systemd Restart=always brings it back with the new config); `manual` just flags restart_pending. The console warns before an auto save. Stage 3 complete: operator config is readable + editable through the real validated, audited, precedence-based layer; runtime-safe edits apply live, infra edits restart. cargo all-targets clean, lib tests pass.
This commit is contained in:
+28
@@ -118,6 +118,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
web_challenges: Arc::default(),
|
||||
prices: prices_cache,
|
||||
admin_sessions,
|
||||
shutdown: Arc::new(tokio::sync::Notify::new()),
|
||||
});
|
||||
|
||||
// Periodic GC of expired website-auth challenges. Bounds the single-node
|
||||
@@ -394,6 +395,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
});
|
||||
}
|
||||
|
||||
let shutdown = state.shutdown.clone();
|
||||
let app = build_router(state);
|
||||
|
||||
let listener = tokio::net::TcpListener::bind(&addr).await?;
|
||||
@@ -403,6 +405,32 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
listener,
|
||||
app.into_make_service_with_connect_info::<std::net::SocketAddr>(),
|
||||
)
|
||||
.with_graceful_shutdown(shutdown_signal(shutdown))
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Completes on SIGTERM / Ctrl-C, or when the app signals a restart (an operator config
|
||||
/// change in `auto` mode). Lets axum drain in-flight requests before exit; systemd
|
||||
/// `Restart=always` then brings the instance back with the new config.
|
||||
async fn shutdown_signal(app_triggered: Arc<tokio::sync::Notify>) {
|
||||
let ctrl_c = async {
|
||||
let _ = tokio::signal::ctrl_c().await;
|
||||
};
|
||||
#[cfg(unix)]
|
||||
let term = async {
|
||||
if let Ok(mut sig) =
|
||||
tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate())
|
||||
{
|
||||
sig.recv().await;
|
||||
}
|
||||
};
|
||||
#[cfg(not(unix))]
|
||||
let term = std::future::pending::<()>();
|
||||
tokio::select! {
|
||||
_ = ctrl_c => {}
|
||||
_ = term => {}
|
||||
_ = app_triggered.notified() => {}
|
||||
}
|
||||
tracing::info!("shutdown signal received; draining in-flight requests");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user