9b1a739e39
CI / Rust Checks (pull_request) Successful in 6m15s
CI / UI Checks (pull_request) Successful in 5s
CI / Community Image Smoke (pull_request) Successful in 4m25s
CI / Frontend E2E (pull_request) Successful in 5m17s
CI / Deploy (pull_request) Has been skipped
CI / Rust Checks (push) Successful in 6m9s
CI / UI Checks (push) Successful in 5s
CI / Community Image Smoke (push) Successful in 1m3s
CI / Frontend E2E (push) Successful in 3m47s
CI / Deploy (push) Failing after 3s
77 lines
2.3 KiB
Rust
77 lines
2.3 KiB
Rust
use std::{sync::Arc, time::Duration};
|
|
|
|
use crank_community_mcp::session::{
|
|
ActiveSessionMetrics, InMemorySessionStore, SharedSessionStore, TransportSessionStore,
|
|
spawn_session_cleanup,
|
|
};
|
|
use metrics_util::debugging::{DebugValue, DebuggingRecorder, Snapshotter};
|
|
use time::OffsetDateTime;
|
|
|
|
#[tokio::test]
|
|
async fn active_session_sampler_tracks_create_delete_and_expiry() {
|
|
let recorder = DebuggingRecorder::new();
|
|
let snapshotter = recorder.snapshotter();
|
|
recorder
|
|
.install()
|
|
.expect("isolated integration test recorder");
|
|
|
|
let store = Arc::new(InMemorySessionStore::default());
|
|
let sessions: SharedSessionStore = store.clone();
|
|
let sampler = ActiveSessionMetrics::start(Arc::clone(&sessions));
|
|
assert_gauge(&sampler, &snapshotter, 0.0).await;
|
|
|
|
let now = OffsetDateTime::now_utc();
|
|
store
|
|
.create(
|
|
"2025-11-25",
|
|
"default",
|
|
"agent",
|
|
false,
|
|
now,
|
|
Some(now + time::Duration::milliseconds(100)),
|
|
)
|
|
.await
|
|
.unwrap();
|
|
assert_gauge(&sampler, &snapshotter, 1.0).await;
|
|
|
|
spawn_session_cleanup(sessions, sampler, Duration::from_millis(10));
|
|
assert_gauge_without_refresh(&snapshotter, 0.0).await;
|
|
}
|
|
|
|
async fn assert_gauge_without_refresh(snapshotter: &Snapshotter, expected: f64) {
|
|
for _ in 0..100 {
|
|
tokio::time::sleep(Duration::from_millis(10)).await;
|
|
if gauge_value(snapshotter) == Some(expected) {
|
|
return;
|
|
}
|
|
}
|
|
panic!("active session gauge did not become {expected} through cleanup");
|
|
}
|
|
|
|
async fn assert_gauge(sampler: &ActiveSessionMetrics, snapshotter: &Snapshotter, expected: f64) {
|
|
for _ in 0..50 {
|
|
sampler.refresh();
|
|
tokio::time::sleep(Duration::from_millis(10)).await;
|
|
if gauge_value(snapshotter) == Some(expected) {
|
|
return;
|
|
}
|
|
}
|
|
panic!("active session gauge did not become {expected}");
|
|
}
|
|
|
|
fn gauge_value(snapshotter: &Snapshotter) -> Option<f64> {
|
|
snapshotter
|
|
.snapshot()
|
|
.into_vec()
|
|
.into_iter()
|
|
.find_map(|(key, _, _, value)| {
|
|
if key.key().name() != "crank_mcp_active_sessions" {
|
|
return None;
|
|
}
|
|
match value {
|
|
DebugValue::Gauge(value) => Some(value.into_inner()),
|
|
_ => None,
|
|
}
|
|
})
|
|
}
|