| 437 | 437 | | None => (None, None, None), |
| 438 | 438 | | }, |
| 439 | 439 | | Ok(None) => (None, Some("The dependency update file is missing or has problems.".to_owned()), None), |
| 440 | | − | Err(error) => (None, Some(format!("The dependency update file could not be read: {error}")), None), |
| 440 | + | Err(error) => (None, Some(format!("The dependency update file could not be read: {error}")), Some(config_retry_at(now_ms()))), |
| 441 | 441 | | }; |
| 442 | 442 | | self.store.finish_run(&repo.repo_id, entry_id, next.as_deref(), result.as_deref(), error.as_deref()).await |
| 443 | 443 | | } |
| ⋯ |
| 458 | 458 | | if !entry.supported { |
| 459 | 459 | | return Ok(Outcome::fail(FailureCode::Invalid, format!("g1t does not open version updates for {} yet.", entry.ecosystem))); |
| 460 | 460 | | } |
| 461 | + | // Read the previous schedule before claiming, so a failed read cannot strand the claim. |
| 462 | + | let mut next = self.store.runs(&repo.repo_id).await?.into_iter().find(|run| run.entry == a.entry).and_then(|run| run.next_run_at); |
| 461 | 463 | | if !self.store.claim_run(&repo.repo_id, &a.entry).await? { |
| 462 | 464 | | return Ok(Outcome::fail(FailureCode::Conflict, "This entry is being checked now.")); |
| 463 | 465 | | } |
| 464 | 466 | | // Claimed: run_claimed would claim again, so run it here. |
| 465 | | − | let loaded = self.load_config(&repo).await?; |
| 466 | | − | let (result, error) = match loaded.as_ref().and_then(|loaded| loaded.config.updates.iter().find(|entry| entry.id() == a.entry).map(|entry| (loaded, entry))) { |
| 467 | | − | Some((loaded, entry)) => match self.run_entry(&repo, loaded, entry).await { |
| 468 | | − | Ok(Ok(summary)) => (Some(summary), None), |
| 469 | | − | Ok(Err(problem)) => (None, Some(problem)), |
| 470 | | − | Err(error) => (None, Some(format!("The check could not finish: {error}"))), |
| 467 | + | let (result, error) = match self.load_config(&repo).await { |
| 468 | + | Ok(loaded) => match loaded.as_ref().and_then(|loaded| loaded.config.updates.iter().find(|entry| entry.id() == a.entry).map(|entry| (loaded, entry))) { |
| 469 | + | Some((loaded, entry)) => match self.run_entry(&repo, loaded, entry).await { |
| 470 | + | Ok(Ok(summary)) => (Some(summary), None), |
| 471 | + | Ok(Err(problem)) => (None, Some(problem)), |
| 472 | + | Err(error) => (None, Some(format!("The check could not finish: {error}"))), |
| 473 | + | }, |
| 474 | + | None => (None, Some("The dependency update file is missing or has problems.".to_owned())), |
| 471 | 475 | | }, |
| 472 | | − | None => (None, Some("The dependency update file is missing or has problems.".to_owned())), |
| 476 | + | Err(error) => { |
| 477 | + | // Finish the claim even when the repository service is unavailable. |
| 478 | + | next = Some(config_retry_at(now_ms())); |
| 479 | + | (None, Some(format!("The dependency update file could not be read: {error}"))) |
| 480 | + | } |
| 473 | 481 | | }; |
| 474 | | − | let next = self |
| 475 | | − | .store |
| 476 | | − | .runs(&repo.repo_id) |
| 477 | | − | .await? |
| 478 | | − | .into_iter() |
| 479 | | − | .find(|run| run.entry == a.entry) |
| 480 | | − | .and_then(|run| run.next_run_at); |
| 481 | 482 | | self.store.finish_run(&repo.repo_id, &a.entry, next.as_deref(), result.as_deref(), error.as_deref()).await?; |
| 482 | 483 | | Ok(Outcome::Ok(self.version_updates_view(&repo).await?)) |
| 483 | 484 | | } |
| ⋯ |
| 1667 | 1668 | | assert_eq!(package_ecosystem("crates.io"), Some("cargo")); |
| 1668 | 1669 | | } |
| 1669 | 1670 | | } |
| 1671 | + | |
| 1672 | + | /// A transient repository read failure retries soon instead of losing its schedule. |
| 1673 | + | fn config_retry_at(now: u64) -> String { |
| 1674 | + | rfc3339(now.saturating_add(5 * 60 * 1000)) |
| 1675 | + | } |
| 1676 | + | |
| 1677 | + | #[cfg(test)] |
| 1678 | + | mod config_retry_tests { |
| 1679 | + | use super::*; |
| 1680 | + | |
| 1681 | + | #[test] |
| 1682 | + | fn failed_config_reads_retry_in_five_minutes() { |
| 1683 | + | let now = 1_700_000_000_000; |
| 1684 | + | assert_eq!(parse_rfc3339(&config_retry_at(now)), Some(now + 300_000)); |
| 1685 | + | } |
| 1686 | + | } |