fc-common: properly implement GitHub API rate limiting; cleanup
More or less mimics Hydra's `GithubStatus.pm` adaptive throttling: - Log rate limit status when remaining <= 2000 - Sleep when remaining <= 1000 Adaptive delay spreads requests over reset window. Rate limits are extracted from *every response* for better accuracy. Accuracy is *critical* because the primary failure is to get rate limited more often due to miscalculation. Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I3b1fa444c937715c604002d71510bcf76a6a6964
This commit is contained in:
parent
4050de5b4e
commit
92844d302e
1 changed files with 38 additions and 3 deletions
|
|
@ -1,6 +1,9 @@
|
|||
//! Notification dispatch for build events
|
||||
|
||||
use std::sync::OnceLock;
|
||||
use std::{
|
||||
sync::OnceLock,
|
||||
time::{SystemTime, UNIX_EPOCH},
|
||||
};
|
||||
|
||||
use sqlx::PgPool;
|
||||
use tracing::{error, info, warn};
|
||||
|
|
@ -475,13 +478,45 @@ async fn set_github_status(
|
|||
.await
|
||||
{
|
||||
Ok(resp) => {
|
||||
if resp.status().is_success() {
|
||||
let is_success = resp.status().is_success();
|
||||
let status = resp.status();
|
||||
|
||||
// Extract rate limit state from response headers before consuming body
|
||||
let rate_limit = extract_rate_limit_from_headers(resp.headers());
|
||||
|
||||
if is_success {
|
||||
info!(build_id = %build.id, "Set GitHub commit status: {state}");
|
||||
} else {
|
||||
let status = resp.status();
|
||||
let text = resp.text().await.unwrap_or_default();
|
||||
warn!("GitHub status API returned {status}: {text}");
|
||||
}
|
||||
|
||||
// Handle rate limiting based on extracted state
|
||||
if let Some(rate_limit) = rate_limit {
|
||||
let now = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs();
|
||||
|
||||
// Log when approaching limit (Hydra threshold: 2000)
|
||||
if rate_limit.remaining <= 2000 {
|
||||
let seconds_until_reset = rate_limit.reset_at.saturating_sub(now);
|
||||
info!(
|
||||
"GitHub rate limit: {}/{}, resets in {}s",
|
||||
rate_limit.remaining, rate_limit.limit, seconds_until_reset
|
||||
);
|
||||
}
|
||||
|
||||
// Sleep when critical (Hydra threshold: 1000)
|
||||
if rate_limit.remaining <= 1000 {
|
||||
let delay = calculate_delay(&rate_limit, now);
|
||||
warn!(
|
||||
"GitHub rate limit critical: {}/{}, sleeping {}s",
|
||||
rate_limit.remaining, rate_limit.limit, delay
|
||||
);
|
||||
tokio::time::sleep(std::time::Duration::from_secs(delay)).await;
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(e) => error!("GitHub status API request failed: {e}"),
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue