claw_core/store/
context.rs1use chrono::{DateTime, Utc};
9use serde::{Deserialize, Serialize};
10use sqlx::SqlitePool;
11use uuid::Uuid;
12
13use crate::error::{ClawError, ClawResult};
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct ContextRecord {
18 pub id: Uuid,
20 pub session_id: String,
22 pub key: String,
24 pub value: serde_json::Value,
26 pub created_at: DateTime<Utc>,
28 pub expires_at: DateTime<Utc>,
30}
31
32#[derive(Debug)]
34pub struct ContextStore<'a> {
35 pool: &'a SqlitePool,
36}
37
38impl<'a> ContextStore<'a> {
39 pub fn new(pool: &'a SqlitePool) -> Self {
41 ContextStore { pool }
42 }
43
44 pub async fn insert(&self, record: &ContextRecord) -> ClawResult<()> {
50 sqlx::query(
51 r#"
52 INSERT INTO context (id, session_id, key, value, created_at, expires_at)
53 VALUES (?, ?, ?, ?, ?, ?)
54 "#,
55 )
56 .bind(record.id.to_string())
57 .bind(&record.session_id)
58 .bind(&record.key)
59 .bind(serde_json::to_string(&record.value)?)
60 .bind(record.created_at.to_rfc3339())
61 .bind(record.expires_at.to_rfc3339())
62 .execute(self.pool)
63 .await?;
64
65 Ok(())
66 }
67
68 pub async fn purge_expired(&self) -> ClawResult<u64> {
76 let now = Utc::now().to_rfc3339();
77 let result = sqlx::query("DELETE FROM context WHERE expires_at <= ?")
78 .bind(now)
79 .execute(self.pool)
80 .await?;
81
82 Ok(result.rows_affected())
83 }
84
85 pub async fn get_active(&self, session_id: &str) -> ClawResult<Vec<ContextRecord>> {
91 let now = Utc::now().to_rfc3339();
92 let rows = sqlx::query_as::<_, (String, String, String, String, String, String)>(
93 "SELECT id, session_id, key, value, created_at, expires_at \
94 FROM context WHERE session_id = ? AND expires_at > ? ORDER BY created_at ASC",
95 )
96 .bind(session_id)
97 .bind(now)
98 .fetch_all(self.pool)
99 .await?;
100
101 rows.into_iter()
102 .map(|(id, session_id, key, value, created_at, expires_at)| {
103 Ok(ContextRecord {
104 id: Uuid::parse_str(&id).map_err(|e| ClawError::Store(e.to_string()))?,
105 session_id,
106 key,
107 value: serde_json::from_str(&value)?,
108 created_at: DateTime::parse_from_rfc3339(&created_at)
109 .map_err(|e| ClawError::Store(e.to_string()))?
110 .with_timezone(&Utc),
111 expires_at: DateTime::parse_from_rfc3339(&expires_at)
112 .map_err(|e| ClawError::Store(e.to_string()))?
113 .with_timezone(&Utc),
114 })
115 })
116 .collect()
117 }
118}