use crate::{errors::HealthchecksConfigError, DEFAULT_USER_AGENT};
use std::result::Result;
use std::time::Duration;
use ureq::{Agent, AgentBuilder};
use uuid::Uuid;
const HEALTHCHECK_PING_URL: &str = "https://hc-ping.com";
const MAX_RETRIES: i8 = 20;
#[allow(clippy::module_name_repetitions)]
pub struct PingClient {
pub(crate) uuid: String,
pub(crate) user_agent: String,
pub(crate) ureq_agent: Agent,
pub(crate) api_url: String,
}
pub fn get_client(uuid: &str) -> Result<PingClient, HealthchecksConfigError> {
get_client_with_url(uuid, HEALTHCHECK_PING_URL)
}
pub fn get_client_with_url(
uuid: &str,
api_url: &str,
) -> Result<PingClient, HealthchecksConfigError> {
if Uuid::parse_str(uuid).is_err() {
Err(HealthchecksConfigError::InvalidUuid(uuid.to_string()))
} else if api_url.is_empty() {
Err(HealthchecksConfigError::EmptyApiUrl)
} else {
Ok(PingClient {
uuid: uuid.to_owned(),
user_agent: DEFAULT_USER_AGENT.to_string(),
ureq_agent: AgentBuilder::new().timeout(Duration::from_secs(5)).build(),
api_url: api_url.to_owned(),
})
}
}
fn maybe_add_run_id(url: String, run_id: Option<&Uuid>) -> String {
if let Some(rid) = run_id {
format!("{url}?rid={rid}")
} else {
url
}
}
impl PingClient {
#[must_use]
pub fn set_user_agent(mut self, user_agent: &str) -> PingClient {
user_agent.clone_into(&mut self.user_agent);
self
}
#[must_use]
pub fn report_success(&self) -> bool {
self.report_success_with_run_id(None)
}
#[must_use]
pub fn report_success_with_run_id(&self, run_id: Option<&Uuid>) -> bool {
let mut retries: i8 = 0;
let url = maybe_add_run_id(format!("{}/{}", self.api_url, self.uuid), run_id);
let request = self
.ureq_agent
.get(&url)
.set("User-Agent", &self.user_agent);
while retries < MAX_RETRIES {
let resp = request.clone().call();
if resp.is_ok() {
return true;
}
retries += 1;
}
if request.call().is_ok() {
return true;
}
false
}
#[must_use]
pub fn report_failure(&self) -> bool {
self.report_failure_with_run_id(None)
}
#[must_use]
pub fn report_failure_with_run_id(&self, run_id: Option<&Uuid>) -> bool {
let mut retries: i8 = 0;
let url = maybe_add_run_id(format!("{}/{}/fail", self.api_url, self.uuid), run_id);
let request = self
.ureq_agent
.get(&url)
.set("User-Agent", &self.user_agent);
while retries < MAX_RETRIES {
let resp = request.clone().call();
if resp.is_ok() {
return true;
}
retries += 1;
}
if request.call().is_ok() {
return true;
}
false
}
#[must_use]
pub fn report_failure_with_logs(&self, data: &str) -> bool {
self.report_failure_with_logs_and_run_id(data, None)
}
#[must_use]
pub fn report_failure_with_logs_and_run_id(&self, data: &str, run_id: Option<&Uuid>) -> bool {
let mut retries: i8 = 0;
let url = maybe_add_run_id(format!("{}/{}/fail", self.api_url, self.uuid), run_id);
let request = self
.ureq_agent
.post(&url)
.set("User-Agent", &self.user_agent);
while retries < MAX_RETRIES {
let resp = request.clone().send_string(data);
if resp.is_ok() {
return true;
}
retries += 1;
}
if request.send_string(data).is_ok() {
return true;
}
false
}
#[must_use]
pub fn start_timer(&self) -> bool {
self.start_timer_with_run_id(None)
}
#[must_use]
pub fn start_timer_with_run_id(&self, run_id: Option<&Uuid>) -> bool {
let mut retries: i8 = 0;
let url = maybe_add_run_id(format!("{}/{}/start", self.api_url, self.uuid), run_id);
let request = self
.ureq_agent
.get(&url)
.set("User-Agent", &self.user_agent);
while retries < MAX_RETRIES {
let resp = request.clone().call();
if resp.is_ok() {
return true;
}
retries += 1;
}
if request.call().is_ok() {
return true;
}
false
}
}