Skip to main content

polyoxide_data/api/
health.rs

1use polyoxide_core::{HttpClient, Request, RequestError};
2use serde::{Deserialize, Serialize};
3use std::time::{Duration, Instant};
4
5use crate::error::DataApiError;
6
7/// Health namespace for API health operations
8#[derive(Clone)]
9pub struct Health {
10    pub(crate) http_client: HttpClient,
11}
12
13impl Health {
14    /// Check API health status
15    pub async fn check(&self) -> Result<HealthResponse, DataApiError> {
16        Request::<HealthResponse, DataApiError>::new(self.http_client.clone(), "/")
17            .send()
18            .await
19    }
20
21    /// Measure the round-trip time (RTT) to the Polymarket Data API.
22    ///
23    /// Makes a GET request to the API root and returns the latency.
24    ///
25    /// # Example
26    ///
27    /// ```no_run
28    /// use polyoxide_data::DataApi;
29    ///
30    /// # async fn example() -> Result<(), polyoxide_data::DataApiError> {
31    /// let client = DataApi::new()?;
32    /// let latency = client.health().ping().await?;
33    /// println!("API latency: {}ms", latency.as_millis());
34    /// # Ok(())
35    /// # }
36    /// ```
37    pub async fn ping(&self) -> Result<Duration, DataApiError> {
38        self.http_client.acquire_rate_limit("/", None).await;
39
40        let start = Instant::now();
41        let response = self
42            .http_client
43            .client
44            .get(self.http_client.base_url.clone())
45            .send()
46            .await?;
47        let latency = start.elapsed();
48
49        if !response.status().is_success() {
50            return Err(DataApiError::from_response(response).await);
51        }
52
53        Ok(latency)
54    }
55}
56
57/// Health check response
58#[derive(Debug, Clone, Serialize, Deserialize)]
59pub struct HealthResponse {
60    /// Status indicator (returns "OK" when healthy)
61    pub data: String,
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67
68    #[test]
69    fn deserialize_health_response() {
70        let json = r#"{"data": "OK"}"#;
71        let health: HealthResponse = serde_json::from_str(json).unwrap();
72        assert_eq!(health.data, "OK");
73    }
74
75    #[test]
76    fn health_response_roundtrip() {
77        let original = HealthResponse {
78            data: "OK".to_string(),
79        };
80        let json = serde_json::to_string(&original).unwrap();
81        let deserialized: HealthResponse = serde_json::from_str(&json).unwrap();
82        assert_eq!(deserialized.data, original.data);
83    }
84}