1use std::path::PathBuf;
7
8use async_trait::async_trait;
9
10use super::{Session, SessionError, SessionId, SessionService};
11use crate::events::Event;
12
13#[derive(Debug, Clone)]
15pub struct SqliteSessionConfig {
16 pub db_path: PathBuf,
18}
19
20impl SqliteSessionConfig {
21 pub fn in_memory() -> Self {
23 Self {
24 db_path: PathBuf::from(":memory:"),
25 }
26 }
27}
28
29pub struct SqliteSessionService {
36 config: SqliteSessionConfig,
37 inner: super::InMemorySessionService,
40}
41
42impl SqliteSessionService {
43 pub fn new(config: SqliteSessionConfig) -> Self {
47 Self {
52 config,
53 inner: super::InMemorySessionService::new(),
54 }
55 }
56
57 pub fn db_path(&self) -> &std::path::Path {
59 &self.config.db_path
60 }
61}
62
63#[async_trait]
64impl SessionService for SqliteSessionService {
65 async fn create_session(&self, app_name: &str, user_id: &str) -> Result<Session, SessionError> {
66 self.inner.create_session(app_name, user_id).await
69 }
70
71 async fn get_session(&self, id: &SessionId) -> Result<Option<Session>, SessionError> {
72 self.inner.get_session(id).await
73 }
74
75 async fn list_sessions(
76 &self,
77 app_name: &str,
78 user_id: &str,
79 ) -> Result<Vec<Session>, SessionError> {
80 self.inner.list_sessions(app_name, user_id).await
81 }
82
83 async fn delete_session(&self, id: &SessionId) -> Result<(), SessionError> {
84 self.inner.delete_session(id).await
85 }
86
87 async fn append_event(&self, id: &SessionId, event: Event) -> Result<(), SessionError> {
88 self.inner.append_event(id, event).await
89 }
90
91 async fn get_events(&self, id: &SessionId) -> Result<Vec<Event>, SessionError> {
92 self.inner.get_events(id).await
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[tokio::test]
101 async fn create_and_get() {
102 let svc = SqliteSessionService::new(SqliteSessionConfig::in_memory());
103 let session = svc.create_session("app", "user").await.unwrap();
104 let fetched = svc.get_session(&session.id).await.unwrap();
105 assert!(fetched.is_some());
106 }
107
108 #[test]
109 fn db_path() {
110 let svc = SqliteSessionService::new(SqliteSessionConfig {
111 db_path: PathBuf::from("/tmp/test.db"),
112 });
113 assert_eq!(svc.db_path(), std::path::Path::new("/tmp/test.db"));
114 }
115
116 #[test]
117 fn in_memory_config() {
118 let config = SqliteSessionConfig::in_memory();
119 assert_eq!(config.db_path, PathBuf::from(":memory:"));
120 }
121}