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
71			dev_log!("storage", "[MementoSaver] Created directory: {}", parent.display());
72		}
73	}
74
75	// Serialize memento data to JSON
76	let json_content = serde_json::to_string_pretty(MementoData).map_err(|e| {
77		dev_log!("storage", "error: [MementoSaver] Failed to serialize memento data: {}", e);
78		CommonError::SerializationError { Description:format!("Failed to serialize memento data: {}", e) }
79	})?;
80
81	// Write to temporary file first, then rename for atomic write
82	let temp_path = StorageFilePath.with_extension("json.tmp");
83
84	fs::write(&temp_path, json_content).map_err(|e| {
85		dev_log!(
86			"storage",
87			"error: [MementoSaver] Failed to write memento to temp file '{}': {}",
88			temp_path.display(),
89			e
90		);
91		CommonError::FileSystemIO { Path:temp_path.clone(), Description:format!("Failed to write memento: {}", e) }
92	})?;
93
94	// Atomic rename from temp to actual file
95	fs::rename(&temp_path, StorageFilePath).map_err(|e| {
96		dev_log!(
97			"storage",
98			"error: [MementoSaver] Failed to rename temp file to '{}': {}",
99			StorageFilePath.display(),
100			e
101		);
102		// Clean up temp file if rename fails
103		let _ = fs::remove_file(&temp_path);
104		CommonError::FileSystemIO {
105			Path:StorageFilePath.to_path_buf(),
106			Description:format!("Failed to rename memento file: {}", e),
107		}
108	})?;
109
110	dev_log!(
111		"storage",
112		"[MementoSaver] Successfully saved memento to: {}",
113		StorageFilePath.display()
114	);
115
116	Ok(())
117}