use std::collections::HashMap; use std::sync::Arc; use std::time::Instant; use tokio::sync::{Mutex, mpsc}; use crate::agent::AgentError; use crate::protocol::WsOutbound; use super::session::Session; use super::session_factory::SessionFactory; #[derive(Clone)] pub(crate) struct SessionPool { inner: Arc>, session_factory: SessionFactory, } struct SessionPoolInner { sessions: HashMap>>, session_timestamps: HashMap, } impl SessionPool { pub(crate) fn new(session_factory: SessionFactory) -> Self { Self { inner: Arc::new(Mutex::new(SessionPoolInner { sessions: HashMap::new(), session_timestamps: HashMap::new(), })), session_factory, } } pub(crate) async fn ensure_session(&self, channel_name: &str) -> Result<(), AgentError> { let mut inner = self.inner.lock().await; // 简化:只检查 session 是否存在,不做超时判断 if inner.sessions.contains_key(channel_name) { return Ok(()); } // Session 不存在则创建 let (user_tx, _rx) = mpsc::channel::(100); let session = self .session_factory .create(channel_name.to_string(), user_tx) .await?; inner .sessions .insert(channel_name.to_string(), Arc::new(Mutex::new(session))); inner .session_timestamps .insert(channel_name.to_string(), Instant::now()); Ok(()) } pub(crate) async fn get(&self, channel_name: &str) -> Option>> { self.inner.lock().await.sessions.get(channel_name).cloned() } pub(crate) async fn touch(&self, channel_name: &str) { self.inner .lock() .await .session_timestamps .insert(channel_name.to_string(), Instant::now()); } pub(crate) async fn cleanup_expired_sessions(&self) -> usize { // Session 级别不再自动清理,返回 0 0 } }