use std::time::{Duration, Instant};
use tonic::transport::{Channel, ClientTlsConfig};
#[derive(Debug)]
pub struct PingResult {
pub success: bool,
pub url: String,
pub latency_ms: Option<u64>,
pub error: Option<String>,
}
pub async fn ping_grpc_server(url: String) -> PingResult {
ping_grpc_server_with_timeout(url, Duration::from_secs(5)).await
}
pub async fn ping_grpc_server_with_timeout(url: String, timeout: Duration) -> PingResult {
let start = Instant::now();
let is_https = url.starts_with("https://");
let endpoint = match Channel::from_shared(url.clone()) {
Ok(ep) => ep.connect_timeout(timeout).timeout(timeout),
Err(e) => {
return PingResult {
success: false,
url,
latency_ms: None,
error: Some(format!("Invalid URL: {}", e)),
};
}
};
let endpoint = if is_https {
let tls_config = ClientTlsConfig::new().with_native_roots();
match endpoint.tls_config(tls_config) {
Ok(ep) => ep,
Err(e) => {
return PingResult {
success: false,
url,
latency_ms: None,
error: Some(format!("TLS configuration error: {}", e)),
};
}
}
} else {
endpoint
};
match endpoint.connect().await {
Ok(_channel) => {
let latency = start.elapsed().as_millis() as u64;
PingResult {
success: true,
url,
latency_ms: Some(latency),
error: None,
}
}
Err(e) => PingResult {
success: false,
url,
latency_ms: None,
error: Some(e.to_string()),
},
}
}