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}