Skip to main content

Mountain/ApplicationState/State/ConfigurationState/
ConfigurationState.rs

1//! # ConfigurationState Module (ApplicationState)
2//!
3//! ## RESPONSIBILITIES
4//!
5//! Manages configuration and storage state including global configuration,
6//! workspace configuration, and memento storage buffers.
7//!
8//! ## ARCHITECTURAL ROLE
9//!
10//! ConfigurationState is part of the **state organization layer**, representing
11//! all configuration and storage-related state in the application. This
12//! includes:
13//! - Global configuration (merged from all sources)
14//! - Workspace configuration
15//! - Global memento storage (for crash recovery)
16//! - Workspace memento storage
17//!
18//! ## KEY COMPONENTS
19//! - State: Main struct containing configuration and storage fields
20//! - Default: Initialization implementation
21//! - Helper methods: Configuration and storage manipulation utilities
22//!
23//! ## ERROR HANDLING
24//!
25//! - Thread-safe access via `Arc<Mutex<...>>`
26//! - Proper lock error handling with `MapLockError` helpers
27//!
28//! ## LOGGING
29//!
30//! State changes are logged at appropriate levels (debug, info, warn, error).
31//!
32//! ## PERFORMANCE CONSIDERATIONS
33//!
34//! - Lock mutexes briefly and release immediately
35//! - Avoid nested locks to prevent deadlocks
36//! - Use Arc for shared ownership across threads
37//!
38//! ## TODO
39//! - [ ] Add configuration validation invariants
40//! - [ ] Implement configuration change events
41//! - [ ] Add configuration diffing
42
43use std::{
44	collections::HashMap,
45	sync::{Arc, Mutex as StandardMutex},
46};
47
48use crate::{ApplicationState::DTO::MergedConfigurationStateDTO::MergedConfigurationStateDTO, dev_log};
49
50/// Configuration and storage state.
51#[derive(Clone)]
52pub struct State {
53	/// Merged global configuration from all sources.
54	pub GlobalConfiguration:Arc<StandardMutex<serde_json::Value>>,
55
56	/// Merged workspace configuration from all sources.
57	pub WorkspaceConfiguration:Arc<StandardMutex<serde_json::Value>>,
58
59	/// Global memento storage for crash recovery.
60	pub MementoGlobalStorage:Arc<StandardMutex<HashMap<String, serde_json::Value>>>,
61
62	/// Workspace memento storage for crash recovery.
63	pub MementoWorkspaceStorage:Arc<StandardMutex<HashMap<String, serde_json::Value>>>,
64}
65
66impl Default for State {
67	fn default() -> Self {
68		dev_log!("config", "[ConfigurationState] Initializing default configuration state...");
69
70		Self {
71			GlobalConfiguration:Arc::new(StandardMutex::new(serde_json::Value::Object(serde_json::Map::new()))),
72
73			WorkspaceConfiguration:Arc::new(StandardMutex::new(serde_json::Value::Object(serde_json::Map::new()))),
74
75			MementoGlobalStorage:Arc::new(StandardMutex::new(HashMap::new())),
76
77			MementoWorkspaceStorage:Arc::new(StandardMutex::new(HashMap::new())),
78		}
79	}
80}
81
82impl State {
83	/// Gets the global configuration.
84	pub fn GetGlobalConfiguration(&self) -> serde_json::Value {
85		self.GlobalConfiguration
86			.lock()
87			.map(|g| g.clone())
88			.unwrap_or(serde_json::Value::Object(serde_json::Map::new()))
89	}
90
91	/// Sets the global configuration.
92	pub fn SetGlobalConfiguration(&self, config:serde_json::Value) {
93		if let Ok(mut guard) = self.GlobalConfiguration.lock() {
94			*guard = config;
95			dev_log!("config", "[ConfigurationState] Global configuration updated");
96		}
97	}
98
99	/// Gets the workspace configuration.
100	pub fn GetWorkspaceConfiguration(&self) -> serde_json::Value {
101		self.WorkspaceConfiguration
102			.lock()
103			.map(|g| g.clone())
104			.unwrap_or(serde_json::Value::Object(serde_json::Map::new()))
105	}
106
107	/// Sets the workspace configuration.
108	pub fn SetWorkspaceConfiguration(&self, config:serde_json::Value) {
109		if let Ok(mut guard) = self.WorkspaceConfiguration.lock() {
110			*guard = config;
111			dev_log!("config", "[ConfigurationState] Workspace configuration updated");
112		}
113	}
114
115	/// Gets a value from global configuration at a specific path.
116	pub fn GetGlobalValue(&self, path:&str) -> Option<serde_json::Value> {
117		self.GetGlobalConfiguration().get(path).cloned()
118	}
119
120	/// Sets a value in global configuration at a specific path.
121	/// This implementation uses the MergedConfigurationStateDTO's SetValue
122	/// method which properly handles nested object creation and value
123	/// assignment.
124	pub fn SetGlobalValue(&self, path:&str, value:serde_json::Value) {
125		if let Ok(mut config_guard) = self.GlobalConfiguration.lock() {
126			// Clone the current config for manipulation
127			let current_config = (*config_guard).clone();
128
129			// Create DTO to leverage its SetValue method
130			let mut dto = MergedConfigurationStateDTO { Data:current_config };
131
132			// Use the DTO's SetValue method which handles nested paths properly
133			if let Err(e) = dto.SetValue(path, value) {
134				dev_log!(
135					"config",
136					"warn: [ConfigurationState] Failed to set value at path '{}': {}",
137					path,
138					e
139				);
140
141				return;
142			}
143
144			// Write the updated data back
145			*config_guard = dto.Data;
146
147			dev_log!("config", "[ConfigurationState] Global configuration value updated at: {}", path);
148		}
149	}
150
151	/// Gets all global memento storage.
152	pub fn GetGlobalMemento(&self) -> HashMap<String, serde_json::Value> {
153		self.MementoGlobalStorage
154			.lock()
155			.ok()
156			.map(|guard| guard.clone())
157			.unwrap_or_default()
158	}
159
160	/// Sets all global memento storage.
161	pub fn SetGlobalMemento(&self, storage:HashMap<String, serde_json::Value>) {
162		if let Ok(mut guard) = self.MementoGlobalStorage.lock() {
163			*guard = storage;
164			dev_log!(
165				"config",
166				"[ConfigurationState] Global memento storage updated ({} keys)",
167				guard.len()
168			);
169		}
170	}
171
172	/// Gets a value from global memento storage.
173	pub fn GetGlobalMementoValue(&self, key:&str) -> Option<serde_json::Value> {
174		self.MementoGlobalStorage.lock().ok().and_then(|guard| guard.get(key).cloned())
175	}
176
177	/// Sets a value in global memento storage.
178	pub fn SetGlobalMementoValue(&self, key:String, value:serde_json::Value) {
179		if let Ok(mut guard) = self.MementoGlobalStorage.lock() {
180			guard.insert(key.clone(), value);
181
182			dev_log!("config", "[ConfigurationState] Global memento value updated for key: {}", key);
183		}
184	}
185
186	/// Gets all workspace memento storage.
187	pub fn GetWorkspaceMemento(&self) -> HashMap<String, serde_json::Value> {
188		self.MementoWorkspaceStorage
189			.lock()
190			.ok()
191			.map(|guard| guard.clone())
192			.unwrap_or_default()
193	}
194
195	/// Sets all workspace memento storage.
196	pub fn SetWorkspaceMemento(&self, storage:HashMap<String, serde_json::Value>) {
197		if let Ok(mut guard) = self.MementoWorkspaceStorage.lock() {
198			*guard = storage;
199			dev_log!(
200				"config",
201				"[ConfigurationState] Workspace memento storage updated ({} keys)",
202				guard.len()
203			);
204		}
205	}
206
207	/// Gets a value from workspace memento storage.
208	pub fn GetWorkspaceMementoValue(&self, key:&str) -> Option<serde_json::Value> {
209		self.MementoWorkspaceStorage
210			.lock()
211			.ok()
212			.and_then(|guard| guard.get(key).cloned())
213	}
214
215	/// Sets a value in workspace memento storage.
216	pub fn SetWorkspaceMementoValue(&self, key:String, value:serde_json::Value) {
217		if let Ok(mut guard) = self.MementoWorkspaceStorage.lock() {
218			guard.insert(key.clone(), value);
219
220			dev_log!(
221				"config",
222				"[ConfigurationState] Workspace memento value updated for key: {}",
223				key
224			);
225		}
226	}
227
228	/// Clears a value from workspace memento storage.
229	pub fn ClearWorkspaceMementoValue(&self, key:&str) {
230		if let Ok(mut guard) = self.MementoWorkspaceStorage.lock() {
231			guard.remove(key);
232
233			dev_log!(
234				"config",
235				"[ConfigurationState] Workspace memento value removed for key: {}",
236				key
237			);
238		}
239	}
240
241	/// Clears global memento storage.
242	pub fn ClearGlobalMemento(&self) {
243		if let Ok(mut guard) = self.MementoGlobalStorage.lock() {
244			guard.clear();
245
246			dev_log!("config", "[ConfigurationState] Global memento storage cleared");
247		}
248	}
249
250	/// Clears workspace memento storage.
251	pub fn ClearWorkspaceMemento(&self) {
252		if let Ok(mut guard) = self.MementoWorkspaceStorage.lock() {
253			guard.clear();
254
255			dev_log!("config", "[ConfigurationState] Workspace memento storage cleared");
256		}
257	}
258}