Skip to main content

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 CommonLibrary::Error::CommonError::CommonError;
35
36use crate::dev_log;
37
38/// Asynchronously saves Memento storage data to a JSON file.
39///
40/// # Arguments
41/// * `StorageFilePath` - Path to the memento storage file
42/// * `MementoData` - The memento data to save
43///
44/// # Returns
45/// Result indicating success or CommonError on failure
46///
47/// # Errors
48/// Returns CommonError for file I/O or serialization errors
49///
50/// # Behavior
51/// - Creates parent directory if it doesn't exist
52/// - Serializes data to JSON
53/// - Writes to file atomically (creates temp file then renames)
54pub async fn SaveMementoToDisk(StorageFilePath:&Path, MementoData:&HashMap<String, Value>) -> Result<(), CommonError> {
55	// Ensure parent directory exists
56	if let Some(parent) = StorageFilePath.parent() {
57		if !parent.exists() {
58			fs::create_dir_all(parent).map_err(|e| {
59				dev_log!(
60					"storage",
61					"error: [MementoSaver] Failed to create directory '{}': {}",
62					parent.display(),
63					e
64				);
65				CommonError::FileSystemIO {
66					Path:parent.to_path_buf(),
67					Description:format!("Failed to create directory: {}", e),
68				}
69			})?;
70			dev_log!("storage", "[MementoSaver] Created directory: {}", parent.display());
71		}
72	}
73
74	// Serialize memento data to JSON
75	let json_content = serde_json::to_string_pretty(MementoData).map_err(|e| {
76		dev_log!("storage", "error: [MementoSaver] Failed to serialize memento data: {}", e);
77		CommonError::SerializationError { Description:format!("Failed to serialize memento data: {}", e) }
78	})?;
79
80	// Write to temporary file first, then rename for atomic write
81	let temp_path = StorageFilePath.with_extension("json.tmp");
82	fs::write(&temp_path, json_content).map_err(|e| {
83		dev_log!(
84			"storage",
85			"error: [MementoSaver] Failed to write memento to temp file '{}': {}",
86			temp_path.display(),
87			e
88		);
89		CommonError::FileSystemIO { Path:temp_path.clone(), Description:format!("Failed to write memento: {}", e) }
90	})?;
91
92	// Atomic rename from temp to actual file
93	fs::rename(&temp_path, StorageFilePath).map_err(|e| {
94		dev_log!(
95			"storage",
96			"error: [MementoSaver] Failed to rename temp file to '{}': {}",
97			StorageFilePath.display(),
98			e
99		);
100		// Clean up temp file if rename fails
101		let _ = fs::remove_file(&temp_path);
102		CommonError::FileSystemIO {
103			Path:StorageFilePath.to_path_buf(),
104			Description:format!("Failed to rename memento file: {}", e),
105		}
106	})?;
107
108	dev_log!(
109		"storage",
110		"[MementoSaver] Successfully saved memento to: {}",
111		StorageFilePath.display()
112	);
113
114	Ok(())
115}