Mountain/ApplicationState/Internal/Persistence/
MementoSaver.rs

1//! # MementoSaver Module (Internal)
2//!
3//! ## RESPONSIBILITIES
4//! Saves memento state to disk for crash recovery and state persistence.
5//! Asynchronously saves memento to JSON file with proper error handling.
6//!
7//! ## ARCHITECTURAL ROLE
8//! MementoSaver is part of the **Internal::Persistence** module, handling
9//! memento saving operations.
10//!
11//! ## KEY COMPONENTS
12//! - SaveMementoToDisk: Main function for saving memento
13//!
14//! ## ERROR HANDLING
15//! - Returns Result with CommonError on failure
16//! - Creates directory structure if needed
17//! - Proper error logging
18//!
19//! ## LOGGING
20//! All operations are logged at appropriate levels (debug, info, warn, error).
21//!
22//! ## PERFORMANCE CONSIDERATIONS
23//! - Asynchronous file I/O
24//! - Proper error handling and recovery
25//!
26//! ## TODO
27//! - [ ] Add checksum calculation
28//! - [ ] Implement atomic writes
29//! - [ ] Add compression support
30
31use std::{collections::HashMap, fs, path::Path};
32
33use serde_json::Value;
34use log::{debug, error};
35use CommonLibrary::Error::CommonError::CommonError;
36
37/// Asynchronously saves Memento storage data to a JSON file.
38///
39/// # Arguments
40/// * `StorageFilePath` - Path to the memento storage file
41/// * `MementoData` - The memento data to save
42///
43/// # Returns
44/// Result indicating success or CommonError on failure
45///
46/// # Errors
47/// Returns CommonError for file I/O or serialization errors
48///
49/// # Behavior
50/// - Creates parent directory if it doesn't exist
51/// - Serializes data to JSON
52/// - Writes to file atomically (creates temp file then renames)
53pub async fn SaveMementoToDisk(StorageFilePath:&Path, MementoData:&HashMap<String, Value>) -> Result<(), CommonError> {
54	// Ensure parent directory exists
55	if let Some(parent) = StorageFilePath.parent() {
56		if !parent.exists() {
57			fs::create_dir_all(parent).map_err(|e| {
58				error!("[MementoSaver] Failed to create directory '{}': {}", parent.display(), e);
59				CommonError::FileSystemIO {
60					Path:parent.to_path_buf(),
61					Description:format!("Failed to create directory: {}", e),
62				}
63			})?;
64			debug!("[MementoSaver] Created directory: {}", parent.display());
65		}
66	}
67
68	// Serialize memento data to JSON
69	let json_content = serde_json::to_string_pretty(MementoData).map_err(|e| {
70		error!("[MementoSaver] Failed to serialize memento data: {}", e);
71		CommonError::SerializationError { Description:format!("Failed to serialize memento data: {}", e) }
72	})?;
73
74	// Write to temporary file first, then rename for atomic write
75	let temp_path = StorageFilePath.with_extension("json.tmp");
76	fs::write(&temp_path, json_content).map_err(|e| {
77		error!(
78			"[MementoSaver] Failed to write memento to temp file '{}': {}",
79			temp_path.display(),
80			e
81		);
82		CommonError::FileSystemIO { Path:temp_path.clone(), Description:format!("Failed to write memento: {}", e) }
83	})?;
84
85	// Atomic rename from temp to actual file
86	fs::rename(&temp_path, StorageFilePath).map_err(|e| {
87		error!(
88			"[MementoSaver] Failed to rename temp file to '{}': {}",
89			StorageFilePath.display(),
90			e
91		);
92		// Clean up temp file if rename fails
93		let _ = fs::remove_file(&temp_path);
94		CommonError::FileSystemIO {
95			Path:StorageFilePath.to_path_buf(),
96			Description:format!("Failed to rename memento file: {}", e),
97		}
98	})?;
99
100	debug!("[MementoSaver] Successfully saved memento to: {}", StorageFilePath.display());
101
102	Ok(())
103}