Files
telemt/src/config/hot_reload.rs
T
2026-08-25 12:59:41 +03:00

64 lines
2.8 KiB
Rust

//! Hot-reload: watches the config file via inotify (Linux) / FSEvents (macOS)
//! / ReadDirectoryChangesW (Windows) using the `notify` crate.
//! SIGHUP is also supported on Unix as an additional manual trigger.
//!
//! # What can be reloaded without restart
//!
//! | Section | Field | Effect |
//! |-----------|--------------------------------|------------------------------------------------|
//! | `general` | `log_level` | Filter updated via `log_level_tx` |
//! | `access` | `user_ad_tags` | Passed on next connection |
//! | `general` | `ad_tag` | Passed on next connection (fallback per-user) |
//! | `general` | `desync_all_full` | Applied immediately |
//! | `general` | `update_every` | Applied to ME updater immediately |
//! | `general` | `me_reinit_*` | Applied to ME reinit scheduler immediately |
//! | `general` | `hardswap` / `me_*_reinit` | Applied on next ME map update |
//! | `general` | `telemetry` / `me_*_policy` | Applied immediately |
//! | `network` | `dns_overrides` | Applied immediately |
//! | `access` | All user/quota fields | Effective immediately |
//! Fields that require re-binding sockets (`server.listeners`, legacy
//! `server.port`, `censorship.*`, `network.*`, `use_middle_proxy`) are **not**
//! applied; a warning is emitted. SYN limiter rules are process-owned and are
//! reconciled only during privileged startup.
//! Non-hot changes are never mixed into the runtime config snapshot.
use std::collections::BTreeSet;
use std::net::IpAddr;
use std::path::{Path, PathBuf};
use std::sync::{Arc, RwLock as StdRwLock};
use std::time::Duration;
use notify::{EventKind, RecursiveMode, Watcher, recommended_watcher};
use tokio::sync::{mpsc, watch};
use tracing::{error, info, warn};
use super::load::{LoadedConfig, ProxyConfig};
#[allow(unused_imports)]
use crate::config::{
CidrRateLimitKey, LogLevel, MeBindStaleMode, MeFloorMode, MeSocksKdfPolicy, MeTelemetryLevel,
MeWriterPickMode, WebDebugConfig, web_debug_fits_limits,
};
#[cfg(test)]
use crate::config::{ListenerConfig, SynLimitMode};
const HOT_RELOAD_DEBOUNCE: Duration = Duration::from_millis(50);
mod diff;
mod fields;
mod reporting;
mod watcher;
#[allow(unused_imports)]
pub use diff::{ChangeClassification, classify_config_changes};
pub use fields::HotFields;
pub use watcher::spawn_config_watcher;
use diff::{config_equal, warn_non_hot_changes};
use fields::overlay_hot_fields;
use reporting::log_changes;
#[cfg(test)]
use watcher::{ReloadState, reload_config};
#[cfg(test)]
mod tests;