Mountain/ApplicationState/Internal/ExtensionScanner/ScanAndPopulateExtensions.rs
1//! # ScanAndPopulateExtensions Module (Internal)
2//!
3//! ## RESPONSIBILITIES
4//! Scans all registered extension paths for valid extensions and populates the
5//! state with discovered extensions.
6//!
7//! ## ARCHITECTURAL ROLE
8//! ScanAndPopulateExtensions is part of the **Internal::ExtensionScanner**
9//! module, handling extension discovery and population.
10//!
11//! ## KEY COMPONENTS
12//! - ScanAndPopulateExtensions: Main function for scanning extensions
13//! - ScanExtensionsWithRecovery: Robust scanning with recovery
14//!
15//! ## ERROR HANDLING
16//! - Returns Result with CommonError on failure
17//! - Handles partial failures gracefully
18//! - Comprehensive error logging
19//!
20//! ## LOGGING
21//! Operations are logged at appropriate levels (info, debug, warn, error).
22//!
23//! ## PERFORMANCE CONSIDERATIONS
24//! - Async operations for scanning
25//! - Handles multiple scan paths
26//! - Partial failure handling
27//!
28//! ## TODO
29//! - [ ] Add concurrent scanning
30//! - [ ] Implement extension caching
31//! - [ ] Add extension validation rules
32
33use std::{collections::HashMap, path::PathBuf};
34
35use CommonLibrary::Error::CommonError::CommonError;
36use log::{debug, error, info, trace, warn};
37use serde_json::Value;
38use tauri::AppHandle;
39
40use crate::{ApplicationState::DTO::ExtensionDescriptionStateDTO::ExtensionDescriptionStateDTO, ExtensionManagement};
41
42/// Scans all registered extension paths for valid extensions and populates the
43/// state.
44///
45/// # Arguments
46/// * `ApplicationHandle` - Tauri application handle for extension management
47/// * `State` - Reference to the application state
48///
49/// # Returns
50/// Result indicating success or CommonError on failure
51///
52/// # Behavior
53/// - Scans all registered extension paths
54/// - Populates state with discovered extensions
55/// - Returns comprehensive scan statistics
56/// - Handles partial failures gracefully
57pub async fn ScanAndPopulateExtensions(
58 ApplicationHandle:AppHandle,
59 _State:&crate::ApplicationState::ExtensionState::State::State,
60) -> Result<(), CommonError> {
61 info!("[ExtensionScanner] Starting extension scan...");
62
63 let mut all_found_extensions:HashMap<String, ExtensionDescriptionStateDTO> = HashMap::new();
64
65 // Note: This would need to be adapted to the new state structure
66 // For now, this is a placeholder showing the structure
67 let scan_paths:Vec<PathBuf> = Vec::new(); // Would get from State.Registry.Extension.Registry.ExtensionScanPaths
68
69 trace!("[ExtensionScanner] Scanning paths: {:?}", scan_paths);
70
71 let mut successful_scans = 0;
72 let mut failed_scans = 0;
73
74 for path in scan_paths {
75 let path_clone = path.clone();
76 match ExtensionManagement::Scanner::ScanDirectoryForExtensions(ApplicationHandle.clone(), path_clone).await {
77 Ok(found_in_path) => {
78 successful_scans += 1;
79 for extension in found_in_path {
80 let identifier = extension
81 .Identifier
82 .get("value")
83 .and_then(Value::as_str)
84 .unwrap_or_default()
85 .to_string();
86
87 if !identifier.is_empty() {
88 all_found_extensions.insert(identifier, extension);
89 }
90 }
91 },
92 Err(error) => {
93 failed_scans += 1;
94 warn!(
95 "[ExtensionScanner] Failed to scan extension path '{}': {}",
96 path.display(),
97 error
98 );
99 },
100 }
101 }
102
103 // Note: Would populate
104 // State.Extension.ScannedExtensions.Extension.ScannedExtensions
105 debug!(
106 "[ExtensionScanner] Extension scan complete. Found {} extensions ({} successful scans, {} failed scans).",
107 all_found_extensions.len(),
108 successful_scans,
109 failed_scans
110 );
111
112 if failed_scans > 0 {
113 warn!("[ExtensionScanner] {} extension paths failed to scan", failed_scans);
114 }
115
116 Ok(())
117}
118
119/// Robust extension scanning with comprehensive error handling.
120///
121/// # Arguments
122/// * `ApplicationHandle` - Tauri application handle for extension management
123/// * `State` - Reference to the application state
124///
125/// # Returns
126/// Result indicating success or CommonError on failure
127///
128/// # Behavior
129/// - Clears potentially corrupted extension state first
130/// - Performs the scan
131/// - Retries once on failure
132/// - Comprehensive error logging
133pub async fn ScanExtensionsWithRecovery(
134 ApplicationHandle:AppHandle,
135 State:&crate::ApplicationState::ExtensionState::State::State,
136) -> Result<(), CommonError> {
137 info!("[ExtensionScanner] Starting robust extension scan with recovery...");
138
139 // Clear potentially corrupted extension state first
140 // Note: Would clear
141 // State.Extension.ScannedExtensions.Extension.ScannedExtensions
142
143 // Perform the scan
144 match ScanAndPopulateExtensions(ApplicationHandle.clone(), State).await {
145 Ok(()) => {
146 info!("[ExtensionScanner] Robust extension scan completed successfully");
147 Ok(())
148 },
149 Err(error) => {
150 error!("[ExtensionScanner] Robust extension scan failed: {}", error);
151 // Attempt recovery by clearing state and retrying once
152 warn!("[ExtensionScanner] Attempting recovery from extension scan failure...");
153
154 // Clear state again
155 // Note: Would clear
156 // State.Extension.ScannedExtensions.Extension.ScannedExtensions
157
158 // Retry the scan with a cloned handle
159 ScanAndPopulateExtensions(ApplicationHandle.clone(), State).await
160 },
161 }
162}