use crate::error::A2aError;
use crate::types::Task;
use bytes::Bytes;
use klieo_core::KvStore;
use std::sync::Arc;
pub const DEFAULT_BUCKET: &str = "a2a.tasks";
pub struct A2aTaskStore {
kv: Arc<dyn KvStore>,
bucket: String,
}
impl A2aTaskStore {
pub fn new(kv: Arc<dyn KvStore>, bucket: String) -> Self {
Self { kv, bucket }
}
fn task_key(&self, id: &str) -> String {
format!("task.{id}")
}
fn index_key(&self, context_id: &str) -> String {
format!("index.context.{context_id}")
}
pub async fn put(&self, task: &Task) -> Result<(), A2aError> {
let bytes = Bytes::from(serde_json::to_vec(task)?);
self.kv
.put(&self.bucket, &self.task_key(&task.id), bytes)
.await?;
let key = self.index_key(&task.contextId);
let current = self.kv.get(&self.bucket, &key).await?;
let mut ids: Vec<String> = match current {
Some(entry) => serde_json::from_slice(&entry.value)?,
None => vec![],
};
if !ids.contains(&task.id) {
ids.push(task.id.clone());
}
let updated = Bytes::from(serde_json::to_vec(&ids)?);
self.kv.put(&self.bucket, &key, updated).await?;
Ok(())
}
pub async fn get(&self, id: &str) -> Result<Option<Task>, A2aError> {
match self.kv.get(&self.bucket, &self.task_key(id)).await? {
Some(entry) => Ok(Some(serde_json::from_slice(&entry.value)?)),
None => Ok(None),
}
}
pub async fn list(&self, context_id: Option<&str>) -> Result<Vec<Task>, A2aError> {
let Some(ctx) = context_id else {
return Ok(vec![]);
};
let entry = self.kv.get(&self.bucket, &self.index_key(ctx)).await?;
let ids: Vec<String> = match entry {
Some(e) => serde_json::from_slice(&e.value)?,
None => return Ok(vec![]),
};
let mut out = Vec::with_capacity(ids.len());
for id in ids {
if let Some(t) = self.get(&id).await? {
out.push(t);
}
}
Ok(out)
}
pub async fn delete(&self, id: &str) -> Result<(), A2aError> {
let task = self.get(id).await?;
self.kv.delete(&self.bucket, &self.task_key(id)).await?;
if let Some(t) = task {
let key = self.index_key(&t.contextId);
if let Some(entry) = self.kv.get(&self.bucket, &key).await? {
let mut ids: Vec<String> = serde_json::from_slice(&entry.value)?;
ids.retain(|x| x != id);
let updated = Bytes::from(serde_json::to_vec(&ids)?);
self.kv.put(&self.bucket, &key, updated).await?;
}
}
Ok(())
}
}