//! Session management use-case. //! //! `SessionServiceImpl` implements [`SessionService`] from the domain //! layer by delegating CRUD operations to injected repository traits. //! //! # Flow //! //! - **`create_session`** — generates a UUID v4 id, creates a `Session` //! entity with the given title, persists via `SessionRepository`. //! - **`list_all`** — delegates to `SessionRepository::list_sessions`. //! - **`archive_session`** — loads session, sets `archived = true`, //! persists the updated entity. //! //! # Generics //! //! - `R: SessionRepository` — session CRUD persistence //! - `L: SessionLockRepository` — session lock acquire/release use std::path::PathBuf; use tracing; use uuid::Uuid; use zesdex_domain::auth::{ ServiceError, Session, SessionId, SessionLockRepository, SessionRepository, }; /// Concrete session service backed by injected repository implementations. pub struct SessionServiceImpl { /// Repository for session CRUD operations. pub session_repo: R, /// Repository for session lock acquire/release. pub lock_repo: L, /// Base data directory passed to repository methods. pub base_dir: PathBuf, } impl SessionServiceImpl { /// Create a new session service with the given repositories and base /// data directory. pub fn new(session_repo: R, lock_repo: L, base_dir: PathBuf) -> Self { SessionServiceImpl { session_repo, lock_repo, base_dir, } } } impl zesdex_domain::auth::SessionService for SessionServiceImpl { fn create_session(&self, title: &str) -> Result { let id = SessionId::new(&Uuid::new_v4().to_string()) .map_err(ServiceError::Other)?; let title_owned = if title.is_empty() { "New Session".to_string() } else { title.to_string() }; let session = Session::new(id.into_string(), title_owned); tracing::debug!(session_id = %session.id, title = %session.title, "creating new session"); self.session_repo .save_session(&self.base_dir, &session)?; Ok(session) } fn list_all(&self) -> Result, ServiceError> { tracing::debug!("listing all sessions"); self.session_repo .list_sessions(&self.base_dir) .map_err(ServiceError::Repository) } fn archive_session(&self, id: SessionId) -> Result<(), ServiceError> { tracing::debug!(session_id = %id, "archiving session"); let mut session = self .session_repo .load_session(&self.base_dir, &id)?; session.archived = true; let millis = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap_or_default() .as_millis(); session.updated_at = i64::try_from(millis).unwrap_or(i64::MAX); self.session_repo .save_session(&self.base_dir, &session)?; Ok(()) } }