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        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/// Health check response
59#[derive(Debug, Clone, Serialize, Deserialize)]
60pub struct HealthResponse {
61    /// Status indicator (returns "OK" when healthy)
62    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}