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			WorkspaceConfiguration:Arc::new(StandardMutex::new(serde_json::Value::Object(serde_json::Map::new()))),
73			MementoGlobalStorage:Arc::new(StandardMutex::new(HashMap::new())),
74			MementoWorkspaceStorage:Arc::new(StandardMutex::new(HashMap::new())),
75		}
76	}
77}
78
79impl State {
80	/// Gets the global configuration.
81	pub fn GetGlobalConfiguration(&self) -> serde_json::Value {
82		self.GlobalConfiguration
83			.lock()
84			.map(|g| g.clone())
85			.unwrap_or(serde_json::Value::Object(serde_json::Map::new()))
86	}
87
88	/// Sets the global configuration.
89	pub fn SetGlobalConfiguration(&self, config:serde_json::Value) {
90		if let Ok(mut guard) = self.GlobalConfiguration.lock() {
91			*guard = config;
92			dev_log!("config", "[ConfigurationState] Global configuration updated");
93		}
94	}
95
96	/// Gets the workspace configuration.
97	pub fn GetWorkspaceConfiguration(&self) -> serde_json::Value {
98		self.WorkspaceConfiguration
99			.lock()
100			.map(|g| g.clone())
101			.unwrap_or(serde_json::Value::Object(serde_json::Map::new()))
102	}
103
104	/// Sets the workspace configuration.
105	pub fn SetWorkspaceConfiguration(&self, config:serde_json::Value) {
106		if let Ok(mut guard) = self.WorkspaceConfiguration.lock() {
107			*guard = config;
108			dev_log!("config", "[ConfigurationState] Workspace configuration updated");
109		}
110	}
111
112	/// Gets a value from global configuration at a specific path.
113	pub fn GetGlobalValue(&self, path:&str) -> Option<serde_json::Value> {
114		self.GetGlobalConfiguration().get(path).cloned()
115	}
116
117	/// Sets a value in global configuration at a specific path.
118	/// This implementation uses the MergedConfigurationStateDTO's SetValue
119	/// method which properly handles nested object creation and value
120	/// assignment.
121	pub fn SetGlobalValue(&self, path:&str, value:serde_json::Value) {
122		if let Ok(mut config_guard) = self.GlobalConfiguration.lock() {
123			// Clone the current config for manipulation
124			let current_config = (*config_guard).clone();
125
126			// Create DTO to leverage its SetValue method
127			let mut dto = MergedConfigurationStateDTO { Data:current_config };
128
129			// Use the DTO's SetValue method which handles nested paths properly
130			if let Err(e) = dto.SetValue(path, value) {
131				dev_log!(
132					"config",
133					"warn: [ConfigurationState] Failed to set value at path '{}': {}",
134					path,
135					e
136				);
137				return;
138			}
139
140			// Write the updated data back
141			*config_guard = dto.Data;
142
143			dev_log!("config", "[ConfigurationState] Global configuration value updated at: {}", path);
144		}
145	}
146
147	/// Gets all global memento storage.
148	pub fn GetGlobalMemento(&self) -> HashMap<String, serde_json::Value> {
149		self.MementoGlobalStorage
150			.lock()
151			.ok()
152			.map(|guard| guard.clone())
153			.unwrap_or_default()
154	}
155
156	/// Sets all global memento storage.
157	pub fn SetGlobalMemento(&self, storage:HashMap<String, serde_json::Value>) {
158		if let Ok(mut guard) = self.MementoGlobalStorage.lock() {
159			*guard = storage;
160			dev_log!(
161				"config",
162				"[ConfigurationState] Global memento storage updated ({} keys)",
163				guard.len()
164			);
165		}
166	}
167
168	/// Gets a value from global memento storage.
169	pub fn GetGlobalMementoValue(&self, key:&str) -> Option<serde_json::Value> {
170		self.MementoGlobalStorage.lock().ok().and_then(|guard| guard.get(key).cloned())
171	}
172
173	/// Sets a value in global memento storage.
174	pub fn SetGlobalMementoValue(&self, key:String, value:serde_json::Value) {
175		if let Ok(mut guard) = self.MementoGlobalStorage.lock() {
176			guard.insert(key.clone(), value);
177			dev_log!("config", "[ConfigurationState] Global memento value updated for key: {}", key);
178		}
179	}
180
181	/// Gets all workspace memento storage.
182	pub fn GetWorkspaceMemento(&self) -> HashMap<String, serde_json::Value> {
183		self.MementoWorkspaceStorage
184			.lock()
185			.ok()
186			.map(|guard| guard.clone())
187			.unwrap_or_default()
188	}
189
190	/// Sets all workspace memento storage.
191	pub fn SetWorkspaceMemento(&self, storage:HashMap<String, serde_json::Value>) {
192		if let Ok(mut guard) = self.MementoWorkspaceStorage.lock() {
193			*guard = storage;
194			dev_log!(
195				"config",
196				"[ConfigurationState] Workspace memento storage updated ({} keys)",
197				guard.len()
198			);
199		}
200	}
201
202	/// Gets a value from workspace memento storage.
203	pub fn GetWorkspaceMementoValue(&self, key:&str) -> Option<serde_json::Value> {
204		self.MementoWorkspaceStorage
205			.lock()
206			.ok()
207			.and_then(|guard| guard.get(key).cloned())
208	}
209
210	/// Sets a value in workspace memento storage.
211	pub fn SetWorkspaceMementoValue(&self, key:String, value:serde_json::Value) {
212		if let Ok(mut guard) = self.MementoWorkspaceStorage.lock() {
213			guard.insert(key.clone(), value);
214			dev_log!(
215				"config",
216				"[ConfigurationState] Workspace memento value updated for key: {}",
217				key
218			);
219		}
220	}
221
222	/// Clears a value from workspace memento storage.
223	pub fn ClearWorkspaceMementoValue(&self, key:&str) {
224		if let Ok(mut guard) = self.MementoWorkspaceStorage.lock() {
225			guard.remove(key);
226			dev_log!(
227				"config",
228				"[ConfigurationState] Workspace memento value removed for key: {}",
229				key
230			);
231		}
232	}
233
234	/// Clears global memento storage.
235	pub fn ClearGlobalMemento(&self) {
236		if let Ok(mut guard) = self.MementoGlobalStorage.lock() {
237			guard.clear();
238			dev_log!("config", "[ConfigurationState] Global memento storage cleared");
239		}
240	}
241
242	/// Clears workspace memento storage.
243	pub fn ClearWorkspaceMemento(&self) {
244		if let Ok(mut guard) = self.MementoWorkspaceStorage.lock() {
245			guard.clear();
246			dev_log!("config", "[ConfigurationState] Workspace memento storage cleared");
247		}
248	}
249}