use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
use super::lightweight::{LightweightConfig, LightweightSubagent};
use echo_core::error::Result;
pub type LightweightFactory =
Arc<dyn Fn(LightweightConfig) -> Result<LightweightSubagent> + Send + Sync>;
pub struct SubAgentPool {
agents: RwLock<HashMap<String, Vec<Arc<LightweightSubagent>>>>,
factory: LightweightFactory,
max_idle: usize,
}
impl SubAgentPool {
pub fn new(factory: LightweightFactory, max_idle: usize) -> Self {
Self {
agents: RwLock::new(HashMap::new()),
factory,
max_idle,
}
}
pub async fn acquire(&self, config: LightweightConfig) -> Result<Arc<LightweightSubagent>> {
let name = config.name.clone();
{
let mut agents = self.agents.write().await;
if let Some(pool) = agents.get_mut(&name) {
if let Some(agent) = pool.pop() {
agent.reset().await;
return Ok(agent);
}
}
}
let agent = (self.factory)(config)?;
Ok(Arc::new(agent))
}
pub async fn release(&self, agent: Arc<LightweightSubagent>) {
let name = agent.config.name.clone();
let mut agents = self.agents.write().await;
let pool = agents.entry(name).or_insert_with(Vec::new);
if pool.len() < self.max_idle {
agent.reset().await;
pool.push(agent);
}
}
pub async fn evict(&self, name: &str) {
let mut agents = self.agents.write().await;
agents.remove(name);
}
pub async fn clear(&self) {
self.agents.write().await.clear();
}
pub async fn idle_count(&self) -> usize {
self.agents
.read()
.await
.values()
.map(|pool| pool.len())
.sum()
}
pub async fn name_count(&self) -> usize {
self.agents.read().await.len()
}
}
impl std::fmt::Debug for SubAgentPool {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SubAgentPool")
.field("max_idle", &self.max_idle)
.finish_non_exhaustive()
}
}