use crate::error::RunLogError;
use crate::types::RunLog;
use async_trait::async_trait;
use klieo_core::ids::RunId;
use std::collections::HashMap;
use tokio::sync::Mutex;
#[async_trait]
pub trait RunLogStore: Send + Sync {
async fn put(&self, run_log: &RunLog) -> Result<(), RunLogError>;
async fn get(&self, run_id: RunId) -> Result<Option<RunLog>, RunLogError>;
async fn list(&self, agent: Option<&str>, limit: usize) -> Result<Vec<RunLog>, RunLogError>;
async fn delete(&self, run_id: RunId) -> Result<(), RunLogError>;
}
#[derive(Default)]
pub struct InMemoryRunLogStore {
inner: Mutex<HashMap<RunId, RunLog>>,
}
impl InMemoryRunLogStore {
pub fn new() -> Self {
Self::default()
}
}
#[async_trait]
impl RunLogStore for InMemoryRunLogStore {
async fn put(&self, run_log: &RunLog) -> Result<(), RunLogError> {
let mut g = self.inner.lock().await;
g.insert(run_log.run_id, run_log.clone());
Ok(())
}
async fn get(&self, run_id: RunId) -> Result<Option<RunLog>, RunLogError> {
let g = self.inner.lock().await;
Ok(g.get(&run_id).cloned())
}
async fn list(&self, agent: Option<&str>, limit: usize) -> Result<Vec<RunLog>, RunLogError> {
let g = self.inner.lock().await;
let mut rows: Vec<RunLog> = g
.values()
.filter(|r| match agent {
Some(a) => r.agent == a,
None => true,
})
.cloned()
.collect();
rows.sort_by(|a, b| b.started_at.cmp(&a.started_at));
rows.truncate(limit);
Ok(rows)
}
async fn delete(&self, run_id: RunId) -> Result<(), RunLogError> {
let mut g = self.inner.lock().await;
g.remove(&run_id);
Ok(())
}
}