-
-
Notifications
You must be signed in to change notification settings - Fork 636
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add retries to NetDownload intrinsic. #16798
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -10,6 +10,8 @@ use bytes::{BufMut, Bytes}; | |||||
use futures::stream::StreamExt; | ||||||
use humansize::{file_size_opts, FileSize}; | ||||||
use reqwest::Error; | ||||||
use tokio_retry::strategy::{jitter, ExponentialBackoff}; | ||||||
use tokio_retry::RetryIf; | ||||||
use url::Url; | ||||||
|
||||||
use crate::context::Core; | ||||||
|
@@ -26,30 +28,41 @@ struct NetDownload { | |||||
|
||||||
impl NetDownload { | ||||||
async fn start(core: &Arc<Core>, url: Url, file_name: String) -> Result<NetDownload, String> { | ||||||
// TODO: Retry failures | ||||||
let response = core | ||||||
let try_download = || async { | ||||||
core | ||||||
.http_client | ||||||
.get(url.clone()) | ||||||
.send() | ||||||
.await | ||||||
.map_err(|err| format!("Error downloading file: {}", err))?; | ||||||
.map_err(|err| (format!("Error downloading file: {}", err), true)) | ||||||
.and_then(|res| | ||||||
// Handle common HTTP errors. | ||||||
if res.status().is_server_error() { | ||||||
Err((format!( | ||||||
"Server error ({}) downloading file {} from {}", | ||||||
res.status().as_str(), | ||||||
file_name, | ||||||
url, | ||||||
), true)) | ||||||
} else if res.status().is_client_error() { | ||||||
Err((format!( | ||||||
"Client error ({}) downloading file {} from {}", | ||||||
res.status().as_str(), | ||||||
file_name, | ||||||
url, | ||||||
), false)) | ||||||
} else { | ||||||
Ok(res) | ||||||
}) | ||||||
}; | ||||||
|
||||||
// TODO: Allow the retry strategy to be configurable? | ||||||
// For now we retry after 10ms, 100ms, 1s, and 10s. | ||||||
let retry_strategy = ExponentialBackoff::from_millis(10).map(jitter).take(4); | ||||||
let response = RetryIf::spawn(retry_strategy, try_download, |err: &(String, bool)| err.1) | ||||||
.await | ||||||
.map_err(|(err, _)| err)?; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As mentioned: I think it's totally fine to TODO making it configurable, but the error message should likely be enriched to give some information about the retries: i.e.:
Suggested change
...so that the next person who comes along has a clear hint of where to go looking if they want to add configurability. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree this would be nice but I'm not sure we have access to the true Instead of modifying this error, what do you think of adding logging to the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I just meant extracting the constant " There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ooooh. I see what you meant here. Was missing the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No problem, updated |
||||||
|
||||||
// Handle common HTTP errors. | ||||||
if response.status().is_server_error() { | ||||||
return Err(format!( | ||||||
"Server error ({}) downloading file {} from {}", | ||||||
response.status().as_str(), | ||||||
file_name, | ||||||
url, | ||||||
)); | ||||||
} else if response.status().is_client_error() { | ||||||
return Err(format!( | ||||||
"Client error ({}) downloading file {} from {}", | ||||||
response.status().as_str(), | ||||||
file_name, | ||||||
url, | ||||||
)); | ||||||
} | ||||||
let byte_stream = Pin::new(Box::new(response.bytes_stream())); | ||||||
Ok(NetDownload { | ||||||
stream: byte_stream, | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fine to leave as a TODO I think, assuming the error is enriched.