mirror of
https://github.com/telemt/telemt.git
synced 2026-09-12 13:34:10 +03:00
e796cb112c
Co-Authored-By: brekotis <93345790+brekotis@users.noreply.github.com>
106 lines
3.2 KiB
Rust
106 lines
3.2 KiB
Rust
use std::time::{Duration, Instant};
|
|
|
|
use super::{SessionState, WebSession};
|
|
use crate::web::telemetry::WebSessionLifecycleObservation;
|
|
|
|
/// Session-local activity clocks with distinct lease and diagnostic authority.
|
|
pub(super) struct SessionActivity {
|
|
last_peer: Instant,
|
|
last_progress: Instant,
|
|
}
|
|
|
|
impl WebSession {
|
|
/// Refreshes the authenticated peer lease and records only threshold-crossing gaps.
|
|
pub(super) fn touch_peer_locked(
|
|
&self,
|
|
state: &mut SessionState,
|
|
now: Instant,
|
|
observation: WebSessionLifecycleObservation,
|
|
) {
|
|
let gap = state.activity.touch_peer(now);
|
|
if gap >= Duration::from_secs(self.timeouts.reconnect_grace_secs)
|
|
&& let Some(manager) = self.manager.upgrade()
|
|
{
|
|
manager
|
|
.telemetry()
|
|
.record_session_observation(self.carrier(), observation);
|
|
}
|
|
}
|
|
|
|
/// Records one valid WebSocket control message as authenticated peer activity.
|
|
pub(crate) fn record_websocket_peer_activity(&self) -> bool {
|
|
let mut state = self.state.lock();
|
|
if state.closed {
|
|
return false;
|
|
}
|
|
self.touch_peer_locked(
|
|
&mut state,
|
|
Instant::now(),
|
|
WebSessionLifecycleObservation::WebSocketActivityAfterGap,
|
|
);
|
|
true
|
|
}
|
|
}
|
|
|
|
impl SessionActivity {
|
|
/// Starts both activity clocks at the same session creation instant.
|
|
pub(super) fn new(now: Instant) -> Self {
|
|
Self {
|
|
last_peer: now,
|
|
last_progress: now,
|
|
}
|
|
}
|
|
|
|
/// Records one validated peer operation and returns the preceding peer gap.
|
|
pub(super) fn touch_peer(&mut self, now: Instant) -> Duration {
|
|
let gap = now.saturating_duration_since(self.last_peer);
|
|
self.last_peer = now;
|
|
self.last_progress = now;
|
|
gap
|
|
}
|
|
|
|
/// Records server-side carrier progress without extending the peer lease.
|
|
pub(super) fn touch_progress(&mut self, now: Instant) {
|
|
self.last_progress = now;
|
|
}
|
|
|
|
/// Returns elapsed time since the latest validated peer operation.
|
|
pub(super) fn peer_idle(&self, now: Instant) -> Duration {
|
|
now.saturating_duration_since(self.last_peer)
|
|
}
|
|
|
|
/// Returns elapsed time since the latest carrier-side progress.
|
|
pub(super) fn progress_idle(&self, now: Instant) -> Duration {
|
|
now.saturating_duration_since(self.last_progress)
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn progress_does_not_extend_the_authenticated_peer_lease() {
|
|
let started = Instant::now();
|
|
let mut activity = SessionActivity::new(started);
|
|
activity.touch_progress(started + Duration::from_secs(4));
|
|
|
|
assert_eq!(
|
|
activity.peer_idle(started + Duration::from_secs(9)),
|
|
Duration::from_secs(9)
|
|
);
|
|
assert_eq!(
|
|
activity.progress_idle(started + Duration::from_secs(9)),
|
|
Duration::from_secs(5)
|
|
);
|
|
assert_eq!(
|
|
activity.touch_peer(started + Duration::from_secs(9)),
|
|
Duration::from_secs(9)
|
|
);
|
|
assert_eq!(
|
|
activity.peer_idle(started + Duration::from_secs(10)),
|
|
Duration::from_secs(1)
|
|
);
|
|
}
|
|
}
|