docs: tambah doc comment, logging, dan inline comments di semua 255 file
Meliputi: - File-level //! doc comment: tujuan file, alur kerja, komponen utama - Function-level /// doc comment: apa, parameter, return, flow, edge cases - Struct/enum/trait /// doc comment: peran, field docs - Tracing logging (tracing::info!/debug!/trace!/warn!/error!) di setiap fungsi - Inline comments untuk variable dan branching logic penting - Seluruh 8 crates di workspace: zesdex-backend, zesdex-cms, zesdex-entities, zesdex-iam, zesdex-infra, zesdex-ipc, zesdex-middleware, zesdex-utils - Build: 0 errors, 242/242 tests passed
This commit is contained in:
@@ -1,23 +1,46 @@
|
||||
//! Conversation use-case implementations.
|
||||
//! Conversation use-case implementations for the CMS.
|
||||
//!
|
||||
//! `ConversationServiceImpl` is generic over `R: ConversationRepository`,
|
||||
//! delegating all persistence to that adapter.
|
||||
//! `ConversationServiceImpl` implements `ConversationService` (defined in
|
||||
//! `domain::service`) and is generic over `R: ConversationRepository`
|
||||
//! (defined in `domain::repository`), delegating all persistence to that
|
||||
//! adapter. The repository is injected at composition root.
|
||||
//!
|
||||
//! ## Flow
|
||||
//! Each method computes the session directory from the session ID, then
|
||||
//! delegates the actual I/O to the injected `repo`. Error context is
|
||||
//! added at this layer to identify which session caused the failure.
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use tracing;
|
||||
|
||||
use crate::domain::conversation::{ChatMessage, Conversation};
|
||||
use crate::domain::repository::ConversationRepository;
|
||||
use crate::domain::service::ConversationService;
|
||||
|
||||
/// Generic conversation service backed by an injected repository.
|
||||
/// Service implementation for conversation CRUD operations.
|
||||
///
|
||||
/// Generic over `R: ConversationRepository` so the persistence layer
|
||||
/// can be swapped without changing business logic.
|
||||
///
|
||||
/// ## Fields
|
||||
/// - `repo` — injected conversation repository implementation
|
||||
/// - `sessions_dir` — base path under which session directories live
|
||||
pub struct ConversationServiceImpl<R> {
|
||||
pub repo: R,
|
||||
pub sessions_dir: std::path::PathBuf,
|
||||
/// Base directory containing session subdirectories.
|
||||
pub sessions_dir: PathBuf,
|
||||
}
|
||||
|
||||
impl<R: ConversationRepository> ConversationServiceImpl<R> {
|
||||
/// Create a new service with the given repository and sessions directory.
|
||||
pub fn new(repo: R, sessions_dir: impl Into<std::path::PathBuf>) -> Self {
|
||||
///
|
||||
/// ## Parameters
|
||||
/// - `repo` — the repository adapter to delegate persistence to
|
||||
/// - `sessions_dir` — base path for session directories (converted via `Into`)
|
||||
pub fn new(repo: R, sessions_dir: impl Into<PathBuf>) -> Self {
|
||||
tracing::debug!("creating ConversationServiceImpl");
|
||||
Self {
|
||||
repo,
|
||||
sessions_dir: sessions_dir.into(),
|
||||
@@ -25,20 +48,30 @@ impl<R: ConversationRepository> ConversationServiceImpl<R> {
|
||||
}
|
||||
|
||||
/// Compute the session directory for a given session id.
|
||||
fn session_dir(&self, session_id: &str) -> std::path::PathBuf {
|
||||
///
|
||||
/// Returns `{sessions_dir}/{session_id}`.
|
||||
fn session_dir(&self, session_id: &str) -> PathBuf {
|
||||
self.sessions_dir.join(session_id)
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: ConversationRepository> ConversationService for ConversationServiceImpl<R> {
|
||||
/// Load a conversation from disk for the given session.
|
||||
///
|
||||
/// Flow: resolve session dir → delegate to repo.load() → wrap error with context.
|
||||
fn load_conversation(&self, session_id: &str) -> Result<Conversation> {
|
||||
tracing::debug!("loading conversation for session {session_id}");
|
||||
let dir = self.session_dir(session_id);
|
||||
self.repo
|
||||
.load(&dir)
|
||||
.with_context(|| format!("failed to load conversation for session '{session_id}'"))
|
||||
}
|
||||
|
||||
/// Persist a conversation to disk.
|
||||
///
|
||||
/// Flow: resolve session dir from conv.session_id → delegate to repo.save() → wrap error.
|
||||
fn save_conversation(&self, conv: &Conversation) -> Result<()> {
|
||||
tracing::debug!("saving conversation for session {}", conv.session_id);
|
||||
let dir = self.session_dir(&conv.session_id);
|
||||
self.repo.save(&dir, conv).with_context(|| {
|
||||
format!(
|
||||
@@ -48,8 +81,16 @@ impl<R: ConversationRepository> ConversationService for ConversationServiceImpl<
|
||||
})
|
||||
}
|
||||
|
||||
/// Add a message to a conversation and persist immediately.
|
||||
///
|
||||
/// Flow: push message to in-memory conversation → resolve session dir → delegate save.
|
||||
///
|
||||
/// ## Note
|
||||
/// This is a write-through operation: the message is appended to the
|
||||
/// in-memory `Conversation` and then the full conversation is persisted.
|
||||
fn add_message(&self, conv: &mut Conversation, msg: ChatMessage) -> Result<()> {
|
||||
conv.push(msg);
|
||||
tracing::debug!("adding message to session {}", conv.session_id);
|
||||
conv.push(msg); // append message to in-memory conversation
|
||||
let dir = self.session_dir(&conv.session_id);
|
||||
self.repo.save(&dir, conv).with_context(|| {
|
||||
format!(
|
||||
|
||||
Reference in New Issue
Block a user