Skip to main content

nodedb_types/config/tuning/
shutdown.rs

1// SPDX-License-Identifier: Apache-2.0
2
3//! Shutdown tuning — deadlines applied to the graceful shutdown
4//! path by `main.rs` and `control::shutdown::LoopRegistry`.
5
6use serde::{Deserialize, Serialize};
7
8fn default_shutdown_deadline_ms() -> u64 {
9    // 900ms: the remaining 100ms of a 1s operator budget is
10    // reserved for transport close + final WAL fsync. Chosen
11    // so `shutdown_all` has a chance to abort async laggards
12    // before the OS hard-kills the process on a second SIGTERM.
13    900
14}
15
16/// Tuning knobs for the graceful shutdown path.
17#[derive(Debug, Clone, Serialize, Deserialize)]
18pub struct ShutdownTuning {
19    /// Deadline in milliseconds for `LoopRegistry::shutdown_all`.
20    /// Every registered background loop must exit within this
21    /// window after the shutdown signal is flipped; laggards
22    /// are aborted (async) or logged (blocking).
23    #[serde(default = "default_shutdown_deadline_ms")]
24    pub deadline_ms: u64,
25}
26
27impl Default for ShutdownTuning {
28    fn default() -> Self {
29        Self {
30            deadline_ms: default_shutdown_deadline_ms(),
31        }
32    }
33}
34
35impl ShutdownTuning {
36    /// Convert the deadline to a `std::time::Duration`.
37    pub fn deadline(&self) -> std::time::Duration {
38        std::time::Duration::from_millis(self.deadline_ms)
39    }
40}
41
42#[cfg(test)]
43mod tests {
44    use super::*;
45
46    #[test]
47    fn default_deadline_is_900ms() {
48        let t = ShutdownTuning::default();
49        assert_eq!(t.deadline_ms, 900);
50        assert_eq!(t.deadline(), std::time::Duration::from_millis(900));
51    }
52
53    #[test]
54    fn override_deadline() {
55        let toml_str = r#"deadline_ms = 1500"#;
56        let t: ShutdownTuning = toml::from_str(toml_str).unwrap();
57        assert_eq!(t.deadline_ms, 1500);
58    }
59}