context_creator/core/semantic/
parser_pool.rs1use crate::utils::error::ContextCreatorError;
5use async_trait::async_trait;
6use deadpool::managed::{self, Manager, Metrics, Pool, RecycleResult};
7use std::collections::HashMap;
8use tree_sitter::{Language, Parser};
9
10pub type PooledParser = managed::Object<ParserManager>;
12
13pub type ParserPool = Pool<ParserManager>;
15
16pub struct ParserManager {
18 language: Language,
19 language_name: &'static str,
20}
21
22impl ParserManager {
23 pub fn new(language: Language, language_name: &'static str) -> Self {
25 Self {
26 language,
27 language_name,
28 }
29 }
30}
31
32#[async_trait]
33impl Manager for ParserManager {
34 type Type = Parser;
35 type Error = ContextCreatorError;
36
37 async fn create(&self) -> Result<Parser, Self::Error> {
38 let mut parser = Parser::new();
39
40 parser.set_language(self.language).map_err(|e| {
42 ContextCreatorError::ParseError(format!(
43 "Failed to set {} language: {}",
44 self.language_name, e
45 ))
46 })?;
47
48 parser.set_timeout_micros(5_000_000);
50
51 Ok(parser)
52 }
53
54 async fn recycle(&self, parser: &mut Parser, _: &Metrics) -> RecycleResult<Self::Error> {
55 parser.reset();
57 Ok(())
58 }
59}
60
61pub struct ParserPoolManager {
63 pools: HashMap<&'static str, ParserPool>,
64}
65
66impl ParserPoolManager {
67 pub fn new() -> Self {
69 let mut pools = HashMap::new();
70
71 let pool_config = managed::PoolConfig {
74 max_size: 16,
75 ..Default::default()
76 };
77
78 pools.insert(
80 "rust",
81 Pool::builder(ParserManager::new(tree_sitter_rust::language(), "rust"))
82 .config(pool_config)
83 .build()
84 .expect("Failed to create Rust parser pool"),
85 );
86
87 pools.insert(
89 "javascript",
90 Pool::builder(ParserManager::new(
91 tree_sitter_javascript::language(),
92 "javascript",
93 ))
94 .config(pool_config)
95 .build()
96 .expect("Failed to create JavaScript parser pool"),
97 );
98
99 pools.insert(
101 "python",
102 Pool::builder(ParserManager::new(tree_sitter_python::language(), "python"))
103 .config(pool_config)
104 .build()
105 .expect("Failed to create Python parser pool"),
106 );
107
108 pools.insert(
110 "typescript",
111 Pool::builder(ParserManager::new(
112 tree_sitter_typescript::language_typescript(),
113 "typescript",
114 ))
115 .config(pool_config)
116 .build()
117 .expect("Failed to create TypeScript parser pool"),
118 );
119
120 pools.insert(
122 "go",
123 Pool::builder(ParserManager::new(tree_sitter_go::language(), "go"))
124 .config(pool_config)
125 .build()
126 .expect("Failed to create Go parser pool"),
127 );
128
129 pools.insert(
131 "java",
132 Pool::builder(ParserManager::new(tree_sitter_java::language(), "java"))
133 .config(pool_config)
134 .build()
135 .expect("Failed to create Java parser pool"),
136 );
137
138 Self { pools }
139 }
140
141 pub async fn get_parser(&self, language: &str) -> Result<PooledParser, ContextCreatorError> {
143 let pool = self.pools.get(language).ok_or_else(|| {
144 ContextCreatorError::ParseError(format!("Unsupported language: {language}"))
145 })?;
146
147 pool.get().await.map_err(|e| {
148 ContextCreatorError::ParseError(format!(
149 "Failed to get {language} parser from pool: {e}"
150 ))
151 })
152 }
153
154 pub fn get_status(&self, language: &str) -> Option<deadpool::Status> {
156 self.pools.get(language).map(|pool| pool.status())
157 }
158}
159
160impl Default for ParserPoolManager {
161 fn default() -> Self {
162 Self::new()
163 }
164}
165
166#[cfg(test)]
167mod tests {
168 use super::*;
169
170 #[tokio::test]
171 async fn test_parser_creation() {
172 let manager = ParserManager::new(tree_sitter_rust::language(), "rust");
173 let parser = manager.create().await.unwrap();
174
175 assert_eq!(parser.timeout_micros(), 5_000_000);
177 }
178
179 #[tokio::test]
180 async fn test_parser_recycling() {
181 let manager = ParserManager::new(tree_sitter_python::language(), "python");
182 let mut parser = manager.create().await.unwrap();
183
184 let result = manager.recycle(&mut parser, &Metrics::default()).await;
186 assert!(result.is_ok());
187 }
188
189 #[tokio::test]
190 async fn test_pool_manager() {
191 let pool_manager = ParserPoolManager::new();
192
193 let rust_parser = pool_manager.get_parser("rust").await;
195 assert!(rust_parser.is_ok());
196
197 let python_parser = pool_manager.get_parser("python").await;
198 assert!(python_parser.is_ok());
199
200 let unknown = pool_manager.get_parser("cobol").await;
202 assert!(unknown.is_err());
203 }
204}