//! The targets of spec §24, measured: `brief` and `say` with a thousand //! messages in the ledger, and how soon `wait` wakes after a mention. Run //! in release, by hand: //! //! `cargo test --release --test bench -- --ignored --nocapture` mod common; use common::{add_agent, setup, Serving}; use serde_json::json; use spectra_mcp::client::{rpc_result, Client}; use std::time::{Duration, Instant}; async fn call(c: &Client, name: &str, args: serde_json::Value) -> serde_json::Value { let req = json!({ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": name, "arguments": args } }); rpc_result(&c.mcp("2025-11-25", &req).await.unwrap()).unwrap() } fn median(mut v: Vec) -> Duration { v.sort(); v[v.len() / 2] } #[tokio::test(flavor = "multi_thread", worker_threads = 4)] #[ignore] async fn spec_24_targets() { let dir = setup(); let d = dir.path(); let a = add_agent(d, "bench-a", &[]); let b = add_agent(d, "bench-b", &[]); let srv = Serving::start(d); let (ca, cb) = (Client::new(&srv.socket, Some(a)), Client::new(&srv.socket, Some(b))); for i in 0..1_000 { call(&ca, "say", json!({ "body": format!("message {i} about the pin bump"), "channel": "general" })).await; } let mut brief = Vec::new(); let mut say = Vec::new(); for i in 0..50 { let t = Instant::now(); call(&ca, "brief", json!({})).await; brief.push(t.elapsed()); let t = Instant::now(); call(&ca, "say", json!({ "body": format!("timed {i}") })).await; say.push(t.elapsed()); } let mut wake = Vec::new(); for i in 0..10 { let w = tokio::spawn({ let cb = Client::new(&srv.socket, Some(spectra_core::keys::KeyPair::load_home(&d.join("agents/bench-b")).unwrap())); async move { call(&cb, "wait", json!({ "timeout_s": 20 })).await; Instant::now() } }); tokio::time::sleep(Duration::from_millis(200)).await; let sent = Instant::now(); call(&ca, "say", json!({ "body": format!("@bench-b wake {i}"), "channel": "general" })).await; wake.push(w.await.unwrap().saturating_duration_since(sent)); call(&cb, "ack", json!({ "ids": [] })).await; let inbox = call(&cb, "inbox", json!({})).await; let ids: Vec = inbox["result"]["structuredContent"]["items"].as_array().unwrap().iter().map(|i| i["id"].clone()).collect(); call(&cb, "ack", json!({ "ids": ids })).await; } println!("spec §24 with 1,000 messages, round trip over the socket including signing:"); println!(" brief median {:?}", median(brief)); println!(" say median {:?}", median(say)); println!(" wait wakes {:?} after the mention is sent (median)", median(wake)); srv.stop(); }