polyoxide_data/api/
health.rs1use polyoxide_core::{HttpClient, Request, RequestError};
2use serde::{Deserialize, Serialize};
3use std::time::{Duration, Instant};
4
5use crate::error::DataApiError;
6
7#[derive(Clone)]
9pub struct Health {
10 pub(crate) http_client: HttpClient,
11}
12
13impl Health {
14 pub async fn check(&self) -> Result<HealthResponse, DataApiError> {
16 Request::<HealthResponse, DataApiError>::new(self.http_client.clone(), "/")
17 .send()
18 .await
19 }
20
21 pub async fn ping(&self) -> Result<Duration, DataApiError> {
38 let _permit = self.http_client.acquire_concurrency().await;
39 self.http_client.acquire_rate_limit("/", None).await;
40
41 let start = Instant::now();
42 let response = self
43 .http_client
44 .client
45 .get(self.http_client.base_url.clone())
46 .send()
47 .await?;
48 let latency = start.elapsed();
49
50 if !response.status().is_success() {
51 return Err(DataApiError::from_response(response).await);
52 }
53
54 Ok(latency)
55 }
56}
57
58#[derive(Debug, Clone, Serialize, Deserialize)]
60pub struct HealthResponse {
61 pub data: String,
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68
69 #[test]
70 fn deserialize_health_response() {
71 let json = r#"{"data": "OK"}"#;
72 let health: HealthResponse = serde_json::from_str(json).unwrap();
73 assert_eq!(health.data, "OK");
74 }
75
76 #[test]
77 fn health_response_roundtrip() {
78 let original = HealthResponse {
79 data: "OK".to_string(),
80 };
81 let json = serde_json::to_string(&original).unwrap();
82 let deserialized: HealthResponse = serde_json::from_str(&json).unwrap();
83 assert_eq!(deserialized.data, original.data);
84 }
85}