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
58 lines
2.2 KiB
Rust
58 lines
2.2 KiB
Rust
//! JSON file–backed `ConversationRepository` implementation.
|
||
//!
|
||
//! Stores `Conversation` as pretty-printed JSON at `<session_dir>/conversation.json`.
|
||
//! Uses atomic write (temp file + rename + fsync) for crash safety.
|
||
//!
|
||
//! ## Data Flow
|
||
//! - `load()`: read file → deserialize JSON → return Conversation
|
||
//! - `save()`: serialize Conversation → atomic write to conversation.json
|
||
|
||
use std::path::Path;
|
||
|
||
use anyhow::{Context, Result};
|
||
use zesdex_utils::write_json_atomic;
|
||
|
||
use crate::domain::conversation::Conversation;
|
||
use crate::domain::repository::ConversationRepository;
|
||
|
||
/// File-based `ConversationRepository` that reads/writes `conversation.json`.
|
||
///
|
||
/// Zero-allocation: the struct is a unit type marker.
|
||
#[derive(Debug, Clone, Default)]
|
||
pub struct JsonConversationRepository;
|
||
|
||
impl JsonConversationRepository {
|
||
/// Create a new repository instance.
|
||
pub fn new() -> Self {
|
||
Self
|
||
}
|
||
}
|
||
|
||
impl ConversationRepository for JsonConversationRepository {
|
||
/// Load a `Conversation` from `<session_dir>/conversation.json`.
|
||
///
|
||
/// Flow: read file → parse JSON → return Conversation.
|
||
fn load(&self, session_dir: &Path) -> Result<Conversation> {
|
||
let path = session_dir.join("conversation.json");
|
||
let data = std::fs::read_to_string(&path)
|
||
.with_context(|| format!("failed to read conversation at '{}'", path.display()))?;
|
||
let conv: Conversation = serde_json::from_str(&data)
|
||
.with_context(|| format!("failed to parse conversation at '{}'", path.display()))?;
|
||
Ok(conv)
|
||
}
|
||
|
||
/// Persist a `Conversation` to `<session_dir>/conversation.json`.
|
||
///
|
||
/// Flow: create session dir → atomic JSON write → log success.
|
||
fn save(&self, session_dir: &Path, conversation: &Conversation) -> Result<()> {
|
||
tracing::debug!("saving conversation to {session_dir:?}");
|
||
std::fs::create_dir_all(session_dir)
|
||
.with_context(|| format!("failed to create session dir '{}'", session_dir.display()))?;
|
||
let path = session_dir.join("conversation.json");
|
||
write_json_atomic(&path, conversation, None)
|
||
.with_context(|| "failed to save conversation")?;
|
||
tracing::debug!("conversation saved to '{}'", path.display());
|
||
Ok(())
|
||
}
|
||
}
|