Mountain/Binary/Main/AppLifecycle.rs
1//! # AppLifecycle (Binary/Main)
2//!
3//! ## RESPONSIBILITIES
4//!
5//! Application lifecycle management for the Tauri application setup and
6//! initialization. This module handles the complete setup process during the
7//! Tauri setup hook, including tray initialization, command registration, IPC
8//! server setup, window creation, environment configuration, and async service
9//! initialization.
10//!
11//! ## ARCHITECTURAL ROLE
12//!
13//! The AppLifecycle module is the **initialization layer** in Mountain's
14//! architecture:
15//!
16//! ```text
17//! Tauri Builder Setup ──► AppLifecycle::AppLifecycleSetup()
18//! │
19//! ├─► Tray Initialization
20//! ├─► Command Registration
21//! ├─► IPC Server Setup
22//! ├─► Window Building
23//! ├─► Environment Setup
24//! ├─► Runtime Setup
25//! └─► Async Service Initialization
26//! ```
27//!
28//! ## KEY COMPONENTS
29//!
30//! - **AppLifecycleSetup()**: Main setup function orchestrating all
31//! initialization
32//! - **Tray Initialization**: System tray icon with Dark/Light mode support
33//! - **Command Registration**: Native command registration with application
34//! state
35//! - **IPC Server**: Mountain IPC server for frontend-backend communication
36//! - **Window Building**: Main application window configuration
37//! - **MountainEnvironment**: Environment context for application services
38//! - **ApplicationRunTime**: Runtime context with scheduler and environment
39//! - **Status Reporter**: IPC status reporting initialization
40//! - **Advanced Features**: Advanced IPC features initialization
41//! - **Wind Sync**: Wind advanced sync initialization
42//! - **Async Initialization**: Post-setup async service initialization
43//!
44//! ## ERROR HANDLING
45//!
46//! Returns `Result<(), Box<dyn std::error::Error>>` for setup errors.
47//! Non-critical failures are logged but don't prevent application startup.
48//! Critical failures are propagated to prevent incomplete startup.
49//!
50//! ## LOGGING
51//!
52//! Comprehensive logging at INFO level for major setup steps,
53//! DEBUG level for detailed processing, and ERROR for failures.
54//! All logs are prefixed with `[Lifecycle] [ComponentName]`.
55//!
56//! ## PERFORMANCE CONSIDERATIONS
57//!
58//! - Async initialization spawned after main setup to avoid blocking
59//! - Services initialized only when needed
60//! - Clone operations minimized for Arc-wrapped shared state
61//!
62//! ## TODO
63//! - [ ] Add setup progress tracking
64//! - [ ] Implement setup timeout handling
65//! - [ ] Add setup rollback mechanism on failure
66
67use std::sync::Arc;
68
69use log::{debug, error, info, trace};
70use tauri::Manager;
71use Echo::Scheduler::Scheduler::Scheduler;
72
73use crate::{
74 // Crate root imports
75 ApplicationState::ApplicationState,
76 // Binary submodule imports
77 Binary::Build::WindowBuild::WindowBuild as WindowBuildFn,
78 Binary::Extension::ExtensionPopulate::ExtensionPopulate as ExtensionPopulateFn,
79 Binary::Extension::ScanPathConfigure::ScanPathConfigure as ScanPathConfigureFn,
80 Binary::Register::AdvancedFeaturesRegister::AdvancedFeaturesRegister as AdvancedFeaturesRegisterFn,
81 Binary::Register::CommandRegister::CommandRegister as CommandRegisterFn,
82 Binary::Register::IPCServerRegister::IPCServerRegister as IPCServerRegisterFn,
83 Binary::Register::StatusReporterRegister::StatusReporterRegister as StatusReporterRegisterFn,
84 Binary::Register::WindSyncRegister::WindSyncRegister as WindSyncRegisterFn,
85 Binary::Service::CocoonStart::CocoonStart as CocoonStartFn,
86 Binary::Service::ConfigurationInitialize::ConfigurationInitialize as ConfigurationInitializeFn,
87 Binary::Service::VineStart::VineStart as VineStartFn,
88 Binary::Tray::EnableTray as EnableTrayFn,
89 Environment::MountainEnvironment::MountainEnvironment,
90 RunTime::ApplicationRunTime::ApplicationRunTime,
91};
92
93/// Logs a checkpoint message at TRACE level.
94macro_rules! TraceStep {
95 ($($arg:tt)*) => {{
96 trace!($($arg)*);
97 }};
98}
99
100/// Sets up the application lifecycle during Tauri initialization.
101///
102/// This function coordinates all setup operations:
103/// 1. System tray initialization
104/// 2. Native command registration
105/// 3. IPC server initialization
106/// 4. Main window creation
107/// 5. Mountain environment setup
108/// 6. Application runtime setup
109/// 7. Status reporter initialization
110/// 8. Advanced features initialization
111/// 9. Wind advanced sync initialization
112/// 10. Async post-setup initialization
113///
114/// # Parameters
115///
116/// * `app` - Mutable reference to Tauri App instance
117/// * `app_handle` - Cloned Tauri AppHandle for async operations
118/// * `localhost_url` - URL for the development server
119/// * `scheduler` - Arc-wrapped Echo Scheduler
120/// * `app_state` - Application state clone
121///
122/// # Returns
123///
124/// `Result<(), Box<dyn std::error::Error>>` - Ok on success, Err on critical
125/// failure
126pub fn AppLifecycleSetup(
127 app:&mut tauri::App,
128 app_handle:tauri::AppHandle,
129 localhost_url:String,
130 scheduler:Arc<Scheduler>,
131 app_state:Arc<ApplicationState>,
132) -> Result<(), Box<dyn std::error::Error>> {
133 info!("[Lifecycle] [Setup] Setup hook started.");
134 debug!("[Lifecycle] [Setup] LocalhostUrl={}", localhost_url);
135
136 let app_handle_for_setup = app_handle.clone();
137 TraceStep!("[Lifecycle] [Setup] AppHandle acquired.");
138
139 // -------------------------------------------------------------------------
140 // [UI] [Tray] Initialize System Tray
141 // -------------------------------------------------------------------------
142 debug!("[UI] [Tray] Initializing system tray...");
143 if let Err(Error) = EnableTrayFn::enable_tray(app) {
144 error!("[UI] [Tray] Failed to enable tray: {}", Error);
145 }
146
147 // -------------------------------------------------------------------------
148 // [Lifecycle] [Commands] Register native commands
149 // -------------------------------------------------------------------------
150 debug!("[Lifecycle] [Commands] Registering native commands...");
151 if let Err(e) = CommandRegisterFn(&app_handle_for_setup, &app_state) {
152 error!("[Lifecycle] [Commands] Failed to register commands: {}", e);
153 }
154 debug!("[Lifecycle] [Commands] Native commands registered.");
155
156 // -------------------------------------------------------------------------
157 // [Lifecycle] [IPC] Initialize IPC Server
158 // -------------------------------------------------------------------------
159 debug!("[Lifecycle] [IPC] Initializing Mountain IPC Server...");
160 if let Err(e) = IPCServerRegisterFn(&app_handle_for_setup) {
161 error!("[Lifecycle] [IPC] Failed to register IPC server: {}", e);
162 }
163
164 // -------------------------------------------------------------------------
165 // [UI] [Window] Build main window
166 // -------------------------------------------------------------------------
167 debug!("[UI] [Window] Building main window...");
168 let MainWindow = WindowBuildFn(app, localhost_url.clone());
169 info!("[UI] [Window] Main window ready.");
170
171 #[cfg(debug_assertions)]
172 {
173 debug!("[UI] [Window] Debug build: opening DevTools.");
174 MainWindow.open_devtools();
175 }
176
177 // -------------------------------------------------------------------------
178 // [Backend] [Env] Mountain environment
179 // -------------------------------------------------------------------------
180 debug!("[Backend] [Env] Creating MountainEnvironment...");
181 let Environment = Arc::new(MountainEnvironment::Create(app_handle_for_setup.clone(), app_state.clone()));
182 info!("[Backend] [Env] MountainEnvironment ready.");
183
184 // -------------------------------------------------------------------------
185 // [Backend] [Runtime] ApplicationRunTime
186 // -------------------------------------------------------------------------
187 debug!("[Backend] [Runtime] Creating ApplicationRunTime...");
188 let Runtime = Arc::new(ApplicationRunTime::Create(scheduler.clone(), Environment.clone()));
189 app_handle_for_setup.manage(Runtime.clone());
190 info!("[Backend] [Runtime] ApplicationRunTime managed.");
191
192 // -------------------------------------------------------------------------
193 // [Lifecycle] [IPC] Initialize Status Reporter
194 // -------------------------------------------------------------------------
195 if let Err(e) = StatusReporterRegisterFn(&app_handle_for_setup, Runtime.clone()) {
196 error!("[Lifecycle] [IPC] Failed to initialize status reporter: {}", e);
197 }
198
199 // -------------------------------------------------------------------------
200 // [Lifecycle] [IPC] Initialize Advanced Features
201 // -------------------------------------------------------------------------
202 if let Err(e) = AdvancedFeaturesRegisterFn(&app_handle_for_setup, Runtime.clone()) {
203 error!("[Lifecycle] [IPC] Failed to initialize advanced features: {}", e);
204 }
205
206 // -------------------------------------------------------------------------
207 // [Lifecycle] [IPC] Initialize Wind Advanced Sync
208 // -------------------------------------------------------------------------
209 if let Err(e) = WindSyncRegisterFn(&app_handle_for_setup, Runtime.clone()) {
210 error!("[Lifecycle] [IPC] Failed to initialize wind advanced sync: {}", e);
211 }
212
213 // -------------------------------------------------------------------------
214 // [Lifecycle] [PostSetup] Async initialization work
215 // -------------------------------------------------------------------------
216 let PostSetupAppHandle = app_handle_for_setup.clone();
217 let PostSetupEnvironment = Environment.clone();
218
219 tauri::async_runtime::spawn(async move {
220 info!("[Lifecycle] [PostSetup] Starting...");
221 let AppStateForSetup = PostSetupEnvironment.ApplicationState.clone();
222 TraceStep!("[Lifecycle] [PostSetup] AppState cloned.");
223
224 // [Config]
225 let _ = ConfigurationInitializeFn(&PostSetupEnvironment).await;
226
227 // [Extensions] [ScanPaths]
228 let _ = ScanPathConfigureFn(&AppStateForSetup);
229
230 // [Extensions] [Scan]
231 let _ = ExtensionPopulateFn(PostSetupAppHandle.clone(), &AppStateForSetup).await;
232
233 // [Vine] [gRPC]
234 let _ = VineStartFn(PostSetupAppHandle.clone(), "[::1]:50051".to_string(), "[::1]:50052".to_string()).await;
235
236 // [Cocoon] [Sidecar]
237 let _ = CocoonStartFn(&PostSetupAppHandle, &PostSetupEnvironment).await;
238
239 info!("[Lifecycle] [PostSetup] Complete. System ready.");
240 });
241
242 Ok(())
243}