diff --git a/src/config.rs b/src/config.rs index 7121415..2355b43 100644 --- a/src/config.rs +++ b/src/config.rs @@ -701,6 +701,11 @@ impl Config { } } + // Validate notification thresholds + if self.notifications.cache_threshold_pct > 100 { + anyhow::bail!("notifications.cache_threshold_pct must be 0–100, got {}", self.notifications.cache_threshold_pct); + } + // Validate SMB auth if self.smb_auth.enabled { if self.smb_auth.username.is_none() { diff --git a/src/daemon.rs b/src/daemon.rs index 88cbf49..fa5c36b 100644 --- a/src/daemon.rs +++ b/src/daemon.rs @@ -70,6 +70,8 @@ pub struct DaemonStatus { pub nas_offline_notified: bool, /// Cache warning level already notified (0=none, 3=writeback depth). pub cache_notified_level: u8, + /// Whether we've already sent the cache-threshold notification (reset when usage drops). + pub cache_threshold_notified: bool, } impl DaemonStatus { @@ -108,6 +110,7 @@ impl DaemonStatus { nas_offline_since: None, nas_offline_notified: false, cache_notified_level: 0, + cache_threshold_notified: false, } } diff --git a/src/supervisor.rs b/src/supervisor.rs index 201ce49..0ebb7ec 100644 --- a/src/supervisor.rs +++ b/src/supervisor.rs @@ -910,6 +910,23 @@ fn supervise( status.nas_offline_notified = false; } + // Cache usage % notification + if notif.cache_threshold_pct > 0 { + let total_cache: u64 = status.shares.iter().map(|s| s.cache_bytes).sum(); + if let Some(max_bytes) = parse_size_bytes(&config.cache.max_size) { + let pct = (total_cache as f64 / max_bytes as f64 * 100.0) as u8; + if pct >= notif.cache_threshold_pct && !status.cache_threshold_notified { + send_webhook_notification(&url, &format!( + "\u{26a0}\u{fe0f} Warpgate: cache usage {}% — consider cleaning", pct + )); + status.cache_threshold_notified = true; + } else if pct < notif.cache_threshold_pct.saturating_sub(5) { + // Hysteresis: reset when usage drops 5% below threshold + status.cache_threshold_notified = false; + } + } + } + // Write-back depth notification if total_dirty >= notif.writeback_depth { if status.cache_notified_level < 3 {