feat: refactor stage 1
This commit is contained in:
+50
-12
@@ -85,8 +85,12 @@ pub async fn fetch_and_run(
|
||||
}
|
||||
}
|
||||
let timeout_ms = monitor.timeout_ms.unwrap_or(30000);
|
||||
let deadline = std::time::Duration::from_millis(timeout_ms + 5000);
|
||||
let result = match tokio::time::timeout(deadline, run_check(&client, &monitor, scheduled_at_iso.clone(), ®ion_owned, &run_id_owned)).await {
|
||||
let attempts = monitor.max_retries.saturating_add(1) as u64;
|
||||
let retry_gap_s = monitor.retry_interval_s;
|
||||
let deadline = std::time::Duration::from_millis(
|
||||
attempts * (timeout_ms + 5000) + attempts.saturating_sub(1) * retry_gap_s * 1000,
|
||||
);
|
||||
let result = match tokio::time::timeout(deadline, run_check_with_retries(&client, &monitor, scheduled_at_iso.clone(), ®ion_owned, &run_id_owned)).await {
|
||||
Ok(r) => r,
|
||||
Err(_) => PingResult {
|
||||
monitor_id: monitor.id.clone(),
|
||||
@@ -113,6 +117,35 @@ pub async fn fetch_and_run(
|
||||
Ok(spawned)
|
||||
}
|
||||
|
||||
async fn run_check_with_retries(client: &reqwest::Client, monitor: &Monitor, scheduled_at: Option<String>, region: &str, run_id: &str) -> PingResult {
|
||||
let attempts = monitor.max_retries.saturating_add(1);
|
||||
let retry_gap = std::time::Duration::from_secs(monitor.retry_interval_s);
|
||||
let mut last: Option<PingResult> = None;
|
||||
for attempt in 0..attempts {
|
||||
let mut result = run_check(client, monitor, scheduled_at.clone(), region, run_id).await;
|
||||
if result.up {
|
||||
if attempt > 0 {
|
||||
if let Some(meta) = result.meta.as_mut().and_then(|m| m.as_object_mut()) {
|
||||
meta.insert("retries".into(), json!(attempt));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
last = Some(result);
|
||||
if attempt + 1 < attempts {
|
||||
tokio::time::sleep(retry_gap).await;
|
||||
}
|
||||
}
|
||||
let mut result = last.expect("at least one attempt");
|
||||
if attempts > 1 {
|
||||
let meta = result.meta.get_or_insert_with(|| json!({}));
|
||||
if let Some(obj) = meta.as_object_mut() {
|
||||
obj.insert("retries".into(), json!(attempts - 1));
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
async fn run_check(client: &reqwest::Client, monitor: &Monitor, scheduled_at: Option<String>, region: &str, run_id: &str) -> PingResult {
|
||||
let checked_at = chrono::Utc::now().to_rfc3339();
|
||||
let jitter_ms: Option<i64> = scheduled_at.as_deref().and_then(|s| {
|
||||
@@ -203,7 +236,7 @@ async fn run_check(client: &reqwest::Client, monitor: &Monitor, scheduled_at: Op
|
||||
}
|
||||
}
|
||||
} else {
|
||||
(status < 400, None)
|
||||
((200..300).contains(&status), None)
|
||||
};
|
||||
|
||||
let cert_expiry_days = match cert_handle {
|
||||
@@ -304,15 +337,20 @@ fn run_check_blocking(
|
||||
resp_headers.insert(name.as_str().to_lowercase(), value.to_str().unwrap_or("").to_string());
|
||||
}
|
||||
|
||||
const MAX_BODY: usize = 10 * 1024 * 1024;
|
||||
let body_str = match resp.body_mut().read_to_string() {
|
||||
Ok(s) => s,
|
||||
Err(e) => format!("[failed to read body: {}]", e),
|
||||
};
|
||||
let body_out = if body_str.len() > MAX_BODY {
|
||||
format!("[body truncated: {} bytes]", body_str.len())
|
||||
} else {
|
||||
body_str
|
||||
const MAX_BODY: usize = 2 * 1024 * 1024;
|
||||
let body_out = match resp.body_mut().with_config().limit((MAX_BODY + 1) as u64).read_to_vec() {
|
||||
Ok(mut buf) => {
|
||||
if buf.len() > MAX_BODY { buf.truncate(MAX_BODY); }
|
||||
String::from_utf8_lossy(&buf).into_owned()
|
||||
}
|
||||
Err(e) => {
|
||||
let msg = e.to_string();
|
||||
if msg.contains("limit") || msg.contains("Limit") {
|
||||
format!("[body exceeded {}-byte cap]", MAX_BODY)
|
||||
} else {
|
||||
format!("[failed to read body: {}]", e)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ok((status, resp_headers, body_out))
|
||||
|
||||
@@ -23,6 +23,10 @@ pub struct Monitor {
|
||||
pub request_body: Option<String>,
|
||||
pub timeout_ms: Option<u64>,
|
||||
pub interval_s: i64,
|
||||
#[serde(default)]
|
||||
pub max_retries: u32,
|
||||
#[serde(default)]
|
||||
pub retry_interval_s: u64,
|
||||
pub query: Option<Value>,
|
||||
pub scheduled_at: Option<String>, // ISO string for backward compat in PingResult
|
||||
#[serde(deserialize_with = "deserialize_ms")]
|
||||
|
||||
Reference in New Issue
Block a user