From ec865ee9f4ab1cf21a3f6f85ecb46b6ac7a4cf23 Mon Sep 17 00:00:00 2001 From: Alexis Sellier Date: Sun, 4 Sep 2022 22:40:42 +0200 Subject: [PATCH] node: Improve fetch command Signed-off-by: Alexis Sellier --- node/src/protocol.rs | 93 +++++++++++++++++++++++--------------------- 1 file changed, 49 insertions(+), 44 deletions(-) diff --git a/node/src/protocol.rs b/node/src/protocol.rs index 66d25ebc..58376497 100644 --- a/node/src/protocol.rs +++ b/node/src/protocol.rs @@ -56,6 +56,8 @@ pub enum Event {} pub enum FetchError { #[error(transparent)] Git(#[from] git2::Error), + #[error(transparent)] + Storage(#[from] storage::Error), } /// Result of looking up providers in our routing table. @@ -66,6 +68,7 @@ pub enum FetchLookup { results: chan::Receiver, }, NotFound, + Error(FetchError), } /// Result of a fetch request from a specific provider. @@ -358,53 +361,55 @@ where Command::Connect(addr) => self.context.connect(addr), Command::Fetch(proj, resp) => { let providers = self.providers(&proj).collect::>(); - - if let Some(providers) = NonEmpty::from_vec(providers) { - log::debug!("Found {} providers for {}", providers.len(), proj); - - let (results_, results) = chan::bounded(providers.len()); - { - let (_, head) = &providers.head; - let tail = providers - .tail() - .iter() - .map(|(_, peer)| peer.addr) - .collect::>(); - - resp.send(FetchLookup::Found { - providers: NonEmpty::from((head.addr, tail)), - results, - }) - .ok(); - } - - let mut repo = self.storage.repository(&proj).unwrap(); - // TODO: Limit the number of providers we fetch from? Randomize? - for (_, peer) in providers { - match repo.fetch(&Url { - scheme: git_url::Scheme::Git, - host: Some(peer.addr.ip().to_string()), - port: Some(peer.addr.port()), - // TODO: Fix upstream crate so that it adds a `/` when needed. - path: format!("/{}", proj).into(), - ..Url::default() - }) { - Ok(()) => { - results_.send(FetchResult::Fetched { from: peer.addr }).ok(); - } - Err(err) => { - results_ - .send(FetchResult::Error { - from: peer.addr, - error: err.into(), - }) - .ok(); - } - } - } + let providers = if let Some(providers) = NonEmpty::from_vec(providers) { + providers } else { log::error!("No providers found for {}", proj); resp.send(FetchLookup::NotFound).ok(); + + return; + }; + log::debug!("Found {} providers for {}", providers.len(), proj); + + let mut repo = match self.storage.repository(&proj) { + Ok(repo) => repo, + Err(err) => { + log::error!("Error opening repo for {}: {}", proj, err); + resp.send(FetchLookup::Error(err.into())).ok(); + + return; + } + }; + + let (results_, results) = chan::bounded(providers.len()); + resp.send(FetchLookup::Found { + providers: providers.clone().map(|(_, peer)| peer.addr), + results, + }) + .ok(); + + // TODO: Limit the number of providers we fetch from? Randomize? + for (_, peer) in providers { + match repo.fetch(&Url { + scheme: git_url::Scheme::Git, + host: Some(peer.addr.ip().to_string()), + port: Some(peer.addr.port()), + // TODO: Fix upstream crate so that it adds a `/` when needed. + path: format!("/{}", proj).into(), + ..Url::default() + }) { + Ok(()) => { + results_.send(FetchResult::Fetched { from: peer.addr }).ok(); + } + Err(err) => { + results_ + .send(FetchResult::Error { + from: peer.addr, + error: err.into(), + }) + .ok(); + } + } } } Command::AnnounceRefsUpdate(proj) => {