Skip to content

Commit 7a36fcc

Browse files
committed
Report retry count on Ok results
Report retry count on `Ok` results that underwent retries through a `RetryCount` response extension, so that users can include the retry count in error messages. We discovered in uv that we were not reporting retries for status code errors. This change does for `Ok` results what #159 did for `Err` results.
1 parent 591ab44 commit 7a36fcc

File tree

4 files changed

+41
-7
lines changed

4 files changed

+41
-7
lines changed

reqwest-retry/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased]
88

9+
### Added
10+
- Report retry count on `Ok` results that underwent retries through a `RetryCount` response extension.
11+
912
## [0.7.0] - 2024-11-08
1013

1114
### Breaking changes

reqwest-retry/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ mod retryable_strategy;
3232
pub use retry_policies::{policies, Jitter, RetryDecision, RetryPolicy};
3333
use thiserror::Error;
3434

35-
pub use middleware::RetryTransientMiddleware;
35+
pub use middleware::{RetryCount, RetryTransientMiddleware};
3636
pub use retryable::Retryable;
3737
pub use retryable_strategy::{
3838
default_on_request_failure, default_on_request_success, DefaultRetryableStrategy,

reqwest-retry/src/middleware.rs

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -184,20 +184,51 @@ where
184184
}
185185
};
186186

187-
// Report whether we failed with or without retries.
188187
break if n_past_retries > 0 {
189-
result.map_err(|err| {
190-
Error::Middleware(
188+
// Both `Ok` results (e.g. status code errors) and `Err` results (e.g. an
189+
// `io::Error` for from connection reset), and we want to inform the user about the
190+
// retries in both cases.
191+
match result {
192+
Ok(mut response) => {
193+
response
194+
.extensions_mut()
195+
.insert(RetryCount::new(n_past_retries));
196+
Ok(response)
197+
}
198+
Err(err) => Err(Error::Middleware(
191199
RetryError::WithRetries {
192200
retries: n_past_retries,
193201
err,
194202
}
195203
.into(),
196-
)
197-
})
204+
)),
205+
}
198206
} else {
199207
result.map_err(|err| Error::Middleware(RetryError::Error(err).into()))
200208
};
201209
}
202210
}
203211
}
212+
213+
/// Extension type to store retry count in a response.
214+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
215+
pub struct RetryCount(u32);
216+
217+
impl RetryCount {
218+
/// Create a new retry count.
219+
pub fn new(count: u32) -> Self {
220+
Self(count)
221+
}
222+
223+
pub fn value(self) -> u32 {
224+
self.0
225+
}
226+
}
227+
228+
impl std::ops::Deref for RetryCount {
229+
type Target = u32;
230+
231+
fn deref(&self) -> &Self::Target {
232+
&self.0
233+
}
234+
}

reqwest-retry/tests/all/helpers/simple_server.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ impl SimpleServer {
126126

127127
/// Parses the request line and checks that it contains the method, uri and http_version parts.
128128
/// It does not check if the content of the checked parts is correct. It just checks the format (it contains enough parts) of the request.
129-
fn parse_request_line(request: &str) -> Result<Request, Box<dyn Error>> {
129+
fn parse_request_line(request: &str) -> Result<Request<'_>, Box<dyn Error>> {
130130
let mut parts = request.split_whitespace();
131131

132132
let method = parts.next().ok_or("Method not specified")?;

0 commit comments

Comments
 (0)