gsm_session/
lib.rs

1use anyhow::Result;
2pub use greentic_session::{SessionData, SessionKey};
3use greentic_session::{SessionStore, inmemory::InMemorySessionStore};
4use greentic_types::{TenantCtx, UserId};
5use std::sync::Arc;
6
7/// Shared session store handle that wraps the greentic-session backends.
8#[derive(Clone)]
9pub struct SharedSessionStore {
10    inner: Arc<InMemorySessionStore>,
11}
12
13/// Builds a session store from environment configuration.
14pub async fn store_from_env() -> Result<SharedSessionStore> {
15    Ok(shared_memory_store())
16}
17
18/// Returns an in-memory session store.
19pub fn shared_memory_store() -> SharedSessionStore {
20    SharedSessionStore {
21        inner: Arc::new(InMemorySessionStore::new()),
22    }
23}
24
25impl SharedSessionStore {
26    /// Looks up the active session bound to the provided tenant + user combination.
27    pub async fn find_by_user(
28        &self,
29        ctx: &TenantCtx,
30        user: &UserId,
31    ) -> Result<Option<(SessionKey, SessionData)>> {
32        let waits = self.inner.list_waits_for_user(ctx, user)?;
33        match waits.len() {
34            0 => Ok(None),
35            1 => {
36                let key = waits.into_iter().next().expect("single wait entry");
37                let data = self
38                    .inner
39                    .get_session(&key)?
40                    .ok_or_else(|| anyhow::anyhow!("session not found for wait"))?;
41                Ok(Some((key, data)))
42            }
43            _ => Err(anyhow::anyhow!(
44                "multiple waits exist for user; use scope-based routing instead"
45            )),
46        }
47    }
48
49    /// Creates a new session and returns its key.
50    pub async fn create_session(&self, ctx: &TenantCtx, data: SessionData) -> Result<SessionKey> {
51        self.inner.create_session(ctx, data).map_err(Into::into)
52    }
53
54    /// Updates an existing session with the supplied snapshot.
55    pub async fn update_session(&self, key: &SessionKey, data: SessionData) -> Result<()> {
56        self.inner.update_session(key, data).map_err(Into::into)
57    }
58}