1use anyhow::Result;
2use async_trait::async_trait;
3use dashmap::DashMap;
4
5use crate::{ConversationScope, SessionKey, SessionRecord, SessionStore};
6
7#[derive(Default)]
8pub struct MemorySessionStore {
9 by_session: DashMap<String, SessionRecord>,
10 by_scope: DashMap<String, SessionKey>,
11}
12
13impl MemorySessionStore {
14 pub fn new() -> Self {
15 Self {
16 by_session: DashMap::new(),
17 by_scope: DashMap::new(),
18 }
19 }
20
21 fn session_key(key: &SessionKey) -> String {
22 key.as_str().to_string()
23 }
24}
25
26#[async_trait]
27impl SessionStore for MemorySessionStore {
28 async fn save(&self, record: SessionRecord) -> Result<()> {
29 let scope_key = record.scope.cache_key();
30 let session_key = Self::session_key(&record.key);
31 self.by_scope.insert(scope_key, record.key.clone());
32 self.by_session.insert(session_key, record);
33 Ok(())
34 }
35
36 async fn get(&self, key: &SessionKey) -> Result<Option<SessionRecord>> {
37 Ok(self
38 .by_session
39 .get(&Self::session_key(key))
40 .map(|entry| entry.value().clone()))
41 }
42
43 async fn find_by_scope(&self, scope: &ConversationScope) -> Result<Option<SessionRecord>> {
44 if let Some(session_id) = self.by_scope.get(&scope.cache_key()) {
45 let key = session_id.value().clone();
46 return self.get(&key).await;
47 }
48 Ok(None)
49 }
50
51 async fn delete(&self, key: &SessionKey) -> Result<()> {
52 if let Some(entry) = self.by_session.remove(&Self::session_key(key)) {
53 let (_k, record) = entry;
54 self.by_scope.remove(&record.scope.cache_key());
55 }
56 Ok(())
57 }
58}