feat(sessions): identify online sessions (connected users)

identify online session by writing the `last_seen_at`
information is stored in a map and flush each 30s to prevent performance impact on pgsql
This commit is contained in:
Edouard Vanbelle
2026-08-19 10:10:39 +02:00
parent 9d69d9c7e7
commit 20e6e05bb4
16 changed files with 1317 additions and 37 deletions
+43
View File
@@ -2126,6 +2126,38 @@ impl AppServiceFactory {
let mut core = core;
core.zip_service = Some(zip_service);
// Session liveness tracker — spawns its own 30 s flush
// loop at construction. Only built when auth (and thus
// sessions) exist; when auth is off this is `None` and
// the middleware never calls it. Uses the maintenance
// pool so background flushes don't compete with
// request-serving connections. See
// [`LastSeenTracker`](crate::infrastructure::services::last_seen_tracker).
let last_seen_tracker = if auth_services.is_some() {
Some(
crate::infrastructure::services::last_seen_tracker::LastSeenTracker::start(
maintenance_pool.clone(),
),
)
} else {
None
};
// Session-liveness Prometheus poller — three COUNT(*) reads
// every 30 s, publishing `oxicloud_sessions_active`,
// `_active_users`, `_total_non_revoked`. Only spawned when
// the Prometheus recorder is installed (i.e.,
// `OXICLOUD_METRICS_LISTEN` is set) — without the recorder
// the `metrics::gauge!(...)` calls are no-ops and the
// periodic PG hits would be pure waste. Requires auth for
// the same reason as `last_seen_tracker`: no sessions to
// count without it.
if auth_services.is_some() && self.config.metrics_listen.is_some() {
crate::infrastructure::services::session_liveness_gauges::spawn(
maintenance_pool.clone(),
);
}
// 9. Assemble final AppState
let mut app_state = AppState {
core,
@@ -2158,6 +2190,7 @@ impl AppServiceFactory {
people_service,
storage_usage_service,
grant_cleanup_service,
last_seen_tracker,
calendar_service: None,
calendar_use_case: None,
addressbook_use_case: None,
@@ -2952,6 +2985,16 @@ pub struct AppState {
pub grant_cleanup_service: Option<
Arc<crate::infrastructure::services::grant_cleanup_service::GrantCleanupService>,
>,
/// Per-session liveness tracker — the auth middleware calls
/// `stamp(session_id)` after every successful token validation,
/// and a background loop flushes the DashMap to `auth.sessions.
/// last_seen_at` every 30 s (batched UNNEST UPDATE). `None`
/// when auth is disabled — nothing to track. See
/// [`LastSeenTracker`](crate::infrastructure::services::last_seen_tracker)
/// for the contract and `docs/plan/sessions.md` for the design.
pub last_seen_tracker: Option<
Arc<crate::infrastructure::services::last_seen_tracker::LastSeenTracker>,
>,
pub calendar_service: Option<Arc<CalendarService>>,
pub calendar_use_case: Option<Arc<CalendarService>>,
pub addressbook_use_case: Option<Arc<ContactService>>,