From add6845edf2f7712985b80d2d569e03afd84b5b4 Mon Sep 17 00:00:00 2001 From: asepharyana Date: Thu, 16 Jul 2026 16:07:01 +0700 Subject: [PATCH] refactor(backend): alihkan manajemen session ke zesdex-iam (SessionRepository/SessionLockRepository) Co-Authored-By: Claude Sonnet 5 --- .../src/app/runtime/actions/mod.rs | 6 ++-- crates/zesdex-backend/src/app/state/rest.rs | 2 +- crates/zesdex-backend/src/main.rs | 34 ++++++++++++++----- crates/zesdex-backend/src/model/mod.rs | 6 ---- 4 files changed, 31 insertions(+), 17 deletions(-) diff --git a/crates/zesdex-backend/src/app/runtime/actions/mod.rs b/crates/zesdex-backend/src/app/runtime/actions/mod.rs index 5c0755c..cc91bb0 100644 --- a/crates/zesdex-backend/src/app/runtime/actions/mod.rs +++ b/crates/zesdex-backend/src/app/runtime/actions/mod.rs @@ -24,6 +24,7 @@ use std::fmt::Write; use crate::app::harness::Verdict; use sha2::Digest; use crate::app::review::{should_trigger_review, trigger_review}; +use zesdex_iam::domain::repository::SessionRepository; use crate::app::state::rest::{AppStateRest, ChatMessageDisplay}; use crate::app::state::runtime::TurnEvent; use crate::app::state::types::{Origin, Overlay, Toast, ToastKind}; @@ -1637,11 +1638,12 @@ fn maybe_trigger_review(state: &mut AppStateRest) { /// Why: called on `ForceQuit` so the session can be resumed later. fn save_current_session(state: &AppStateRest) { let base = state.store_base_dir(); - let session = crate::model::session::Session::new( + let session = zesdex_iam::domain::session::Session::new( state.session_id.clone(), "session".to_string(), ); - let _ = session.save(&base); + let session_repo = zesdex_iam::infrastructure::persistence::session_repo::FileSystemSessionRepository::new(); + let _ = session_repo.save_session(&base, &session); if let Some(ref rt) = state.session_runtime { let conv_path = session.conversation_path(&base); if let Ok(data) = serde_json::to_string(&rt.messages) { diff --git a/crates/zesdex-backend/src/app/state/rest.rs b/crates/zesdex-backend/src/app/state/rest.rs index 58c72d5..4eac09f 100644 --- a/crates/zesdex-backend/src/app/state/rest.rs +++ b/crates/zesdex-backend/src/app/state/rest.rs @@ -57,7 +57,7 @@ pub struct AppStateRest { pub mention_index: MentionIndex, pub edit_log: EditLog, pub session_runtime: Option, - pub sessions: Vec, + pub sessions: Vec, pub transcript_cache: TranscriptCache, pub scroll: ScrollState, pub input: InputState, diff --git a/crates/zesdex-backend/src/main.rs b/crates/zesdex-backend/src/main.rs index eebc25a..15bf030 100644 --- a/crates/zesdex-backend/src/main.rs +++ b/crates/zesdex-backend/src/main.rs @@ -14,6 +14,7 @@ use crossterm::execute; use crossterm::terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}; use ratatui::backend::CrosstermBackend; use ratatui::Terminal; +use zesdex_iam::domain::repository::{SessionLockRepository, SessionRepository}; mod app; mod controller; @@ -25,6 +26,21 @@ mod tool; mod resources; mod view; +/// RAII guard that releases a session lock on drop, restoring the +/// panic-safety net the old `entities::SessionLock`'s `Drop` impl provided +/// (the `SessionLockRepository` trait itself is stateless and has no +/// `Drop`, since a repository isn't tied to any one lock's lifetime). +struct SessionLockGuard<'a, L: zesdex_iam::domain::repository::SessionLockRepository> { + lock_repo: &'a L, + session_dir: std::path::PathBuf, +} + +impl Drop for SessionLockGuard<'_, L> { + fn drop(&mut self) { + let _ = self.lock_repo.unlock(&self.session_dir); + } +} + /// Process entry point: parse CLI flags, initialize logging, then dispatch /// to single-process, daemon, or attach mode. /// @@ -98,10 +114,11 @@ fn run_single_process() -> Result<()> { let session_dir = store.base_dir.join("sessions").join(&session_id); std::fs::create_dir_all(&session_dir)?; - let session_lock = model::session_lock::SessionLock::new(&session_dir); - if !session_lock.try_lock()? { + let lock_repo = zesdex_iam::infrastructure::persistence::session_lock_repo::FileSystemSessionLockRepository::new(); + if !lock_repo.try_lock(&session_dir)? { anyhow::bail!("session already active (another zesdex process holds the lock for this session directory)"); } + let _session_lock_guard = SessionLockGuard { lock_repo: &lock_repo, session_dir: session_dir.clone() }; let workspace_roots = vec![std::env::current_dir()?]; let mut state = app::state::rest::AppStateRest::new( @@ -110,7 +127,8 @@ fn run_single_process() -> Result<()> { store.memory_dir, ); state.spawn_mention_index_build(); - state.sessions = model::session::Session::list(&store.base_dir); + let session_repo = zesdex_iam::infrastructure::persistence::session_repo::FileSystemSessionRepository::new(); + state.sessions = session_repo.list_sessions(&store.base_dir).unwrap_or_default(); @@ -139,7 +157,6 @@ fn run_single_process() -> Result<()> { } let _ = state.settings.save(); - session_lock.unlock(); Ok(()) } @@ -432,10 +449,11 @@ fn run_daemon() -> Result<()> { let session_dir = store.base_dir.join("sessions").join(&session_id); std::fs::create_dir_all(&session_dir)?; - let session_lock = model::session_lock::SessionLock::new(&session_dir); - if !session_lock.try_lock()? { + let lock_repo = zesdex_iam::infrastructure::persistence::session_lock_repo::FileSystemSessionLockRepository::new(); + if !lock_repo.try_lock(&session_dir)? { anyhow::bail!("session already active (another zesdex process holds the lock for this session directory)"); } + let _session_lock_guard = SessionLockGuard { lock_repo: &lock_repo, session_dir: session_dir.clone() }; let workspace_roots = vec![std::env::current_dir()?]; let mut state = app::state::rest::AppStateRest::new( @@ -444,7 +462,8 @@ fn run_daemon() -> Result<()> { store.memory_dir, ); state.spawn_mention_index_build(); - state.sessions = model::session::Session::list(&store.base_dir); + let session_repo = zesdex_iam::infrastructure::persistence::session_repo::FileSystemSessionRepository::new(); + state.sessions = session_repo.list_sessions(&store.base_dir).unwrap_or_default(); let _rt = tokio::runtime::Runtime::new()?; @@ -475,7 +494,6 @@ fn run_daemon() -> Result<()> { } let _ = std::fs::remove_file(&socket_path); - session_lock.unlock(); Ok(()) } diff --git a/crates/zesdex-backend/src/model/mod.rs b/crates/zesdex-backend/src/model/mod.rs index c1420bf..83c4c09 100644 --- a/crates/zesdex-backend/src/model/mod.rs +++ b/crates/zesdex-backend/src/model/mod.rs @@ -2,12 +2,6 @@ //! plus local sub-modules (agent_def, msglog) that weren't extracted. // Module re-exports matching original `crate::model::*` paths -pub mod session { - pub use zesdex_entities::seaorm::auth::session::*; -} -pub mod session_lock { - pub use zesdex_entities::seaorm::auth::session_lock::*; -} pub mod settings { pub use zesdex_entities::seaorm::common::settings::*; }