@@ -26,29 +26,43 @@ pub fn build_client() -> Result<reqwest::Client, crate::error::GwsError> {
2626 } )
2727}
2828
29- /// Send an HTTP request with automatic retry on 429 (rate limit) responses.
29+ /// Send an HTTP request with automatic retry on 429 (rate limit) responses
30+ /// and transient connection/timeout errors.
3031/// Respects the `Retry-After` header; falls back to exponential backoff (1s, 2s, 4s).
3132pub async fn send_with_retry (
3233 build_request : impl Fn ( ) -> reqwest:: RequestBuilder ,
3334) -> Result < reqwest:: Response , reqwest:: Error > {
34- for attempt in 0 ..MAX_RETRIES {
35- let resp = build_request ( ) . send ( ) . await ?;
35+ let mut last_err: Option < reqwest:: Error > = None ;
3636
37- if resp. status ( ) != reqwest:: StatusCode :: TOO_MANY_REQUESTS {
38- return Ok ( resp) ;
37+ for attempt in 0 ..MAX_RETRIES {
38+ match build_request ( ) . send ( ) . await {
39+ Ok ( resp) => {
40+ if resp. status ( ) != reqwest:: StatusCode :: TOO_MANY_REQUESTS {
41+ return Ok ( resp) ;
42+ }
43+
44+ let header_value = resp
45+ . headers ( )
46+ . get ( "retry-after" )
47+ . and_then ( |v| v. to_str ( ) . ok ( ) ) ;
48+ let retry_after = compute_retry_delay ( header_value, attempt) ;
49+ tokio:: time:: sleep ( std:: time:: Duration :: from_secs ( retry_after) ) . await ;
50+ }
51+ Err ( e) if e. is_connect ( ) || e. is_timeout ( ) => {
52+ // Transient network error — retry with exponential backoff
53+ let delay = compute_retry_delay ( None , attempt) ;
54+ tokio:: time:: sleep ( std:: time:: Duration :: from_secs ( delay) ) . await ;
55+ last_err = Some ( e) ;
56+ }
57+ Err ( e) => return Err ( e) ,
3958 }
40-
41- let header_value = resp
42- . headers ( )
43- . get ( "retry-after" )
44- . and_then ( |v| v. to_str ( ) . ok ( ) ) ;
45- let retry_after = compute_retry_delay ( header_value, attempt) ;
46-
47- tokio:: time:: sleep ( std:: time:: Duration :: from_secs ( retry_after) ) . await ;
4859 }
4960
5061 // Final attempt — return whatever we get
51- build_request ( ) . send ( ) . await
62+ match build_request ( ) . send ( ) . await {
63+ Ok ( resp) => Ok ( resp) ,
64+ Err ( e) => Err ( last_err. unwrap_or ( e) ) ,
65+ }
5266}
5367
5468/// Compute the retry delay from a Retry-After header value and attempt number.
0 commit comments