oxicode_sdk/lifecycle/
agent_pool.rs1use oxicode_agent::Agent;
9use parking_lot::RwLock;
10use std::collections::HashMap;
11use std::sync::Arc;
12
13pub struct AgentPool {
18 agents: RwLock<HashMap<String, Arc<Agent>>>,
19}
20
21impl AgentPool {
22 pub fn new() -> Self {
24 Self {
25 agents: RwLock::new(HashMap::new()),
26 }
27 }
28
29 pub fn insert(&self, id: String, agent: Arc<Agent>) {
31 self.agents.write().insert(id, agent);
32 }
33
34 pub fn get(&self, id: &str) -> Option<Arc<Agent>> {
36 self.agents.read().get(id).cloned()
37 }
38
39 pub fn remove(&self, id: &str) -> Option<Arc<Agent>> {
41 self.agents.write().remove(id)
42 }
43
44 pub fn export_state(&self, id: &str) -> Option<serde_json::Value> {
49 let agents = self.agents.read();
50 let agent = agents.get(id)?;
51 agent.export_state().ok()
52 }
53
54 pub fn import_state(&self, id: &str, state: serde_json::Value) -> bool {
58 let agents = self.agents.read();
59 if let Some(agent) = agents.get(id) {
60 agent.import_state(state).is_ok()
61 } else {
62 false
63 }
64 }
65
66 pub fn len(&self) -> usize {
68 self.agents.read().len()
69 }
70
71 pub fn is_empty(&self) -> bool {
73 self.agents.read().is_empty()
74 }
75
76 pub fn ids(&self) -> Vec<String> {
78 self.agents.read().keys().cloned().collect()
79 }
80
81 pub fn contains(&self, id: &str) -> bool {
83 self.agents.read().contains_key(id)
84 }
85
86 pub fn for_each_row<F: FnMut(&str, &Arc<Agent>)>(&self, mut f: F) {
89 let agents = self.agents.read();
90 for (id, agent) in agents.iter() {
91 f(id.as_str(), agent);
92 }
93 }
94}
95
96impl Default for AgentPool {
97 fn default() -> Self {
98 Self::new()
99 }
100}
101
102impl std::fmt::Debug for AgentPool {
103 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104 f.debug_struct("AgentPool")
105 .field("count", &self.len())
106 .finish()
107 }
108}
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113
114 #[test]
120 fn test_pool_new_empty() {
121 let pool = AgentPool::new();
122 assert!(pool.is_empty());
123 assert_eq!(pool.len(), 0);
124 }
125
126 #[test]
127 fn for_each_row_visits_all_inserted() {
128 let pool = AgentPool::new();
129 let mut seen = Vec::new();
130 pool.for_each_row(|id, _| seen.push(id.to_string()));
131 assert!(seen.is_empty());
132 }
133
134 #[test]
135 fn test_pool_default() {
136 let pool = AgentPool::default();
137 assert!(pool.is_empty());
138 }
139
140 #[test]
141 fn test_pool_debug() {
142 let pool = AgentPool::new();
143 let debug = format!("{:?}", pool);
144 assert!(debug.contains("AgentPool"));
145 }
146}