mirror of
https://github.com/telemt/telemt.git
synced 2026-06-19 02:00:08 +07:00
52 lines
2.0 KiB
Rust
52 lines
2.0 KiB
Rust
|
|
use std::sync::atomic::{AtomicU64, Ordering};
|
||
|
|
use std::time::Duration;
|
||
|
|
|
||
|
|
use tokio::time::Instant;
|
||
|
|
|
||
|
|
// ============= SharedCounters =============
|
||
|
|
|
||
|
|
/// Atomic counters shared between the relay (via StatsIo) and the watchdog task.
|
||
|
|
///
|
||
|
|
/// Using `Relaxed` ordering is sufficient because:
|
||
|
|
/// - Counters are monotonically increasing (no ABA problem)
|
||
|
|
/// - Slight staleness in watchdog reads is harmless (±10s check interval anyway)
|
||
|
|
/// - No ordering dependencies between different counters
|
||
|
|
pub(in crate::proxy::relay) struct SharedCounters {
|
||
|
|
/// Bytes read from client (C→S direction)
|
||
|
|
pub(in crate::proxy::relay) c2s_bytes: AtomicU64,
|
||
|
|
/// Bytes written to client (S→C direction)
|
||
|
|
pub(in crate::proxy::relay) s2c_bytes: AtomicU64,
|
||
|
|
/// Number of poll_read completions (≈ C→S chunks)
|
||
|
|
pub(in crate::proxy::relay) c2s_ops: AtomicU64,
|
||
|
|
/// Number of poll_write completions (≈ S→C chunks)
|
||
|
|
pub(in crate::proxy::relay) s2c_ops: AtomicU64,
|
||
|
|
/// Milliseconds since relay epoch of last I/O activity
|
||
|
|
last_activity_ms: AtomicU64,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl SharedCounters {
|
||
|
|
pub(in crate::proxy::relay) fn new() -> Self {
|
||
|
|
Self {
|
||
|
|
c2s_bytes: AtomicU64::new(0),
|
||
|
|
s2c_bytes: AtomicU64::new(0),
|
||
|
|
c2s_ops: AtomicU64::new(0),
|
||
|
|
s2c_ops: AtomicU64::new(0),
|
||
|
|
last_activity_ms: AtomicU64::new(0),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Record activity at this instant.
|
||
|
|
#[inline]
|
||
|
|
pub(in crate::proxy::relay) fn touch(&self, now: Instant, epoch: Instant) {
|
||
|
|
let ms = now.duration_since(epoch).as_millis() as u64;
|
||
|
|
self.last_activity_ms.store(ms, Ordering::Relaxed);
|
||
|
|
}
|
||
|
|
|
||
|
|
/// How long since last recorded activity.
|
||
|
|
pub(in crate::proxy::relay) fn idle_duration(&self, now: Instant, epoch: Instant) -> Duration {
|
||
|
|
let last_ms = self.last_activity_ms.load(Ordering::Relaxed);
|
||
|
|
let now_ms = now.duration_since(epoch).as_millis() as u64;
|
||
|
|
Duration::from_millis(now_ms.saturating_sub(last_ms))
|
||
|
|
}
|
||
|
|
}
|