Add retry logic to metadata fetch, don't crash on 500

This commit is contained in:
Tyler Hallada 2021-07-25 18:03:54 -04:00
parent 39ae7703b0
commit 523f3eeb3f
2 changed files with 42 additions and 43 deletions

View File

@ -304,26 +304,13 @@ pub async fn main() -> Result<()> {
continue; continue;
} }
} else { } else {
warn!("file has no metadata link"); warn!("file has no metadata link, continuing with download");
} }
Ok(())
} }
Err(err) => { Err(err) => {
if let Some(reqwest_err) = err.downcast_ref::<reqwest::Error>() { warn!(error = %err, "error retreiving metadata for file, continuing with download");
if reqwest_err.status() == Some(StatusCode::NOT_FOUND) {
warn!(
status = ?reqwest_err.status(),
"metadata for file not found on server"
);
Ok(())
} else {
Err(err)
}
} else {
Err(err)
}
} }
}?; };
let download_link_resp = let download_link_resp =
nexus_api::download_link::get(&client, db_mod.nexus_mod_id, api_file.file_id) nexus_api::download_link::get(&client, db_mod.nexus_mod_id, api_file.file_id)

View File

@ -2,7 +2,8 @@ use anyhow::{anyhow, Result};
use reqwest::Client; use reqwest::Client;
use serde_json::Value; use serde_json::Value;
use std::env; use std::env;
use tracing::{info, instrument}; use tokio::time::sleep;
use tracing::{info, instrument, warn};
use super::files::ApiFile; use super::files::ApiFile;
use super::USER_AGENT; use super::USER_AGENT;
@ -44,34 +45,45 @@ fn has_plugin(json: &Value) -> Result<bool> {
#[instrument(skip(client, api_file), fields(metadata_link = api_file.content_preview_link.unwrap_or("null")))] #[instrument(skip(client, api_file), fields(metadata_link = api_file.content_preview_link.unwrap_or("null")))]
pub async fn contains_plugin(client: &Client, api_file: &ApiFile<'_>) -> Result<Option<bool>> { pub async fn contains_plugin(client: &Client, api_file: &ApiFile<'_>) -> Result<Option<bool>> {
if let Some(metadata_link) = api_file.content_preview_link { for attempt in 1..=3 {
let res = client if let Some(metadata_link) = api_file.content_preview_link {
.get(metadata_link) let res = match client
.header("accept", "application/json") .get(metadata_link)
.header("apikey", env::var("NEXUS_API_KEY")?) .header("accept", "application/json")
.header("user-agent", USER_AGENT) .header("apikey", env::var("NEXUS_API_KEY")?)
.send() .header("user-agent", USER_AGENT)
.await? .send()
.error_for_status()?; .await?
.error_for_status()
info!(status = %res.status(), "fetched file metadata from API"); {
let json = res.json::<Value>().await?; Ok(res) => res,
Err(err) => {
match json.get("children") { warn!(error = %err, attempt, "Failed to get metadata for file, trying again after 1 second");
None => Ok(Some(false)), sleep(std::time::Duration::from_secs(1)).await;
Some(children) => { continue;
let children = children }
.as_array() };
.ok_or_else(|| anyhow!("children value in metadata is not an array"))?;
for child in children { info!(status = %res.status(), "fetched file metadata from API");
if has_plugin(child)? { let json = res.json::<Value>().await?;
return Ok(Some(true));
} match json.get("children") {
None => return Ok(Some(false)),
Some(children) => {
let children = children
.as_array()
.ok_or_else(|| anyhow!("children value in metadata is not an array"))?;
for child in children {
if has_plugin(child)? {
return Ok(Some(true));
}
}
return Ok(Some(false));
} }
Ok(Some(false))
} }
} else {
return Ok(None);
} }
} else {
Ok(None)
} }
Err(anyhow!("Failed to get metadata for file in three attempts"))
} }