Skip to main content

systemprompt_api/services/health/
checker.rs

1use anyhow::{anyhow, Result};
2use std::time::Duration;
3use tokio::time::sleep;
4use tracing::{info, warn};
5
6#[derive(Debug)]
7pub struct HealthChecker {
8    url: String,
9    max_retries: u32,
10    retry_delay: Duration,
11}
12
13impl HealthChecker {
14    pub const fn new(url: String) -> Self {
15        Self {
16            url,
17            max_retries: 20,
18            retry_delay: Duration::from_secs(3),
19        }
20    }
21
22    pub const fn with_max_retries(mut self, max_retries: u32) -> Self {
23        self.max_retries = max_retries;
24        self
25    }
26
27    pub const fn with_retry_delay(mut self, retry_delay: Duration) -> Self {
28        self.retry_delay = retry_delay;
29        self
30    }
31
32    pub async fn check(&self) -> Result<()> {
33        info!("Performing health checks");
34
35        let client = reqwest::Client::builder()
36            .timeout(Duration::from_secs(5))
37            .build()?;
38
39        for attempt in 0..self.max_retries {
40            sleep(self.retry_delay).await;
41
42            match client.get(&self.url).send().await {
43                Ok(response) if response.status().is_success() => {
44                    info!("API health check passed");
45                    return Ok(());
46                },
47                Ok(response) => {
48                    let remaining = self.max_retries - attempt - 1;
49                    warn!(
50                        attempt = attempt + 1,
51                        max_retries = self.max_retries,
52                        status = %response.status(),
53                        retry_delay_secs = self.retry_delay.as_secs(),
54                        retries_remaining = remaining,
55                        "Health check failed, retrying"
56                    );
57                },
58                Err(e) => {
59                    let remaining = self.max_retries - attempt - 1;
60                    warn!(
61                        attempt = attempt + 1,
62                        max_retries = self.max_retries,
63                        error = %e,
64                        retry_delay_secs = self.retry_delay.as_secs(),
65                        retries_remaining = remaining,
66                        "Health check failed, retrying"
67                    );
68                },
69            }
70        }
71
72        Err(anyhow!(
73            "Health check failed after {} attempts ({} seconds)",
74            self.max_retries,
75            self.max_retries * self.retry_delay.as_secs() as u32
76        ))
77    }
78}