Skip to main content

systemprompt_logging/services/
throttle.rs

1//! Interval-based suppression for repeated log emissions.
2//!
3//! [`LogThrottle`] gates a hot-path warning down to at most one emission per
4//! interval; under concurrency at most one caller wins each interval.
5//!
6//! Copyright (c) systemprompt.io — Business Source License 1.1.
7//! See <https://systemprompt.io> for licensing details.
8
9use std::sync::atomic::{AtomicU64, Ordering};
10use std::time::{SystemTime, UNIX_EPOCH};
11
12#[derive(Debug)]
13pub struct LogThrottle {
14    interval_secs: u64,
15    last_emit_epoch_secs: AtomicU64,
16}
17
18impl LogThrottle {
19    #[must_use]
20    pub const fn new(interval_secs: u64) -> Self {
21        Self {
22            interval_secs,
23            last_emit_epoch_secs: AtomicU64::new(0),
24        }
25    }
26
27    #[must_use]
28    pub fn allow(&self) -> bool {
29        let now = SystemTime::now()
30            .duration_since(UNIX_EPOCH)
31            .map(|d| d.as_secs())
32            .unwrap_or_default();
33        self.allow_at(now)
34    }
35
36    #[must_use]
37    pub fn allow_at(&self, now_epoch_secs: u64) -> bool {
38        let last = self.last_emit_epoch_secs.load(Ordering::Acquire);
39        if last != 0 && now_epoch_secs.saturating_sub(last) < self.interval_secs {
40            return false;
41        }
42        self.last_emit_epoch_secs
43            .compare_exchange(last, now_epoch_secs, Ordering::AcqRel, Ordering::Relaxed)
44            .is_ok()
45    }
46}