sqry_daemon/lifecycle/mod.rs
1//! Task 9 lifecycle primitives.
2//!
3//! This module is the landing zone for all sqryd binary lifecycle concerns:
4//!
5//! - [`notify`] — thin `sd_notify` wrapper with platform-appropriate fallbacks.
6//! On Linux the real `sd_notify` crate is called; on macOS and Windows the
7//! functions are no-ops so that callers in the shared startup path never need
8//! `#[cfg(target_os = "linux")]` guards at the call site.
9//! - [`log_rotate`] — `RollingSizeAppender` + `install_tracing` (Task 9 U5).
10//! Rotates the active log file when it exceeds `log_max_size_mb`, keeping at
11//! most `log_keep_rotations` copies. When `NOTIFY_SOCKET` is present
12//! (systemd supervision) the rolling appender is skipped and output goes to
13//! stderr instead (§G.1 m4 fix).
14//!
15//! Modules added by later Task 9 units (U3–U10) will be declared here as they
16//! are implemented. This avoids merge-conflict churn: each unit adds one
17//! `pub mod` line.
18//!
19//! # Design reference
20//!
21//! `docs/reviews/sqryd-daemon/2026-04-19/task-9-design_iter3_request.md` §C.3.1
22//! (step 15 — authoritative ready-signal matrix) + §F.1 (systemd user unit
23//! `Type=notify`) + §G (log rotation).
24
25pub mod detach;
26pub mod log_rotate;
27pub mod notify;
28pub mod pidfile;
29pub mod signals;
30pub mod units;
31
32#[cfg(test)]
33pub(crate) mod test_support {
34 use std::ffi::OsString;
35 use std::sync::{Mutex, MutexGuard};
36
37 static NOTIFY_SOCKET_LOCK: Mutex<()> = Mutex::new(());
38
39 pub(crate) struct NotifySocketGuard {
40 previous: Option<OsString>,
41 _lock: MutexGuard<'static, ()>,
42 }
43
44 impl NotifySocketGuard {
45 pub(crate) fn unset() -> Self {
46 let _lock = NOTIFY_SOCKET_LOCK.lock().unwrap_or_else(|e| e.into_inner());
47 let previous = std::env::var_os("NOTIFY_SOCKET");
48 unsafe {
49 std::env::remove_var("NOTIFY_SOCKET");
50 }
51 Self { previous, _lock }
52 }
53
54 pub(crate) fn set(value: &str) -> Self {
55 let _lock = NOTIFY_SOCKET_LOCK.lock().unwrap_or_else(|e| e.into_inner());
56 let previous = std::env::var_os("NOTIFY_SOCKET");
57 unsafe {
58 std::env::set_var("NOTIFY_SOCKET", value);
59 }
60 Self { previous, _lock }
61 }
62 }
63
64 impl Drop for NotifySocketGuard {
65 fn drop(&mut self) {
66 match &self.previous {
67 Some(value) => unsafe { std::env::set_var("NOTIFY_SOCKET", value) },
68 None => unsafe { std::env::remove_var("NOTIFY_SOCKET") },
69 }
70 }
71 }
72}