1#![allow(non_snake_case)]
166
167use std::{env, net::SocketAddr, sync::Arc, time::Duration};
168
169use AirLibrary::dev_log;
170use tokio::{signal, time::interval};
171use AirLibrary::{
173 ApplicationState::ApplicationState,
174 Authentication::AuthenticationService,
175 CLI::{CliParser, Command, ConfigCommand, DebugCommand, OutputFormatter},
176 Configuration::{AirConfiguration, ConfigurationManager},
177 Daemon::DaemonManager,
178 DefaultBindAddress,
179 DefaultConfigFile,
180 Downloader::DownloadManager,
181 HealthCheck::{HealthCheckLevel, HealthCheckManager, HealthStatistics},
182 Indexing::FileIndexer,
183 Logging,
184 Metrics,
185 ProtocolVersion,
186 Tracing,
187 Updates::UpdateManager,
188 VERSION,
189 Vine::Generated::air::air_service_server::AirServiceServer,
190 Vine::Server::AirVinegRPCService::AirVinegRPCService,
191};
192
193macro_rules! Trace {
199
200 ($($arg:tt)*) => {{
201
202 dev_log!("lifecycle", $($arg)*);
203 }};
204}
205
206async fn WaitForShutdownSignal() {
218 dev_log!("lifecycle", "[Shutdown] Waiting for termination signal...");
219
220 let ctrl_c = async {
221 match signal::ctrl_c().await {
222 Ok(()) => dev_log!("lifecycle", "[Shutdown] Received Ctrl+C signal"),
223
224 Err(e) => dev_log!("lifecycle", "error: [Shutdown] Failed to install Ctrl+C handler: {}", e),
225 }
226 };
227
228 #[cfg(unix)]
229 let terminate = async {
230 match signal::unix::signal(signal::unix::SignalKind::terminate()) {
231 Ok(mut sig) => {
232 sig.recv().await;
233
234 dev_log!("lifecycle", "[Shutdown] Received SIGTERM signal");
235 },
236
237 Err(e) => dev_log!("lifecycle", "error: [Shutdown] Failed to install signal handler: {}", e),
238 }
239 };
240
241 #[cfg(not(unix))]
242 let terminate = std::future::pending::<()>();
243
244 tokio::select! {
245
246 _ = ctrl_c => {},
247
248 _ = terminate => {},
249 }
250
251 dev_log!("lifecycle", "[Shutdown] Signal received, initiating graceful shutdown");
252}
253
254fn InitializeLogging() {
271 let json_output = match std::env::var("AIR_LOG_JSON") {
273 Ok(val) if !val.is_empty() => {
274 let normalized = val.to_lowercase();
275
276 if normalized != "true" && normalized != "false" {
277 eprintln!(
278 "Warning: Invalid AIR_LOG_JSON value '{}', expected 'true' or 'false'. Using default: false",
279 val
280 );
281
282 false
283 } else {
284 normalized == "true"
285 }
286 },
287
288 Ok(_) => false,
289
290 Err(_) => false,
291 };
292
293 let log_file_path = std::env::var("AIR_LOG_FILE").ok().and_then(|path| {
295 if path.is_empty() {
296 None
297 } else {
298 if let Some(parent) = std::path::PathBuf::from(&path).parent() {
300 if parent.as_os_str().is_empty() {
301 Some(path)
303 } else if parent.exists() {
304 Some(path)
305 } else {
306 eprintln!(
307 "Warning: Log file directory does not exist: {}. Logging to stdout only.",
308 parent.display()
309 );
310 None
311 }
312 } else {
313 Some(path)
314 }
315 }
316 });
317
318 let log_result = Logging::InitializeLogger(json_output, log_file_path.clone());
320
321 match log_result {
322 Ok(_) => {
323 let log_info = match &log_file_path {
324 Some(path) => format!("file: {}", path),
325
326 None => "stdout/stderr".to_string(),
327 };
328
329 dev_log!(
330 "lifecycle",
331 "[Boot] Logging initialized - JSON: {}, Output: {}",
332 json_output,
333 log_info
334 );
335 },
336
337 Err(e) => {
338 eprintln!("[ERROR] Failed to initialize structured logging: {}", e);
340
341 eprintln!("[ERROR] Logging will fall back to stderr-only output");
342 },
343 }
344}
345
346fn ParseArguments() -> (Option<String>, Option<String>, Option<Command>) {
365 let args:Vec<String> = std::env::args().collect();
367
368 if args.len() > 1024 {
370 eprintln!("[ERROR] Too many command line arguments (max: 1024)");
371
372 std::process::exit(1);
373 }
374
375 for (i, arg) in args.iter().enumerate() {
377 if arg.len() > 4096 {
378 eprintln!("[ERROR] Argument at position {} is too long (max: 4096 characters)", i);
379
380 std::process::exit(1);
381 }
382 }
383
384 if args.len() > 1 {
386 match args[1].as_str() {
387 "status" | "restart" | "config" | "metrics" | "logs" | "debug" | "help" | "version" | "-h" | "--help"
388 | "-v" | "--version" => {
389 match CliParser::parse(args.clone()) {
391 Ok(cmd) => {
392 dev_log!("lifecycle", "[Boot] CLI command parsed: {:?}", cmd);
393
394 return (None, None, Some(cmd));
395 },
396
397 Err(e) => {
398 eprintln!("[ERROR] Error parsing CLI command: {}", e);
399
400 eprintln!("[ERROR] Run 'Air help' for usage information");
401
402 std::process::exit(1);
403 },
404 }
405 },
406
407 _ => {},
408 }
409 }
410
411 let mut config_path:Option<String> = None;
413
414 let mut bind_address:Option<String> = None;
415
416 let mut i = 0;
417
418 while i < args.len() {
419 match args[i].as_str() {
420 "--config" | "-c" => {
421 if i + 1 < args.len() {
422 let path = &args[i + 1];
423
424 if path.contains("..") || path.contains('\0') {
426 eprintln!("[ERROR] Invalid config path: contains '..' or null character");
427
428 std::process::exit(1);
429 }
430
431 config_path = Some(path.clone());
432
433 i += 1;
434 } else {
435 eprintln!("[ERROR] --config flag requires a path argument");
436
437 std::process::exit(1);
438 }
439 },
440
441 "--bind" | "-b" => {
442 if i + 1 < args.len() {
443 let addr = &args[i + 1];
444
445 if addr.is_empty() || addr.len() > 256 {
447 eprintln!("[ERROR] Invalid bind address: must be 1-256 characters");
448
449 std::process::exit(1);
450 }
451
452 if addr.contains('\0') {
454 eprintln!("[ERROR] Invalid bind address: contains null character");
455
456 std::process::exit(1);
457 }
458
459 bind_address = Some(addr.clone());
460
461 i += 1;
462 } else {
463 eprintln!("[ERROR] --bind flag requires an address argument");
464
465 std::process::exit(1);
466 }
467 },
468
469 _ => {
470
471 },
474 }
475
476 i += 1;
477 }
478
479 dev_log!(
480 "lifecycle",
481 "[Boot] Daemon mode - config: {:?}, bind: {:?}",
482 config_path,
483 bind_address
484 );
485
486 (config_path, bind_address, None)
487}
488
489async fn HandleCommand(cmd:Command) -> Result<(), Box<dyn std::error::Error>> {
512 let validation_result = validate_command(&cmd);
514
515 if let Err(e) = validation_result {
516 eprintln!("[ERROR] Command validation failed: {}", e);
517
518 return Err(e.into());
519 }
520
521 match cmd {
522 Command::Help { command } => {
523 if let Some(ref cmd) = command {
525 if cmd.len() > 128 {
526 eprintln!("[ERROR] Command name too long (max: 128 characters)");
527
528 return Err("Command name too long".into());
529 }
530 }
531
532 println!("{}", OutputFormatter::format_help(command.as_deref(), VERSION));
533
534 Ok(())
535 },
536
537 Command::Version => {
538 println!("Air {} ({})", VERSION, env!("CARGO_PKG_NAME"));
539
540 println!("Protocol: Version {} (gRPC)", ProtocolVersion);
541
542 println!("Port: {} (Air), {} (Cocoon)", DefaultBindAddress, "[::1]:50052");
543
544 println!("Build: {} {}", env!("CARGO_PKG_VERSION"), env!("CARGO_PKG_NAME"));
545
546 Ok(())
547 },
548
549 Command::Status { service, verbose, json } => {
550 if let Some(ref svc) = service {
552 if svc.is_empty() || svc.len() > 64 {
553 return Err("Service name must be 1-64 characters".into());
554 }
555 }
556
557 if let Some(svc) = service {
562 println!("📊 Status for service: {}", svc);
563
564 match attempt_daemon_connection().await {
566 Ok(_) => {
567 println!(" Status: ⚠️ Running (basic check)");
568
569 println!(" Note: Connect to gRPC endpoint for detailed status");
570 },
571
572 Err(e) => {
573 println!(" Status: ❌ Cannot connect to daemon");
574
575 println!(" Error: {}", e);
576
577 println!("");
578
579 println!(" To start the daemon, run: Air --daemon");
580
581 return Err(format!("Cannot connect to daemon: {}", e).into());
582 },
583 }
584 } else {
585 println!("📊 Air Daemon Status");
586
587 println!("");
588
589 match attempt_daemon_connection().await {
591 Ok(_) => {
592 println!(" Overall: ⚠️ Running (basic check)");
593
594 println!(" Note: Connect to gRPC endpoint for detailed status");
595
596 println!("");
597
598 println!(" Services:");
599
600 println!(" gRPC Server: ✅ Listening");
601
602 println!(" Authentication: ⚠️ Status check not implemented");
603
604 println!(" Updates: ⚠️ Status check not implemented");
605
606 println!(" Download Manager: ⚠️ Status check not implemented");
607
608 println!(" File Indexer: ⚠️ Status check not implemented");
609 },
610
611 Err(e) => {
612 println!(" Overall: ❌ Daemon not running");
613
614 println!(" Error: {}", e);
615
616 println!("");
617
618 println!(" To start the daemon, run: Air --daemon");
619
620 return Err("Daemon not running".into());
621 },
622 }
623 }
624
625 if verbose {
626 println!("");
627
628 println!("🔍 Verbose Information:");
629
630 println!(" Debug mode: Disabled by default");
631
632 println!(" Log level: info");
633
634 println!(" Config file: {}", DefaultConfigFile);
635
636 println!("");
637
638 println!(" Detailed service status can be obtained via gRPC:");
639
640 println!(" - Service uptime");
641
642 println!(" - Request/response statistics");
643
644 println!(" - Error rates and recent errors");
645
646 println!(" - Resource usage");
647
648 println!(" - Active connections");
649 }
650
651 if json {
652 println!("");
653
654 println!("📋 JSON Output:");
655
656 println!(
657 "{}",
658 serde_json::json!({
659 "overall": "running",
660 "services": {
661 "grpc": "listening",
662 "status": "not_implemented"
663 },
664 "note": "Detailed JSON output not yet implemented"
665 })
666 );
667 }
668
669 Ok(())
670 },
671
672 Command::Restart { service, force } => {
673 if let Some(ref svc) = service {
675 if svc.is_empty() || svc.len() > 64 {
676 return Err("Service name must be 1-64 characters".into());
677 }
678 }
679
680 println!("🔄 Restart Command");
683
684 println!("");
685
686 if let Some(svc) = service {
687 println!("Restarting service: {}", svc);
688
689 println!(" Note: Individual service restart requires gRPC integration");
690
691 println!(" Workaround: Restart the entire daemon");
692 } else {
693 println!("Restarting all services...");
694
695 println!(" Note: Full daemon restart requires gRPC integration");
696
697 println!(" Workaround: Use: kill <pid> && Air --daemon");
698 }
699
700 if force {
701 println!("");
702
703 println!("⚠️ Force mode enabled");
704
705 println!(
706 " Note: Force restart requires proper coordination to gracefully terminate in-progress operations"
707 );
708 }
709
710 Err("Restart command requires gRPC integration".into())
711 },
712
713 Command::Config(config_cmd) => {
714 match config_cmd {
715 ConfigCommand::Get { key } => {
716 if key.is_empty() || key.len() > 256 {
718 return Err("Configuration key must be 1-256 characters".into());
719 }
720
721 if key.contains('\0') || key.contains('\n') {
722 return Err("Configuration key contains invalid characters".into());
723 }
724
725 println!("⚙️ Get Configuration");
728
729 println!(" Key: {}", key);
730
731 println!("");
732
733 match attempt_daemon_connection().await {
734 Ok(_) => {
735 println!(" Status: ✅ Connected to daemon");
736
737 println!("");
738
739 println!(" Note: Config retrieval via gRPC not yet implemented");
740
741 println!(" Config value would be retrieved from daemon's configuration manager");
742 },
743
744 Err(e) => {
745 println!(" Status: ❌ Cannot connect to daemon");
746
747 println!(" Error: {}", e);
748
749 println!("");
750
751 println!(" Workaround: Check config file directly: cat {}", DefaultConfigFile);
752
753 return Err(format!("Cannot get config: {}", e).into());
754 },
755 }
756
757 Err("Config 'get' command requires gRPC integration".into())
758 },
759
760 ConfigCommand::Set { key, value } => {
761 if key.is_empty() || key.len() > 256 {
763 return Err("Configuration key must be 1-256 characters".into());
764 }
765
766 if value.len() > 8192 {
767 return Err("Configuration value too long (max: 8192 characters)".into());
768 }
769
770 if key.contains('\0') || key.contains('\n') {
771 return Err("Configuration key contains invalid characters".into());
772 }
773
774 println!("⚙️ Set Configuration");
777
778 println!(" Key: {}", key);
779
780 println!(" Value: {}", value);
781
782 println!("");
783
784 match attempt_daemon_connection().await {
785 Ok(_) => {
786 println!(" Status: ✅ Connected to daemon");
787
788 println!("");
789
790 println!(" Note: Config update via gRPC not yet implemented");
791
792 println!(" Config value would be set in daemon's configuration manager");
793 },
794
795 Err(e) => {
796 println!(" Status: ❌ Cannot connect to daemon");
797
798 println!(" Error: {}", e);
799
800 println!("");
801
802 println!(" Workaround: Edit config file directly, then use 'Air config reload'");
803
804 return Err(format!("Cannot set config: {}", e).into());
805 },
806 }
807
808 println!("");
809
810 println!(" ⚠️ Warning: Config changes may require reload or restart");
811
812 Err("Config 'set' command requires gRPC integration".into())
813 },
814
815 ConfigCommand::Reload { validate } => {
816 println!("🔄 Reload Configuration");
819
820 println!("");
821
822 match attempt_daemon_connection().await {
823 Ok(_) => {
824 println!(" Status: ✅ Connected to daemon");
825
826 println!("");
827
828 if validate {
829 println!(" Validating configuration...");
830
831 println!(" Note: Validation not yet implemented");
832 }
833
834 println!(" Note: Config reload via gRPC not yet implemented");
835
836 println!(" Workaround: Restart daemon to apply config changes");
837 },
838
839 Err(e) => {
840 println!(" Status: ❌ Cannot connect to daemon");
841
842 println!(" Error: {}", e);
843
844 return Err(format!("Cannot reload config: {}", e).into());
845 },
846 }
847
848 Err("Config 'reload' command requires gRPC integration".into())
849 },
850
851 ConfigCommand::Show { json } => {
852 println!("⚙️ Show Configuration");
855
856 println!("");
857
858 if json {
859 println!(" JSON output requested");
860
861 match attempt_daemon_connection().await {
862 Ok(_) => {
863 println!(" Status: ✅ Connected to daemon");
864
865 println!(" Note: JSON config export via gRPC not yet implemented");
866 },
867
868 Err(e) => {
869 println!(" Status: ❌ Cannot connect to daemon");
870
871 println!(" Error: {}", e);
872
873 return Err(format!("Cannot show config: {}", e).into());
874 },
875 }
876 } else {
877 println!(" Current Configuration:");
878
879 match attempt_daemon_connection().await {
880 Ok(_) => {
881 println!(" Status: ✅ Connected to daemon");
882
883 println!(" Note: Config display via gRPC not yet implemented");
884 },
885
886 Err(e) => {
887 println!(" Status: ❌ Cannot connect to daemon");
888
889 println!(" Error: {}", e);
890
891 println!(" Workaround: View config file: cat {}", DefaultConfigFile);
892
893 return Err(format!("Cannot show config: {}", e).into());
894 },
895 }
896 }
897
898 println!("");
899
900 println!(" Default config file: {}", DefaultConfigFile);
901
902 println!(" Config directory: ~/.config/Air/");
903
904 Err("Config 'show' command requires gRPC integration".into())
905 },
906
907 ConfigCommand::Validate { path } => {
908 if let Some(ref p) = path {
910 if p.is_empty() || p.len() > 512 {
911 return Err("Config path must be 1-512 characters".into());
912 }
913
914 if p.contains("..") || p.contains('\0') {
915 return Err("Config path contains invalid characters".into());
916 }
917 }
918
919 println!("✅ Validate Configuration");
920
921 println!("");
922
923 let config_path = path.unwrap_or_else(|| DefaultConfigFile.to_string());
924
925 println!(" Config file: {}", config_path);
926
927 println!("");
928
929 match std::path::Path::new(&config_path).exists() {
931 true => {
932 println!(" ✅ Config file exists");
933
934 println!(" Note: Detailed validation not yet implemented");
935
936 println!(" Workaround: Use: Air --validate-config");
937 },
938
939 false => {
940 println!(" ❌ Config file not found");
941
942 println!(" Hint: Create a config file or use defaults");
943 },
944 }
945
946 Err("Config 'validate' command not yet implemented".into())
947 },
948 }
949 },
950
951 Command::Metrics { json, service } => {
952 if let Some(ref svc) = service {
954 if svc.is_empty() || svc.len() > 64 {
955 return Err("Service name must be 1-64 characters".into());
956 }
957 }
958
959 println!("📊 Metrics");
960
961 println!("");
962
963 match attempt_daemon_connection().await {
965 Ok(_) => {
966 println!(" Status: ✅ Daemon is running");
967
968 println!("");
969
970 println!(" Note: Metrics collection is partially implemented");
971
972 println!("");
973
974 println!(" Current Metrics (basic):");
975
976 println!(" Uptime: Not tracked yet");
977
978 println!(" Requests: Not tracked yet");
979
980 println!(" Errors: Not tracked yet");
981
982 println!(" Memory: Not tracked yet");
983
984 println!(" CPU: Not tracked yet");
985
986 println!("");
987
988 println!(" Note: Comprehensive metrics require gRPC integration:");
989
990 println!(" - Request/response counters");
991
992 println!(" - Latency percentiles");
993
994 println!(" - Error rate tracking");
995
996 println!(" - Resource usage");
997
998 println!(" - Connection pool stats");
999
1000 println!(" - Background queue depth");
1001 },
1002
1003 Err(e) => {
1004 println!(" Status: ❌ Cannot connect to daemon");
1005
1006 println!(" Error: {}", e);
1007
1008 return Err(format!("Cannot retrieve metrics: {}", e).into());
1009 },
1010 }
1011
1012 if json {
1013 println!("");
1014
1015 println!("📋 JSON Output:");
1016
1017 println!(
1018 "{}",
1019 serde_json::json!({
1020 "note": "Detailed metrics not yet implemented",
1021 "suggestion": "Use /metrics endpoint when daemon is running"
1022 })
1023 );
1024 }
1025
1026 if let Some(svc) = service {
1027 println!("");
1028
1029 println!(" Service-specific metrics requested: {}", svc);
1030
1031 println!(" Note: Service isolation not yet implemented");
1032 }
1033
1034 Ok(())
1035 },
1036
1037 Command::Logs { service, tail, filter, follow } => {
1038 if let Some(ref svc) = service {
1040 if svc.is_empty() || svc.len() > 64 {
1041 return Err("Service name must be 1-64 characters".into());
1042 }
1043 }
1044
1045 if let Some(n) = tail {
1046 if n < 1 || n > 10000 {
1047 return Err("Tail count must be 1-10000 lines".into());
1048 }
1049 }
1050
1051 if let Some(ref f) = filter {
1052 if f.is_empty() || f.len() > 512 {
1053 return Err("Filter string must be 1-512 characters".into());
1054 }
1055 }
1056
1057 println!("📝 Logs");
1058
1059 println!("");
1060
1061 let log_file = std::env::var("AIR_LOG_FILE").ok();
1063
1064 let log_dir = std::env::var("AIR_LOG_DIR").ok();
1065
1066 match (log_file, log_dir) {
1067 (Some(file), _) => {
1068 println!(" Log file: {}", file);
1069
1070 if std::path::Path::new(&file).exists() {
1072 println!(" Status: ✅ Log file exists");
1073
1074 println!("");
1075
1076 println!(" Note: Log tailing via file API not yet implemented");
1079
1080 println!(" Workaround: Use standard tools:");
1081
1082 println!(" - tail -n {} {}", tail.unwrap_or(100), file);
1083
1084 if let Some(f) = filter {
1085 println!(" - grep '{}' {} | tail -n {}", f, file, tail.unwrap_or(100));
1086 }
1087
1088 if follow {
1089 println!(" - tail -f {}", file);
1090 }
1091 } else {
1092 println!(" Status: ❌ Log file not found");
1093
1094 println!(" Check logging configuration");
1095 }
1096 },
1097
1098 (_, Some(dir)) => {
1099 println!(" Log directory: {}", dir);
1100
1101 println!(" Note: Log file viewing not yet implemented");
1102
1103 println!(" Workaround: Find and view log files in the directory");
1104 },
1105
1106 _ => {
1107 println!(" Log file: Not configured");
1108
1109 println!(" Set via: AIR_LOG_FILE=/path/to/Air.log");
1110
1111 println!("");
1112
1113 println!(" Logs are likely going to stdout/stderr");
1114
1115 println!(" Use journalctl (Linux/macOS) or Event Viewer (Windows)");
1116 },
1117 }
1118
1119 if let Some(svc) = service {
1120 println!("");
1121
1122 println!(" Service-specific logs requested: {}", svc);
1123
1124 println!(" Note: Service log isolation not yet implemented");
1125 }
1126
1127 Err("Logs command not yet fully implemented".into())
1129 },
1130
1131 Command::Debug(debug_cmd) => {
1132 match debug_cmd {
1133 DebugCommand::DumpState { service, json } => {
1134 if let Some(ref svc) = service {
1136 if svc.is_empty() || svc.len() > 64 {
1137 return Err("Service name must be 1-64 characters".into());
1138 }
1139 }
1140
1141 println!("🔧 Debug: Dump State");
1142
1143 println!("");
1144
1145 if let Some(svc) = service {
1146 println!(" Service: {}", svc);
1147
1148 println!(" Note: Service state isolation not yet implemented");
1149 } else {
1150 println!(" Dumping all service states...");
1151
1152 println!(" Note: State dumping not yet implemented");
1153 }
1154
1155 if json {
1156 println!("");
1157
1158 println!(" JSON format requested");
1159
1160 println!(" Note: JSON state export not yet implemented");
1161 }
1162
1163 println!("");
1164
1165 println!(" Note: State dumping requires gRPC integration:");
1166
1167 println!(" - Application state");
1168
1169 println!(" - Service states");
1170
1171 println!(" - Connection pool");
1172
1173 println!(" - Background tasks");
1174
1175 println!(" - Metrics cache");
1176
1177 println!(" - Configuration snapshot");
1178
1179 Err("Debug 'dump-state' command not yet implemented".into())
1180 },
1181
1182 DebugCommand::DumpConnections { format } => {
1183 println!("🔧 Debug: Dump Connections");
1184
1185 println!("");
1186
1187 match attempt_daemon_connection().await {
1188 Ok(_) => {
1189 println!(" Status: ✅ Daemon is running");
1190
1191 println!("");
1192
1193 println!(" Active Connections: 0");
1194
1195 println!(" Note: Connection tracking not yet implemented");
1196 },
1197
1198 Err(e) => {
1199 println!(" Status: ❌ Cannot connect to daemon");
1200
1201 println!(" Error: {}", e);
1202
1203 return Err(format!("Cannot dump connections: {}", e).into());
1204 },
1205 }
1206
1207 if let Some(fmt) = format {
1208 println!("");
1209
1210 println!(" Format: {}", fmt);
1211
1212 println!(" Note: Custom format not yet implemented");
1213 }
1214
1215 println!("");
1216
1217 println!(" Note: Connection dump requires gRPC integration:");
1218
1219 println!(" - Connection ID");
1220
1221 println!(" - Remote address");
1222
1223 println!(" - Connected at timestamp");
1224
1225 println!(" - Last activity");
1226
1227 println!(" - Active requests");
1228
1229 println!(" - Bytes transferred");
1230
1231 Err("Debug 'dump-connections' command not yet implemented".into())
1232 },
1233
1234 DebugCommand::HealthCheck { verbose, service } => {
1235 if let Some(ref svc) = service {
1237 if svc.is_empty() || svc.len() > 64 {
1238 return Err("Service name must be 1-64 characters".into());
1239 }
1240 }
1241
1242 println!("🔧 Debug: Health Check");
1243
1244 println!("");
1245
1246 match attempt_daemon_connection().await {
1247 Ok(_) => {
1248 println!(" Overall: ⚠️ Basic check passed");
1249
1250 println!("");
1251
1252 if let Some(svc) = service {
1253 println!(" Service: {}", svc);
1254
1255 println!(" Status: Not checked (detailed checks not implemented)");
1256 } else {
1257 println!(" Services:");
1258
1259 println!(" gRPC Server: ✅ Responding");
1260
1261 println!(" Authentication: ⏸️ Not checked");
1262
1263 println!(" Updates: ⏸️ Not checked");
1264
1265 println!(" Download Manager: ⏸️ Not checked");
1266
1267 println!(" File Indexer: ⏸️ Not checked");
1268 }
1269
1270 if verbose {
1271 println!("");
1272
1273 println!(" 🔍 Verbose Information:");
1274
1275 println!(" Last health check: Not tracked");
1276
1277 println!(" Health check interval: 30s (default)");
1278
1279 println!(" Failure threshold: 3 (configurable)");
1280
1281 println!(" Recovery threshold: 2 (configurable)");
1282 }
1283 },
1284
1285 Err(e) => {
1286 println!(" Overall: ❌ Daemon unreachable");
1287
1288 println!(" Error: {}", e);
1289
1290 return Err(format!("Health check failed: {}", e).into());
1291 },
1292 }
1293
1294 Err("Debug 'health-check' not detailed yet".into())
1295 },
1296
1297 DebugCommand::Diagnostics { level } => {
1298 println!("🔧 Debug: Diagnostics");
1299
1300 println!("");
1301
1302 println!(" Level: {:?}", level);
1303
1304 println!("");
1305
1306 println!(" System Information:");
1308
1309 println!(" OS: {}", std::env::consts::OS);
1310
1311 println!(" Arch: {}", std::env::consts::ARCH);
1312
1313 println!(" Air Version: {}", VERSION);
1314
1315 println!("");
1316
1317 match attempt_daemon_connection().await {
1318 Ok(_) => {
1319 println!(" Daemon: ✅ Running");
1320 },
1321
1322 Err(e) => {
1323 println!(" Daemon: ❌ Running");
1324
1325 println!(" Error: {}", e);
1326 },
1327 }
1328
1329 println!("");
1330
1331 println!(" Note: Advanced diagnostics require additional infrastructure:");
1332
1333 println!(" - Thread dump");
1334
1335 println!(" - Memory profiling");
1336
1337 println!(" - Lock contention analysis");
1338
1339 println!(" - Resource leak detection");
1340
1341 println!(" - Performance bottlenecks");
1342
1343 Ok(())
1344 },
1345 }
1346 },
1347 }
1348}
1349
1350fn validate_command(cmd:&Command) -> Result<(), String> {
1357 match cmd {
1358 Command::Help { command } => {
1359 if let Some(cmd) = command {
1360 if cmd.len() > 128 {
1361 return Err("Command name too long (max: 128)".to_string());
1362 }
1363 }
1364 },
1365
1366 _ => {},
1367 }
1368
1369 Ok(())
1370}
1371
1372async fn attempt_daemon_connection_with_retry(max_retries:usize, initial_delay_ms:u64) -> Result<(), String> {
1395 use tokio::{
1396 net::TcpStream,
1397 time::{Duration, timeout},
1398 };
1399
1400 let addr = DefaultBindAddress;
1401
1402 let mut attempt = 0;
1403
1404 let mut delay_ms = initial_delay_ms;
1405
1406 loop {
1407 attempt += 1;
1408
1409 dev_log!("lifecycle", "[DaemonConnection] Attempt {} of {}", attempt, max_retries + 1);
1410
1411 let connection_result = timeout(Duration::from_secs(5), async { TcpStream::connect(addr).await }).await;
1413
1414 match connection_result {
1415 Ok(Ok(_stream)) => {
1416 dev_log!("lifecycle", "[DaemonConnection] Connected successfully on attempt {}", attempt);
1417
1418 return Ok(());
1419 },
1420
1421 Ok(Err(e)) => {
1422 dev_log!("lifecycle", "[DaemonConnection] Attempt {} failed: {}", attempt, e);
1423 },
1424
1425 Err(_) => {
1426 dev_log!("lifecycle", "[DaemonConnection] Attempt {} timed out", attempt);
1427 },
1428 }
1429
1430 if attempt > max_retries {
1432 break;
1433 }
1434
1435 dev_log!("lifecycle", "[DaemonConnection] Waiting {}ms before retry...", delay_ms);
1437
1438 tokio::time::sleep(Duration::from_millis(delay_ms)).await;
1439
1440 delay_ms = delay_ms * 2; }
1442
1443 Err(format!("Failed to connect after {} attempts", max_retries + 1))
1444}
1445
1446async fn attempt_daemon_connection() -> Result<(), String> {
1451 attempt_daemon_connection_with_retry(3, 500).await
1453}
1454
1455#[allow(dead_code)]
1475fn HandleMetricsRequest() -> String {
1476 let _timeout_duration = std::time::Duration::from_millis(100);
1478
1479 let metrics_collector = Metrics::GetMetrics();
1480
1481 let export_result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| metrics_collector.ExportMetrics()));
1483
1484 match export_result {
1485 Ok(Ok(metrics_text)) => {
1486 if metrics_text.len() > 10_000_000 {
1488 dev_log!(
1489 "metrics",
1490 "error: [Metrics] Exported metrics unreasonably large (size: {} bytes)",
1491 metrics_text.len()
1492 );
1493
1494 format!("# ERROR: Metrics export too large (max: 10MB)\n")
1495 } else {
1496 metrics_text
1497 }
1498 },
1499
1500 Ok(Err(e)) => {
1501 dev_log!("metrics", "error: [Metrics] Failed to export metrics: {}", e);
1502
1503 format!("# ERROR: Failed to export metrics: {}\n", e)
1504 },
1505
1506 Err(_) => {
1507 dev_log!("metrics", "error: [Metrics] Metrics export panicked");
1508
1509 format!("# ERROR: Metrics export failed due to internal error\n")
1510 },
1511 }
1512}
1513
1514async fn Main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
1555 CommonLibrary::Telemetry::Initialize::Fn(CommonLibrary::Telemetry::Tier::Tier::Air).await;
1561
1562 InitializeLogging();
1566
1567 dev_log!("lifecycle", "[Boot] ===========================================");
1568
1569 dev_log!("lifecycle", "[Boot] Starting Air Daemon");
1570
1571 dev_log!("lifecycle", "[Boot] ===========================================");
1572
1573 dev_log!(
1574 "lifecycle",
1575 "[Boot] Version: {} ({})",
1576 env!("CARGO_PKG_VERSION"),
1577 env!("CARGO_PKG_NAME")
1578 );
1579
1580 let build_timestamp = env::var("BUILD_TIMESTAMP").unwrap_or_else(|_| "unknown".to_string());
1581
1582 dev_log!("lifecycle", "[Boot] Build: {}", build_timestamp);
1583
1584 dev_log!(
1585 "lifecycle",
1586 "[Boot] Target: {}-{}",
1587 std::env::consts::OS,
1588 std::env::consts::ARCH
1589 );
1590
1591 dev_log!("lifecycle", "[Boot] Validating environment...");
1595
1596 if let Err(e) = validate_environment().await {
1597 dev_log!("lifecycle", "error: [Boot] Environment validation failed: {}", e);
1598
1599 return Err(format!("Environment validation failed: {}", e).into());
1600 }
1601
1602 dev_log!("lifecycle", "[Boot] Environment validation passed");
1603
1604 Trace!("[Boot] [Observability] Initializing observability systems...");
1608
1609 if let Err(e) = Metrics::InitializeMetrics() {
1611 dev_log!("lifecycle", "error: [Boot] Failed to initialize metrics: {}", e);
1612
1613 } else {
1615 dev_log!("lifecycle", "[Boot] [Observability] Metrics system initialized");
1616 }
1617
1618 if let Err(e) = Tracing::initialize_tracing(None) {
1620 dev_log!("lifecycle", "error: [Boot] Failed to initialize tracing: {}", e);
1621
1622 } else {
1624 dev_log!("lifecycle", "[Boot] [Observability] Tracing system initialized");
1625 }
1626
1627 dev_log!("lifecycle", "[Boot] [Observability] Observability systems initialized");
1628
1629 Trace!("[Boot] [Args] Parsing command line arguments...");
1633
1634 let (config_path, bind_address, cli_command) = ParseArguments();
1635
1636 if let Some(cmd) = cli_command {
1638 dev_log!("lifecycle", "[Boot] CLI command detected, executing...");
1639
1640 let result = HandleCommand(cmd).await;
1641
1642 match &result {
1643 Ok(_) => {
1644 dev_log!("lifecycle", "[Boot] CLI command completed successfully");
1645
1646 std::process::exit(0);
1647 },
1648
1649 Err(e) => {
1650 dev_log!("lifecycle", "error: [Boot] CLI command failed: {}", e);
1651
1652 std::process::exit(1);
1653 },
1654 }
1655 }
1656
1657 Trace!("[Boot] [Configuration] Loading configuration...");
1661
1662 let config_manager = match ConfigurationManager::New(config_path) {
1663 Ok(cm) => cm,
1664
1665 Err(e) => {
1666 dev_log!("lifecycle", "error: [Boot] Failed to create configuration manager: {}", e);
1667
1668 return Err(format!("Configuration manager initialization failed: {}", e).into());
1669 },
1670 };
1671
1672 let configuration:std::sync::Arc<AirLibrary::Configuration::AirConfiguration> =
1674 match tokio::time::timeout(Duration::from_secs(10), config_manager.LoadConfiguration()).await {
1675 Ok(Ok(config)) => {
1676 dev_log!("lifecycle", "[Boot] [Configuration] Configuration loaded successfully");
1677
1678 std::sync::Arc::new(config)
1679 },
1680
1681 Ok(Err(e)) => {
1682 dev_log!("lifecycle", "error: [Boot] Failed to load configuration: {}", e);
1683
1684 return Err(format!("Configuration load failed: {}", e).into());
1685 },
1686
1687 Err(_) => {
1688 dev_log!("lifecycle", "error: [Boot] Configuration load timed out");
1689
1690 return Err("Configuration load timed out".into());
1691 },
1692 };
1693
1694 validate_configuration(&configuration)?;
1696
1697 Trace!("[Boot] [Daemon] Initializing daemon lifecycle management...");
1701
1702 let daemon_manager = match DaemonManager::New(None) {
1703 Ok(dm) => dm,
1704
1705 Err(e) => {
1706 dev_log!("lifecycle", "error: [Boot] Failed to create daemon manager: {}", e);
1707
1708 return Err(format!("Daemon manager initialization failed: {}", e).into());
1709 },
1710 };
1711
1712 match tokio::time::timeout(Duration::from_secs(5), daemon_manager.AcquireLock()).await {
1714 Ok(Ok(_)) => {
1715 dev_log!("lifecycle", "[Boot] [Daemon] Daemon lock acquired successfully");
1716 },
1717
1718 Ok(Err(e)) => {
1719 dev_log!("lifecycle", "error: [Boot] Failed to acquire daemon lock: {}", e);
1720
1721 dev_log!("lifecycle", "error: [Boot] Another instance may already be running");
1722
1723 return Err(format!("Daemon lock acquisition failed: {}", e).into());
1724 },
1725
1726 Err(_) => {
1727 dev_log!("lifecycle", "error: [Boot] Daemon lock acquisition timed out");
1728
1729 return Err("Daemon lock acquisition timed out".into());
1730 },
1731 }
1732
1733 Trace!("[Boot] [Health] Initializing health check system...");
1737
1738 let health_manager:std::sync::Arc<HealthCheckManager> = Arc::new(HealthCheckManager::new(None));
1739
1740 dev_log!("lifecycle", "[Boot] [Health] Health check system initialized");
1741
1742 Trace!("[Boot] [State] Initializing application state...");
1746
1747 let AppState:std::sync::Arc<ApplicationState> =
1748 match tokio::time::timeout(Duration::from_secs(10), ApplicationState::New(configuration.clone())).await {
1749 Ok(Ok(state)) => {
1750 dev_log!("lifecycle", "[Boot] [State] Application state initialized");
1751
1752 Arc::new(state)
1753 },
1754
1755 Ok(Err(e)) => {
1756 dev_log!("lifecycle", "error: [Boot] Failed to initialize application state: {}", e);
1757
1758 let _ = daemon_manager.ReleaseLock().await;
1760
1761 return Err(format!("Application state initialization failed: {}", e).into());
1762 },
1763
1764 Err(_) => {
1765 dev_log!("lifecycle", "error: [Boot] Application state initialization timed out");
1766
1767 let _ = daemon_manager.ReleaseLock().await;
1768
1769 return Err("Application state initialization timed out".into());
1770 },
1771 };
1772
1773 Trace!("[Boot] [Services] Initializing core services...");
1777
1778 let auth_service:std::sync::Arc<AuthenticationService> =
1780 match tokio::time::timeout(Duration::from_secs(10), AuthenticationService::new(AppState.clone())).await {
1781 Ok(Ok(svc)) => Arc::new(svc),
1782
1783 Ok(Err(e)) => {
1784 dev_log!("lifecycle", "error: [Boot] Failed to initialize authentication service: {}", e);
1785
1786 return Err(format!("Authentication service initialization failed: {}", e).into());
1787 },
1788
1789 Err(_) => {
1790 dev_log!("lifecycle", "error: [Boot] Authentication service initialization timed out");
1791
1792 return Err("Authentication service initialization timed out".into());
1793 },
1794 };
1795
1796 let update_manager:std::sync::Arc<UpdateManager> =
1797 match tokio::time::timeout(Duration::from_secs(10), UpdateManager::new(AppState.clone())).await {
1798 Ok(Ok(svc)) => Arc::new(svc),
1799
1800 Ok(Err(e)) => {
1801 dev_log!("lifecycle", "error: [Boot] Failed to initialize update manager: {}", e);
1802
1803 return Err(format!("Update manager initialization failed: {}", e).into());
1804 },
1805
1806 Err(_) => {
1807 dev_log!("lifecycle", "error: [Boot] Update manager initialization timed out");
1808
1809 return Err("Update manager initialization timed out".into());
1810 },
1811 };
1812
1813 let download_manager:std::sync::Arc<DownloadManager> =
1814 match tokio::time::timeout(Duration::from_secs(10), DownloadManager::new(AppState.clone())).await {
1815 Ok(Ok(svc)) => Arc::new(svc),
1816
1817 Ok(Err(e)) => {
1818 dev_log!("lifecycle", "error: [Boot] Failed to initialize download manager: {}", e);
1819
1820 return Err(format!("Download manager initialization failed: {}", e).into());
1821 },
1822
1823 Err(_) => {
1824 dev_log!("lifecycle", "error: [Boot] Download manager initialization timed out");
1825
1826 return Err("Download manager initialization timed out".into());
1827 },
1828 };
1829
1830 let file_indexer:std::sync::Arc<FileIndexer> =
1831 match tokio::time::timeout(Duration::from_secs(10), FileIndexer::new(AppState.clone())).await {
1832 Ok(Ok(svc)) => Arc::new(svc),
1833
1834 Ok(Err(e)) => {
1835 dev_log!("lifecycle", "error: [Boot] Failed to initialize file indexer: {}", e);
1836
1837 return Err(format!("File indexer initialization failed: {}", e).into());
1838 },
1839
1840 Err(_) => {
1841 dev_log!("lifecycle", "error: [Boot] File indexer initialization timed out");
1842
1843 return Err("File indexer initialization timed out".into());
1844 },
1845 };
1846
1847 dev_log!("lifecycle", "[Boot] [Services] All core services initialized successfully");
1848
1849 Trace!("[Boot] [Health] Registering services for health monitoring...");
1853
1854 let service_registrations = vec![
1856 ("authentication", HealthCheckLevel::Functional),
1857 ("updates", HealthCheckLevel::Functional),
1858 ("downloader", HealthCheckLevel::Functional),
1859 ("indexing", HealthCheckLevel::Functional),
1860 ("grpc", HealthCheckLevel::Responsive),
1861 ("connections", HealthCheckLevel::Alive),
1862 ];
1863
1864 for (service_name, level) in service_registrations {
1865 match tokio::time::timeout(
1866 Duration::from_secs(5),
1867 health_manager.RegisterService(service_name.to_string(), level),
1868 )
1869 .await
1870 {
1871 Ok(result) => {
1872 match result {
1873 Ok(_) => {
1874 dev_log!("lifecycle", "[Boot] [Health] Registered service: {}", service_name);
1875 },
1876
1877 Err(e) => {
1878 dev_log!("lifecycle", "warn: [Boot] Failed to register service {}: {}", service_name, e);
1879
1880 },
1883 }
1884 },
1885
1886 Err(_) => {
1887 dev_log!("lifecycle", "warn: [Boot] Service registration timed out: {}", service_name);
1888 },
1889 }
1890 }
1891
1892 dev_log!("lifecycle", "[Boot] [Health] Service health monitoring configured");
1893
1894 Trace!("[Boot] [Vine] Initializing gRPC server...");
1898
1899 let bind_addr:SocketAddr = match bind_address {
1901 Some(addr) => {
1902 match addr.parse() {
1903 Ok(parsed) => {
1904 dev_log!("lifecycle", "[Boot] [Vine] Using custom bind address: {}", parsed);
1905
1906 parsed
1907 },
1908
1909 Err(e) => {
1910 dev_log!("lifecycle", "error: [Boot] Invalid bind address '{}': {}", addr, e);
1911
1912 return Err(format!("Invalid bind address: {}", e).into());
1913 },
1914 }
1915 },
1916
1917 None => {
1918 match DefaultBindAddress.parse() {
1919 Ok(parsed) => parsed,
1920
1921 Err(e) => {
1922 dev_log!(
1923 "lifecycle",
1924 "error: [Boot] Invalid default bind address '{}': {}",
1925 DefaultBindAddress,
1926 e
1927 );
1928
1929 return Err(format!("Invalid default bind address: {}", e).into());
1930 },
1931 }
1932 },
1933 };
1934
1935 dev_log!("lifecycle", "[Boot] [Vine] Configuring gRPC server on {}", bind_addr);
1936
1937 let vine_service = AirVinegRPCService::new(
1939 AppState.clone(),
1940 auth_service.clone(),
1941 update_manager.clone(),
1942 download_manager.clone(),
1943 file_indexer.clone(),
1944 );
1945
1946 let (shutdown_tx, shutdown_rx) = tokio::sync::oneshot::channel::<()>();
1948
1949 let server_handle:tokio::task::JoinHandle<Result<(), Box<dyn std::error::Error + Send + Sync>>> =
1951 tokio::spawn(async move {
1952 dev_log!("lifecycle", "[Vine] Starting gRPC server on {}", bind_addr);
1953
1954 let svc = AirServiceServer::new(vine_service);
1955
1956 let server = tonic::transport::Server::builder()
1957 .add_service(svc)
1958 .serve_with_shutdown(bind_addr, async {
1959 let _ = shutdown_rx.await;
1961 dev_log!("lifecycle", "[Vine] Shutdown signal received, stopping server...");
1962 });
1963
1964 dev_log!("lifecycle", "[Vine] gRPC server listening on {}", bind_addr);
1965
1966 match server.await {
1967 Ok(_) => {
1968 dev_log!("lifecycle", "[Vine] gRPC server stopped cleanly");
1969 Ok(())
1970 },
1971 Err(e) => {
1972 dev_log!("grpc", "error: [Vine] gRPC server error: {}", e);
1973 Err(e.into())
1974 },
1975 }
1976 });
1977
1978 tokio::time::sleep(Duration::from_millis(100)).await;
1980
1981 if server_handle.is_finished() {
1983 dev_log!("lifecycle", "error: [Boot] gRPC server failed to start");
1984
1985 let _ = daemon_manager.ReleaseLock().await;
1986
1987 return Err("gRPC server failed to start".into());
1988 }
1989
1990 Trace!("[Boot] [Monitoring] Starting background monitoring tasks...");
1994
1995 let connection_monitor_handle:tokio::task::JoinHandle<()> = tokio::spawn({
1997 let AppState = AppState.clone();
1998 let health_manager = health_manager.clone();
1999 async move {
2000 let mut interval = interval(Duration::from_secs(60)); loop {
2002 interval.tick().await;
2003
2004 if let Err(e) = AppState.UpdateResourceUsage().await {
2006 dev_log!("lifecycle", "warn: [ConnectionMonitor] Failed to update resource usage: {}", e);
2007 }
2008
2009 let resources = AppState.GetResourceUsage().await;
2011
2012 let metrics_collector = Metrics::GetMetrics();
2014 metrics_collector.UpdateResourceMetrics(
2015 (resources.MemoryUsageMb * 1024.0 * 1024.0) as u64, resources.CPUUsagePercent,
2017 AppState.GetActiveConnectionCount().await as u64,
2018 0, );
2020
2021 if let Err(e) = AppState.CleanupStaleConnections(300).await {
2023 dev_log!(
2024 "lifecycle",
2025 "warn: [ConnectionMonitor] Failed to cleanup stale connections: {}",
2026 e
2027 );
2028 }
2029
2030 match health_manager.CheckService("connections").await {
2032 Ok(_) => {},
2033 Err(e) => {
2034 dev_log!("lifecycle", "warn: [ConnectionMonitor] Health check failed: {}", e);
2035
2036 let metrics_collector = Metrics::GetMetrics();
2038 metrics_collector.RecordRequestFailure("health_check_failed", 0.0);
2039 },
2040 }
2041
2042 dev_log!(
2043 "lifecycle",
2044 "[ConnectionMonitor] Active connections: {}",
2045 AppState.GetActiveConnectionCount().await
2046 );
2047 }
2048 }
2049 });
2050
2051 if let Err(e) = AppState.RegisterBackgroundTask(connection_monitor_handle).await {
2053 dev_log!("lifecycle", "warn: [Boot] Failed to register connection monitor: {}", e);
2054
2055 }
2057
2058 let health_monitor_handle:tokio::task::JoinHandle<()> = tokio::spawn({
2060 let health_manager = health_manager.clone();
2061 async move {
2062 let mut interval = interval(Duration::from_secs(30)); loop {
2064 interval.tick().await;
2065
2066 let services = ["authentication", "updates", "downloader", "indexing", "grpc"];
2068 for service in services.iter() {
2069 if let Err(e) = health_manager.CheckService(service).await {
2070 dev_log!("lifecycle", "warn: [HealthMonitor] Health check failed for {}: {}", service, e);
2071 }
2072 }
2073
2074 let overall_health = health_manager.GetOverallHealth().await;
2076 dev_log!("lifecycle", "[HealthMonitor] Overall health: {:?}", overall_health);
2077 }
2078 }
2079 });
2080
2081 if let Err(e) = AppState.RegisterBackgroundTask(health_monitor_handle).await {
2083 dev_log!("lifecycle", "warn: [Boot] Failed to register health monitor: {}", e);
2084
2085 }
2087
2088 Trace!("[Boot] [Startup] Starting background services...");
2092
2093 let _ = auth_service.StartBackgroundTasks().await?;
2095
2096 let _ = update_manager.StartBackgroundTasks().await?;
2097
2098 let _ = download_manager.StartBackgroundTasks().await?;
2099
2100 let _indexing_handle = None::<tokio::task::JoinHandle<()>>;
2102
2103 dev_log!("lifecycle", "[Boot] [Startup] All services started successfully");
2104
2105 dev_log!("lifecycle", "===========================================");
2109
2110 dev_log!("lifecycle", "[Runtime] Air Daemon is now running");
2111
2112 dev_log!("lifecycle", "[Runtime] Listening on {} for Mountain connections", bind_addr);
2113
2114 dev_log!("lifecycle", "[Runtime] Protocol Version: {}", ProtocolVersion);
2115
2116 dev_log!("lifecycle", "[Runtime] Cocoon Port: 50052");
2117
2118 dev_log!("lifecycle", "===========================================");
2119
2120 dev_log!("lifecycle", "");
2121
2122 dev_log!("lifecycle", "Running. Press Ctrl+C to stop.");
2123
2124 dev_log!("lifecycle", "");
2125
2126 WaitForShutdownSignal().await;
2128
2129 dev_log!("lifecycle", "[Shutdown] Signaling gRPC server to stop...");
2131
2132 let _ = shutdown_tx.send(());
2133
2134 match tokio::time::timeout(Duration::from_secs(30), server_handle).await {
2136 Ok(Ok(Ok(_))) => {
2137 dev_log!("lifecycle", "[Shutdown] gRPC server stopped normally");
2138 },
2139
2140 Ok(Ok(Err(e))) => {
2141 dev_log!("lifecycle", "warn: [Shutdown] gRPC server stopped with error: {}", e);
2142 },
2143
2144 Ok(Err(e)) => {
2145 dev_log!("lifecycle", "warn: [Shutdown] gRPC server task panicked: {:?}", e);
2146 },
2147
2148 Err(_) => {
2149 dev_log!("lifecycle", "warn: [Shutdown] gRPC server shutdown timed out");
2150 },
2151 }
2152
2153 dev_log!("lifecycle", "===========================================");
2157
2158 dev_log!("lifecycle", "[Shutdown] Initiating graceful shutdown...");
2159
2160 dev_log!("lifecycle", "===========================================");
2161
2162 dev_log!("lifecycle", "[Shutdown] Stopping background tasks...");
2164
2165 if let Err(_) =
2166 tokio::time::timeout(Duration::from_secs(10), async { AppState.StopAllBackgroundTasks().await }).await
2167 {
2168 dev_log!("lifecycle", "warn: [Shutdown] Background tasks stop timed out or failed");
2169 }
2170
2171 dev_log!("lifecycle", "[Shutdown] Stopping background services...");
2173
2174 auth_service.StopBackgroundTasks().await;
2175
2176 update_manager.StopBackgroundTasks().await;
2177
2178 download_manager.StopBackgroundTasks().await;
2179
2180 dev_log!("lifecycle", "[Shutdown] Collecting final statistics...");
2182
2183 let metrics = AppState.GetMetrics().await;
2184
2185 let resources = AppState.GetResourceUsage().await;
2186
2187 let health_stats:HealthStatistics = health_manager.GetHealthStatistics().await;
2188
2189 let metrics_data = Metrics::GetMetrics().GetMetricsData();
2191
2192 dev_log!("lifecycle", "===========================================");
2193
2194 dev_log!("lifecycle", "[Shutdown] Final Statistics");
2195
2196 dev_log!("lifecycle", "===========================================");
2197
2198 dev_log!("lifecycle", "[Shutdown] Requests:");
2199
2200 dev_log!("lifecycle", " - Successful: {}", metrics.SuccessfulRequest);
2201
2202 dev_log!("lifecycle", " - Failed: {}", metrics.FailedRequest);
2203
2204 dev_log!("lifecycle", "[Shutdown] Metrics:");
2205
2206 dev_log!("lifecycle", " - Success rate: {:.2}%", metrics_data.SuccessRate());
2207
2208 dev_log!("lifecycle", " - Error rate: {:.2}%", metrics_data.ErrorRate());
2209
2210 dev_log!("lifecycle", "[Shutdown] Resources:");
2211
2212 dev_log!("lifecycle", " - Memory: {:.2} MB", resources.MemoryUsageMb);
2213
2214 dev_log!("lifecycle", " - CPU: {:.2}%", resources.CPUUsagePercent);
2215
2216 dev_log!("lifecycle", "[Shutdown] Health:");
2217
2218 dev_log!("lifecycle", " - Overall: {:.2}%", health_stats.OverallHealthPercentage());
2219
2220 dev_log!(
2221 "lifecycle",
2222 " - Healthy services: {}/{}",
2223 health_stats.HealthyServices,
2224 health_stats.TotalServices
2225 );
2226
2227 dev_log!("lifecycle", "===========================================");
2228
2229 dev_log!("lifecycle", "[Shutdown] Releasing daemon lock...");
2231
2232 if let Err(e) = daemon_manager.ReleaseLock().await {
2233 dev_log!("lifecycle", "warn: [Shutdown] Failed to release daemon lock: {}", e);
2234 }
2235
2236 dev_log!("lifecycle", "[Shutdown] All services stopped");
2237
2238 dev_log!("lifecycle", "[Shutdown] Air Daemon has shut down gracefully");
2239
2240 dev_log!("lifecycle", "===========================================");
2241
2242 Ok(())
2243}
2244
2245async fn validate_environment() -> Result<(), String> {
2254 dev_log!(
2256 "lifecycle",
2257 "[Environment] OS: {}, Arch: {}",
2258 std::env::consts::OS,
2259 std::env::consts::ARCH
2260 );
2261
2262 if let Ok(home) = std::env::var("HOME") {
2264 if home.is_empty() {
2265 return Err("HOME environment variable is not set".to_string());
2266 }
2267 }
2268
2269 let lock_path = "/tmp/Air-test-lock.tmp";
2271
2272 if std::fs::write(lock_path, b"test").is_err() {
2273 return Err("Cannot write to /tmp directory".to_string());
2274 }
2275
2276 let _ = std::fs::remove_file(lock_path);
2277
2278 Ok(())
2279}
2280
2281fn validate_configuration(_config:&AirConfiguration) -> Result<(), String> {
2290 dev_log!("lifecycle", "[Config] Configuration passed basic validation");
2292
2293 Ok(())
2294}
2295
2296#[tokio::main]
2297async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> { Main().await }