Skip to content

Commit 4fe2183

Browse files
authored
Merge pull request #1820 from ehuss/fix-retry
Adjust GitHub rate limiting behavior.
2 parents 54cd575 + e5e4c92 commit 4fe2183

File tree

2 files changed

+21
-10
lines changed

2 files changed

+21
-10
lines changed

src/actions.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ pub fn to_human(d: DateTime<Utc>) -> String {
108108
#[async_trait]
109109
impl<'a> Action for Step<'a> {
110110
async fn call(&self) -> anyhow::Result<String> {
111-
let gh = GithubClient::new_from_env();
111+
let mut gh = GithubClient::new_from_env();
112+
gh.set_retry_rate_limit(true);
112113

113114
let mut context = Context::new();
114115
let mut results = HashMap::new();

src/github.rs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@ impl GithubClient {
3131
.with_context(|| format!("building reqwest {}", req_dbg))?;
3232

3333
let mut resp = self.client.execute(req.try_clone().unwrap()).await?;
34-
if let Some(sleep) = Self::needs_retry(&resp).await {
35-
resp = self.retry(req, sleep, MAX_ATTEMPTS).await?;
34+
if self.retry_rate_limit {
35+
if let Some(sleep) = Self::needs_retry(&resp).await {
36+
resp = self.retry(req, sleep, MAX_ATTEMPTS).await?;
37+
}
3638
}
3739
let maybe_err = resp.error_for_status_ref().err();
3840
let body = resp
@@ -51,7 +53,10 @@ impl GithubClient {
5153
const REMAINING: &str = "X-RateLimit-Remaining";
5254
const RESET: &str = "X-RateLimit-Reset";
5355

54-
if resp.status().is_success() {
56+
if !matches!(
57+
resp.status(),
58+
StatusCode::FORBIDDEN | StatusCode::TOO_MANY_REQUESTS
59+
) {
5560
return None;
5661
}
5762

@@ -60,12 +65,6 @@ impl GithubClient {
6065
return None;
6166
}
6267

63-
// Weird github api behavior. It asks us to retry but also has a remaining count above 1
64-
// Try again immediately and hope for the best...
65-
if headers[REMAINING] != "0" {
66-
return Some(Duration::from_secs(0));
67-
}
68-
6968
let reset_time = headers[RESET].to_str().unwrap().parse::<u64>().unwrap();
7069
Some(Duration::from_secs(Self::calc_sleep(reset_time) + 10))
7170
}
@@ -2149,6 +2148,8 @@ pub struct GithubClient {
21492148
api_url: String,
21502149
graphql_url: String,
21512150
raw_url: String,
2151+
/// If `true`, requests will sleep if it hits GitHub's rate limit.
2152+
retry_rate_limit: bool,
21522153
}
21532154

21542155
impl GithubClient {
@@ -2159,6 +2160,7 @@ impl GithubClient {
21592160
api_url,
21602161
graphql_url,
21612162
raw_url,
2163+
retry_rate_limit: false,
21622164
}
21632165
}
21642166

@@ -2174,6 +2176,14 @@ impl GithubClient {
21742176
)
21752177
}
21762178

2179+
/// Sets whether or not this client will retry when it hits GitHub's rate limit.
2180+
///
2181+
/// Just beware that the retry may take a long time (like 30 minutes,
2182+
/// depending on various factors).
2183+
pub fn set_retry_rate_limit(&mut self, retry: bool) {
2184+
self.retry_rate_limit = retry;
2185+
}
2186+
21772187
pub fn raw(&self) -> &Client {
21782188
&self.client
21792189
}

0 commit comments

Comments
 (0)