burncloud_database_client/
burncloud_repositories.rs1use crate::{BaseRepository, QueryExecutor, QueryContext, QueryOptions};
4use burncloud_database_core::error::DatabaseResult;
5use crate::models::*;
6use burncloud_database_core::error::DatabaseError;
7use async_trait::async_trait;
8use std::sync::Arc;
9use chrono::{DateTime, Utc};
10use uuid::Uuid;
11
12pub struct AiModelRepository {
14 pub base: BaseRepository<AiModel>,
15}
16
17impl AiModelRepository {
18 pub fn new(query_executor: Box<dyn QueryExecutor>) -> Self {
19 Self {
20 base: BaseRepository::new(query_executor, "ai_models".to_string()),
21 }
22 }
23
24 pub async fn find_by_status(&self, status: ModelStatus, context: &QueryContext) -> DatabaseResult<Vec<AiModel>> {
26 let query = "SELECT * FROM ai_models WHERE status = $1";
27 let status_str = serde_json::to_string(&status)
28 .map_err(|e| DatabaseError::SerializationError(e.to_string()))?;
29 let status_param = burncloud_database_impl::StringParam(status_str);
30 let params: Vec<&dyn burncloud_database_core::QueryParam> = vec![&status_param];
31
32 let result = self.base.query_executor.execute_query(query, ¶ms, context).await?;
33
34 let mut models = Vec::new();
35 for row in result.rows {
36 let model: AiModel = serde_json::from_value(serde_json::Value::Object(
37 row.iter().map(|(k, v)| (k.clone(), v.clone())).collect()
38 )).map_err(|e| DatabaseError::SerializationError(e.to_string()))?;
39 models.push(model);
40 }
41
42 Ok(models)
43 }
44
45 pub async fn find_by_type(&self, model_type: ModelType, context: &QueryContext) -> DatabaseResult<Vec<AiModel>> {
47 let query = "SELECT * FROM ai_models WHERE model_type = $1";
48 let type_str = serde_json::to_string(&model_type)
49 .map_err(|e| DatabaseError::SerializationError(e.to_string()))?;
50 let type_param = burncloud_database_impl::StringParam(type_str);
51 let params: Vec<&dyn burncloud_database_core::QueryParam> = vec![&type_param];
52
53 let result = self.base.query_executor.execute_query(query, ¶ms, context).await?;
54
55 let mut models = Vec::new();
56 for row in result.rows {
57 let model: AiModel = serde_json::from_value(serde_json::Value::Object(
58 row.iter().map(|(k, v)| (k.clone(), v.clone())).collect()
59 )).map_err(|e| DatabaseError::SerializationError(e.to_string()))?;
60 models.push(model);
61 }
62
63 Ok(models)
64 }
65
66 pub async fn search(&self, query_text: &str, context: &QueryContext) -> DatabaseResult<Vec<AiModel>> {
68 let query = "SELECT * FROM ai_models WHERE name ILIKE $1 OR description ILIKE $1";
69 let search_pattern = format!("%{}%", query_text);
70 let search_param = burncloud_database_impl::StringParam(search_pattern);
71 let params: Vec<&dyn burncloud_database_core::QueryParam> = vec![&search_param];
72
73 let result = self.base.query_executor.execute_query(query, ¶ms, context).await?;
74
75 let mut models = Vec::new();
76 for row in result.rows {
77 let model: AiModel = serde_json::from_value(serde_json::Value::Object(
78 row.iter().map(|(k, v)| (k.clone(), v.clone())).collect()
79 )).map_err(|e| DatabaseError::SerializationError(e.to_string()))?;
80 models.push(model);
81 }
82
83 Ok(models)
84 }
85}
86
87pub struct ModelDeploymentRepository {
89 pub base: BaseRepository<ModelDeployment>,
90}
91
92impl ModelDeploymentRepository {
93 pub fn new(query_executor: Box<dyn QueryExecutor>) -> Self {
94 Self {
95 base: BaseRepository::new(query_executor, "model_deployments".to_string()),
96 }
97 }
98
99 pub async fn find_by_model_id(&self, model_id: Uuid, context: &QueryContext) -> DatabaseResult<Vec<ModelDeployment>> {
101 let query = "SELECT * FROM model_deployments WHERE model_id = $1";
102 let model_id_param = burncloud_database_impl::StringParam(model_id.to_string());
103 let params: Vec<&dyn burncloud_database_core::QueryParam> = vec![&model_id_param];
104
105 let result = self.base.query_executor.execute_query(query, ¶ms, context).await?;
106
107 let mut deployments = Vec::new();
108 for row in result.rows {
109 let deployment: ModelDeployment = serde_json::from_value(serde_json::Value::Object(
110 row.iter().map(|(k, v)| (k.clone(), v.clone())).collect()
111 )).map_err(|e| DatabaseError::SerializationError(e.to_string()))?;
112 deployments.push(deployment);
113 }
114
115 Ok(deployments)
116 }
117
118 pub async fn find_by_status(&self, status: DeploymentStatus, context: &QueryContext) -> DatabaseResult<Vec<ModelDeployment>> {
120 let query = "SELECT * FROM model_deployments WHERE status = $1";
121 let status_str = serde_json::to_string(&status)
122 .map_err(|e| DatabaseError::SerializationError(e.to_string()))?;
123 let status_param = burncloud_database_impl::StringParam(status_str);
124 let params: Vec<&dyn burncloud_database_core::QueryParam> = vec![&status_param];
125
126 let result = self.base.query_executor.execute_query(query, ¶ms, context).await?;
127
128 let mut deployments = Vec::new();
129 for row in result.rows {
130 let deployment: ModelDeployment = serde_json::from_value(serde_json::Value::Object(
131 row.iter().map(|(k, v)| (k.clone(), v.clone())).collect()
132 )).map_err(|e| DatabaseError::SerializationError(e.to_string()))?;
133 deployments.push(deployment);
134 }
135
136 Ok(deployments)
137 }
138
139 pub async fn find_by_port(&self, port: u16, context: &QueryContext) -> DatabaseResult<Option<ModelDeployment>> {
141 let query = "SELECT * FROM model_deployments WHERE port = $1 LIMIT 1";
142 let port_param = burncloud_database_impl::I64Param(port as i64);
143 let params: Vec<&dyn burncloud_database_core::QueryParam> = vec![&port_param];
144
145 let result = self.base.query_executor.execute_query(query, ¶ms, context).await?;
146
147 if result.rows.is_empty() {
148 Ok(None)
149 } else {
150 let deployment: ModelDeployment = serde_json::from_value(serde_json::Value::Object(
151 result.rows[0].iter().map(|(k, v)| (k.clone(), v.clone())).collect()
152 )).map_err(|e| DatabaseError::SerializationError(e.to_string()))?;
153 Ok(Some(deployment))
154 }
155 }
156
157 pub async fn get_running_deployments(&self, context: &QueryContext) -> DatabaseResult<Vec<ModelDeployment>> {
159 self.find_by_status(DeploymentStatus::Running, context).await
160 }
161}
162
163pub struct SystemMetricsRepository {
165 pub base: BaseRepository<SystemMetrics>,
166}
167
168impl SystemMetricsRepository {
169 pub fn new(query_executor: Box<dyn QueryExecutor>) -> Self {
170 Self {
171 base: BaseRepository::new(query_executor, "system_metrics".to_string()),
172 }
173 }
174
175 pub async fn find_by_time_range(
177 &self,
178 start_time: DateTime<Utc>,
179 end_time: DateTime<Utc>,
180 context: &QueryContext,
181 ) -> DatabaseResult<Vec<SystemMetrics>> {
182 let query = "SELECT * FROM system_metrics WHERE timestamp >= $1 AND timestamp <= $2 ORDER BY timestamp DESC";
183 let start_param = burncloud_database_impl::StringParam(start_time.to_rfc3339());
184 let end_param = burncloud_database_impl::StringParam(end_time.to_rfc3339());
185 let params: Vec<&dyn burncloud_database_core::QueryParam> = vec![&start_param, &end_param];
186
187 let result = self.base.query_executor.execute_query(query, ¶ms, context).await?;
188
189 let mut metrics = Vec::new();
190 for row in result.rows {
191 let metric: SystemMetrics = serde_json::from_value(serde_json::Value::Object(
192 row.iter().map(|(k, v)| (k.clone(), v.clone())).collect()
193 )).map_err(|e| DatabaseError::SerializationError(e.to_string()))?;
194 metrics.push(metric);
195 }
196
197 Ok(metrics)
198 }
199
200 pub async fn get_latest(&self, context: &QueryContext) -> DatabaseResult<Option<SystemMetrics>> {
202 let query = "SELECT * FROM system_metrics ORDER BY timestamp DESC LIMIT 1";
203 let params: Vec<&dyn burncloud_database_core::QueryParam> = vec![];
204
205 let result = self.base.query_executor.execute_query(query, ¶ms, context).await?;
206
207 if result.rows.is_empty() {
208 Ok(None)
209 } else {
210 let metric: SystemMetrics = serde_json::from_value(serde_json::Value::Object(
211 result.rows[0].iter().map(|(k, v)| (k.clone(), v.clone())).collect()
212 )).map_err(|e| DatabaseError::SerializationError(e.to_string()))?;
213 Ok(Some(metric))
214 }
215 }
216
217 pub async fn cleanup_old_metrics(&self, before_time: DateTime<Utc>, context: &QueryContext) -> DatabaseResult<u64> {
219 let query = "DELETE FROM system_metrics WHERE timestamp < $1";
220 let time_param = burncloud_database_impl::StringParam(before_time.to_rfc3339());
221 let params: Vec<&dyn burncloud_database_core::QueryParam> = vec![&time_param];
222
223 let result = self.base.query_executor.execute_query(query, ¶ms, context).await?;
224 Ok(result.rows_affected)
225 }
226}
227
228pub struct ModelMetricsRepository {
230 pub base: BaseRepository<ModelMetrics>,
231}
232
233impl ModelMetricsRepository {
234 pub fn new(query_executor: Box<dyn QueryExecutor>) -> Self {
235 Self {
236 base: BaseRepository::new(query_executor, "model_metrics".to_string()),
237 }
238 }
239
240 pub async fn find_by_deployment_id(
242 &self,
243 deployment_id: Uuid,
244 start_time: DateTime<Utc>,
245 end_time: DateTime<Utc>,
246 context: &QueryContext,
247 ) -> DatabaseResult<Vec<ModelMetrics>> {
248 let query = "SELECT * FROM model_metrics WHERE deployment_id = $1 AND timestamp >= $2 AND timestamp <= $3 ORDER BY timestamp DESC";
249 let deployment_param = burncloud_database_impl::StringParam(deployment_id.to_string());
250 let start_param = burncloud_database_impl::StringParam(start_time.to_rfc3339());
251 let end_param = burncloud_database_impl::StringParam(end_time.to_rfc3339());
252 let params: Vec<&dyn burncloud_database_core::QueryParam> = vec![&deployment_param, &start_param, &end_param];
253
254 let result = self.base.query_executor.execute_query(query, ¶ms, context).await?;
255
256 let mut metrics = Vec::new();
257 for row in result.rows {
258 let metric: ModelMetrics = serde_json::from_value(serde_json::Value::Object(
259 row.iter().map(|(k, v)| (k.clone(), v.clone())).collect()
260 )).map_err(|e| DatabaseError::SerializationError(e.to_string()))?;
261 metrics.push(metric);
262 }
263
264 Ok(metrics)
265 }
266
267 pub async fn get_latest_for_deployment(&self, deployment_id: Uuid, context: &QueryContext) -> DatabaseResult<Option<ModelMetrics>> {
269 let query = "SELECT * FROM model_metrics WHERE deployment_id = $1 ORDER BY timestamp DESC LIMIT 1";
270 let deployment_param = burncloud_database_impl::StringParam(deployment_id.to_string());
271 let params: Vec<&dyn burncloud_database_core::QueryParam> = vec![&deployment_param];
272
273 let result = self.base.query_executor.execute_query(query, ¶ms, context).await?;
274
275 if result.rows.is_empty() {
276 Ok(None)
277 } else {
278 let metric: ModelMetrics = serde_json::from_value(serde_json::Value::Object(
279 result.rows[0].iter().map(|(k, v)| (k.clone(), v.clone())).collect()
280 )).map_err(|e| DatabaseError::SerializationError(e.to_string()))?;
281 Ok(Some(metric))
282 }
283 }
284}
285
286pub struct RequestLogRepository {
288 pub base: BaseRepository<RequestLog>,
289}
290
291impl RequestLogRepository {
292 pub fn new(query_executor: Box<dyn QueryExecutor>) -> Self {
293 Self {
294 base: BaseRepository::new(query_executor, "request_logs".to_string()),
295 }
296 }
297
298 pub async fn find_by_deployment_id(
300 &self,
301 deployment_id: Uuid,
302 start_time: DateTime<Utc>,
303 end_time: DateTime<Utc>,
304 context: &QueryContext,
305 ) -> DatabaseResult<Vec<RequestLog>> {
306 let query = "SELECT * FROM request_logs WHERE deployment_id = $1 AND timestamp >= $2 AND timestamp <= $3 ORDER BY timestamp DESC";
307 let deployment_param = burncloud_database_impl::StringParam(deployment_id.to_string());
308 let start_param = burncloud_database_impl::StringParam(start_time.to_rfc3339());
309 let end_param = burncloud_database_impl::StringParam(end_time.to_rfc3339());
310 let params: Vec<&dyn burncloud_database_core::QueryParam> = vec![&deployment_param, &start_param, &end_param];
311
312 let result = self.base.query_executor.execute_query(query, ¶ms, context).await?;
313
314 let mut logs = Vec::new();
315 for row in result.rows {
316 let log: RequestLog = serde_json::from_value(serde_json::Value::Object(
317 row.iter().map(|(k, v)| (k.clone(), v.clone())).collect()
318 )).map_err(|e| DatabaseError::SerializationError(e.to_string()))?;
319 logs.push(log);
320 }
321
322 Ok(logs)
323 }
324
325 pub async fn find_errors(
327 &self,
328 start_time: DateTime<Utc>,
329 end_time: DateTime<Utc>,
330 context: &QueryContext,
331 ) -> DatabaseResult<Vec<RequestLog>> {
332 let query = "SELECT * FROM request_logs WHERE status_code >= 400 AND timestamp >= $1 AND timestamp <= $2 ORDER BY timestamp DESC";
333 let start_param = burncloud_database_impl::StringParam(start_time.to_rfc3339());
334 let end_param = burncloud_database_impl::StringParam(end_time.to_rfc3339());
335 let params: Vec<&dyn burncloud_database_core::QueryParam> = vec![&start_param, &end_param];
336
337 let result = self.base.query_executor.execute_query(query, ¶ms, context).await?;
338
339 let mut logs = Vec::new();
340 for row in result.rows {
341 let log: RequestLog = serde_json::from_value(serde_json::Value::Object(
342 row.iter().map(|(k, v)| (k.clone(), v.clone())).collect()
343 )).map_err(|e| DatabaseError::SerializationError(e.to_string()))?;
344 logs.push(log);
345 }
346
347 Ok(logs)
348 }
349}
350
351pub struct UserSettingsRepository {
353 pub base: BaseRepository<UserSettings>,
354}
355
356impl UserSettingsRepository {
357 pub fn new(query_executor: Box<dyn QueryExecutor>) -> Self {
358 Self {
359 base: BaseRepository::new(query_executor, "user_settings".to_string()),
360 }
361 }
362
363 pub async fn find_by_user_id(&self, user_id: &str, context: &QueryContext) -> DatabaseResult<Option<UserSettings>> {
365 let query = "SELECT * FROM user_settings WHERE user_id = $1 LIMIT 1";
366 let user_param = burncloud_database_impl::StringParam(user_id.to_string());
367 let params: Vec<&dyn burncloud_database_core::QueryParam> = vec![&user_param];
368
369 let result = self.base.query_executor.execute_query(query, ¶ms, context).await?;
370
371 if result.rows.is_empty() {
372 Ok(None)
373 } else {
374 let settings: UserSettings = serde_json::from_value(serde_json::Value::Object(
375 result.rows[0].iter().map(|(k, v)| (k.clone(), v.clone())).collect()
376 )).map_err(|e| DatabaseError::SerializationError(e.to_string()))?;
377 Ok(Some(settings))
378 }
379 }
380}
381
382pub struct SecurityConfigRepository {
384 pub base: BaseRepository<SecurityConfig>,
385}
386
387impl SecurityConfigRepository {
388 pub fn new(query_executor: Box<dyn QueryExecutor>) -> Self {
389 Self {
390 base: BaseRepository::new(query_executor, "security_configs".to_string()),
391 }
392 }
393
394 pub async fn get_current(&self, context: &QueryContext) -> DatabaseResult<Option<SecurityConfig>> {
396 let query = "SELECT * FROM security_configs ORDER BY created_at DESC LIMIT 1";
397 let params: Vec<&dyn burncloud_database_core::QueryParam> = vec![];
398
399 let result = self.base.query_executor.execute_query(query, ¶ms, context).await?;
400
401 if result.rows.is_empty() {
402 Ok(None)
403 } else {
404 let config: SecurityConfig = serde_json::from_value(serde_json::Value::Object(
405 result.rows[0].iter().map(|(k, v)| (k.clone(), v.clone())).collect()
406 )).map_err(|e| DatabaseError::SerializationError(e.to_string()))?;
407 Ok(Some(config))
408 }
409 }
410}