Skip to main content

Mountain/ApplicationState/State/FeatureState/Terminals/
TerminalState.rs

1//! # TerminalState Module (ApplicationState)
2//!
3//! ## RESPONSIBILITIES
4//! Manages terminal instances state including terminal metadata, content, and
5//! unique identifier tracking.
6//!
7//! ## ARCHITECTURAL ROLE
8//! TerminalState is part of the **FeatureState** module, representing
9//! terminal instances state organized by terminal ID.
10//!
11//! ## KEY COMPONENTS
12//! - TerminalState: Main struct containing active terminals map and counter
13//! - Default: Initialization implementation
14//! - Helper methods: Terminal manipulation utilities
15//!
16//! ## ERROR HANDLING
17//! - Thread-safe access via `Arc<Mutex<...>>`
18//! - Proper lock error handling with `MapLockError` helpers
19//!
20//! ## LOGGING
21//! State changes are logged at appropriate levels (debug, info, warn, error).
22//!
23//! ## PERFORMANCE CONSIDERATIONS
24//! - Lock mutexes briefly and release immediately
25//! - Avoid nested locks to prevent deadlocks
26//! - Use Arc for shared ownership across threads
27//! - Use double mutex for terminals (outer for map, inner for each terminal)
28//!
29//! ## TODO
30//! - [ ] Add terminal validation invariants
31//! - [ ] Implement terminal lifecycle events
32//! - [ ] Add terminal metrics collection
33
34use std::{
35	collections::HashMap,
36	sync::{
37		Arc,
38		Mutex as StandardMutex,
39		atomic::{AtomicU64, Ordering as AtomicOrdering},
40	},
41};
42
43use crate::{ApplicationState::DTO::TerminalStateDTO::TerminalStateDTO, dev_log};
44
45/// Active terminals state containing terminals by ID with next identifier
46/// counter.
47#[derive(Clone)]
48pub struct TerminalState {
49	/// Active terminals organized by ID.
50	pub ActiveTerminals:Arc<StandardMutex<HashMap<u64, Arc<StandardMutex<TerminalStateDTO>>>>>,
51
52	/// Counter for generating unique terminal identifiers.
53	pub NextTerminalIdentifier:Arc<AtomicU64>,
54}
55
56impl Default for TerminalState {
57	fn default() -> Self {
58		dev_log!("terminal", "[TerminalState] Initializing default terminal state...");
59
60		Self {
61			ActiveTerminals:Arc::new(StandardMutex::new(HashMap::new())),
62			NextTerminalIdentifier:Arc::new(AtomicU64::new(1)),
63		}
64	}
65}
66
67impl TerminalState {
68	/// Gets the next available unique identifier for a terminal instance.
69	pub fn GetNextTerminalIdentifier(&self) -> u64 { self.NextTerminalIdentifier.fetch_add(1, AtomicOrdering::Relaxed) }
70
71	/// Gets all active terminals.
72	pub fn GetAll(&self) -> HashMap<u64, TerminalStateDTO> {
73		self.ActiveTerminals
74			.lock()
75			.ok()
76			.map(|guard| {
77				guard
78					.iter()
79					.filter_map(|(id, arc)| arc.lock().ok().map(|dto| (*id, dto.clone())))
80					.collect()
81			})
82			.unwrap_or_default()
83	}
84
85	/// Gets a terminal by its ID.
86	pub fn Get(&self, id:u64) -> Option<TerminalStateDTO> {
87		self.ActiveTerminals
88			.lock()
89			.ok()
90			.and_then(|guard| guard.get(&id).and_then(|arc| arc.lock().ok().map(|dto| dto.clone())))
91	}
92
93	/// Gets a terminal's Arc<Mutex<>> by its ID for direct manipulation.
94	pub fn GetArc(&self, id:u64) -> Option<Arc<StandardMutex<TerminalStateDTO>>> {
95		self.ActiveTerminals.lock().ok().and_then(|guard| guard.get(&id).cloned())
96	}
97
98	/// Adds or updates a terminal.
99	pub fn AddOrUpdate(&self, id:u64, terminal:TerminalStateDTO) {
100		if let Ok(mut guard) = self.ActiveTerminals.lock() {
101			guard.insert(id, Arc::new(StandardMutex::new(terminal)));
102			dev_log!("terminal", "[TerminalState] Terminal added/updated with ID: {}", id);
103		}
104	}
105
106	/// Removes a terminal by its ID.
107	pub fn Remove(&self, id:u64) {
108		if let Ok(mut guard) = self.ActiveTerminals.lock() {
109			guard.remove(&id);
110			dev_log!("terminal", "[TerminalState] Terminal removed with ID: {}", id);
111		}
112	}
113
114	/// Clears all active terminals.
115	pub fn Clear(&self) {
116		if let Ok(mut guard) = self.ActiveTerminals.lock() {
117			guard.clear();
118			dev_log!("terminal", "[TerminalState] All terminals cleared");
119		}
120	}
121
122	/// Gets the count of active terminals.
123	pub fn Count(&self) -> usize { self.ActiveTerminals.lock().ok().map(|guard| guard.len()).unwrap_or(0) }
124
125	/// Checks if a terminal exists.
126	pub fn Contains(&self, id:u64) -> bool {
127		self.ActiveTerminals
128			.lock()
129			.ok()
130			.map(|guard| guard.contains_key(&id))
131			.unwrap_or(false)
132	}
133}