From d4f3bacf78d944b8729216d1e0957aa60b32bd5f Mon Sep 17 00:00:00 2001 From: Gabriel Bao Date: Wed, 20 May 2026 15:04:09 +0800 Subject: [PATCH] =?UTF-8?q?feat(health):=20=E5=81=A5=E5=BA=B7=E6=A3=80?= =?UTF-8?q?=E6=9F=A5=E6=B7=BB=E5=8A=A0=E7=BD=91=E7=BB=9C=E6=A3=80=E6=9F=A5?= =?UTF-8?q?=E4=B8=8E=E6=95=B0=E6=8D=AE=E5=BA=93=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/health/db_checker.rs | 20 ++++++++++++++++ src/health/mod.rs | 4 ++-- src/health/network_checker.rs | 44 +++++++++++++++++++++++++++++++++++ src/lib.rs | 15 ++++++++---- 4 files changed, 76 insertions(+), 7 deletions(-) diff --git a/src/health/db_checker.rs b/src/health/db_checker.rs index e69de29..470daa3 100644 --- a/src/health/db_checker.rs +++ b/src/health/db_checker.rs @@ -0,0 +1,20 @@ +use crate::core::db::DatabaseManager; +use log::error; + +pub fn check_db() -> Result { + let db = DatabaseManager::new() + .map_err(|e| { + let err_msg = format!("Failed to create database manager: {}", e); + error!("{}", err_msg); + err_msg + })?; + + db.health_check() + .map_err(|e| { + let err_msg = format!("Database health check failed: {}", e); + error!("{}", err_msg); + err_msg + })?; + + Ok(true) +} \ No newline at end of file diff --git a/src/health/mod.rs b/src/health/mod.rs index 0bc440b..d200c95 100644 --- a/src/health/mod.rs +++ b/src/health/mod.rs @@ -1,4 +1,4 @@ mod system_checker; -mod network_checker; -mod db_checker; +pub(crate) mod network_checker; +pub(crate) mod db_checker; mod config_checker; \ No newline at end of file diff --git a/src/health/network_checker.rs b/src/health/network_checker.rs index e69de29..6315d8c 100644 --- a/src/health/network_checker.rs +++ b/src/health/network_checker.rs @@ -0,0 +1,44 @@ +use std::net::{TcpStream, ToSocketAddrs}; +use std::time::Duration; +use log::{info, warn, error}; + +pub fn check_network() -> bool { + let targets = [ + "1.1.1.1:443", // Cloudflare + "8.8.8.8:53", // Google DNS + "223.5.5.5:53", // AliDNS + "180.76.76.76:53", // Baidu DNS + ]; + + info!("Starting network connectivity check"); + + for target in targets { + if can_connect(target, Duration::from_secs(3)) { + info!("Network check passed, successfully connected to {}", target); + return true; + } else { + warn!("Failed to connect to {}", target); + } + } + + error!("All network targets unreachable, network check failed"); + false +} + +fn can_connect(addr: &str, timeout: Duration) -> bool { + let addrs = match addr.to_socket_addrs() { + Ok(addrs) => addrs, + Err(e) => { + warn!("Failed to resolve address {}: {}", addr, e); + return false; + } + }; + + for addr in addrs { + if TcpStream::connect_timeout(&addr, timeout).is_ok() { + return true; + } + } + + false +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index a8d4c9b..44dc6d5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,9 +1,8 @@ #[macro_use] extern crate rust_i18n; -use crate::core::db::DatabaseManager; use crate::pages::layout::App; -use log::info; +use log::{error, info}; use ratatui_kit::crossterm::event::{Event, KeyCode, KeyEventKind}; use ratatui_kit::prelude::RouterProvider; use ratatui_kit::{AnyElement, ElementExt, Hooks, UseEvents, UseRouter, component, element}; @@ -31,8 +30,11 @@ pub async fn run() -> anyhow::Result<()> { info!("{}", t!("logger_is_initialized")); info!("{}", t!("test_message", name = "OmegaCode")); info!("{}", t!("current_locale", locale_name = "en")); - let db = DatabaseManager::new()?; - db.health_check()?; + + if !health_check() { + error!("Health check failed"); + return Err(anyhow::anyhow!("Health check failed")); + } element!(Root) .into_any() @@ -45,7 +47,6 @@ pub async fn run() -> anyhow::Result<()> { #[component] pub fn Root(_hooks: Hooks) -> impl Into> { - // 严格按照官方文档:RouterProvider 放最顶层 element!( RouterProvider( routes: app_routes(), @@ -54,4 +55,8 @@ pub fn Root(_hooks: Hooks) -> impl Into> { ) } +fn health_check() -> bool { + health::network_checker::check_network() && health::db_checker::check_db().unwrap() +} +