gemini_adk_rs/session/
sqlite.rs1use std::path::PathBuf;
12
13use async_trait::async_trait;
14
15use super::{Session, SessionError, SessionId, SessionService};
16use crate::events::Event;
17
18#[derive(Debug, Clone)]
20pub struct SqliteSessionConfig {
21 pub db_path: PathBuf,
23}
24
25impl SqliteSessionConfig {
26 pub fn in_memory() -> Self {
28 Self {
29 db_path: PathBuf::from(":memory:"),
30 }
31 }
32}
33
34#[cfg(feature = "database-sessions")]
39type Backend = super::DatabaseSessionService;
40#[cfg(not(feature = "database-sessions"))]
41type Backend = super::InMemorySessionService;
42
43pub struct SqliteSessionService {
50 config: SqliteSessionConfig,
51 inner: Backend,
52}
53
54impl SqliteSessionService {
55 pub fn new(config: SqliteSessionConfig) -> Self {
60 let inner = Self::build_backend(&config);
61 Self { config, inner }
62 }
63
64 #[cfg(feature = "database-sessions")]
65 fn build_backend(config: &SqliteSessionConfig) -> Backend {
66 let path = config.db_path.to_string_lossy();
67 let url = if path == ":memory:" {
70 "sqlite::memory:".to_string()
71 } else {
72 format!("sqlite://{path}")
73 };
74 super::DatabaseSessionService::new(url)
75 }
76
77 #[cfg(not(feature = "database-sessions"))]
78 fn build_backend(_config: &SqliteSessionConfig) -> Backend {
79 super::InMemorySessionService::new()
80 }
81
82 pub fn db_path(&self) -> &std::path::Path {
84 &self.config.db_path
85 }
86}
87
88#[async_trait]
89impl SessionService for SqliteSessionService {
90 async fn create_session(&self, app_name: &str, user_id: &str) -> Result<Session, SessionError> {
91 self.inner.create_session(app_name, user_id).await
92 }
93
94 async fn get_session(&self, id: &SessionId) -> Result<Option<Session>, SessionError> {
95 self.inner.get_session(id).await
96 }
97
98 async fn list_sessions(
99 &self,
100 app_name: &str,
101 user_id: &str,
102 ) -> Result<Vec<Session>, SessionError> {
103 self.inner.list_sessions(app_name, user_id).await
104 }
105
106 async fn delete_session(&self, id: &SessionId) -> Result<(), SessionError> {
107 self.inner.delete_session(id).await
108 }
109
110 async fn append_event(&self, id: &SessionId, event: Event) -> Result<(), SessionError> {
111 self.inner.append_event(id, event).await
112 }
113
114 async fn get_events(&self, id: &SessionId) -> Result<Vec<Event>, SessionError> {
115 self.inner.get_events(id).await
116 }
117}
118
119#[cfg(test)]
120mod tests {
121 use super::*;
122
123 #[tokio::test]
124 async fn create_and_get() {
125 let svc = SqliteSessionService::new(SqliteSessionConfig::in_memory());
126 let session = svc.create_session("app", "user").await.unwrap();
127 let fetched = svc.get_session(&session.id).await.unwrap();
128 assert!(fetched.is_some());
129 }
130
131 #[test]
132 fn db_path() {
133 let svc = SqliteSessionService::new(SqliteSessionConfig {
134 db_path: PathBuf::from("/tmp/test.db"),
135 });
136 assert_eq!(svc.db_path(), std::path::Path::new("/tmp/test.db"));
137 }
138
139 #[test]
140 fn in_memory_config() {
141 let config = SqliteSessionConfig::in_memory();
142 assert_eq!(config.db_path, PathBuf::from(":memory:"));
143 }
144}