node: Only try to fetch from connected nodes
This commit is contained in:
parent
ac23f45d9b
commit
be77eebc3d
|
|
@ -394,36 +394,44 @@ where
|
||||||
|
|
||||||
match cmd {
|
match cmd {
|
||||||
Command::Connect(id, addr) => self.reactor.connect(id, addr),
|
Command::Connect(id, addr) => self.reactor.connect(id, addr),
|
||||||
Command::Fetch(id, resp) => {
|
Command::Fetch(rid, resp) => {
|
||||||
if !self
|
if !self
|
||||||
.tracking
|
.tracking
|
||||||
.is_repo_tracked(&id)
|
.is_repo_tracked(&rid)
|
||||||
.expect("Service::command: error accessing tracking configuration")
|
.expect("Service::command: error accessing tracking configuration")
|
||||||
{
|
{
|
||||||
resp.send(FetchLookup::NotTracking).ok();
|
resp.send(FetchLookup::NotTracking).ok();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let seeds = match self.routing.get(&id) {
|
let (connected, unconnected) = match self.routing.get(&rid) {
|
||||||
Ok(seeds) => seeds
|
Ok(seeds) => seeds
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|node| *node != self.node_id())
|
.filter(|node| *node != self.node_id())
|
||||||
.collect(),
|
.partition::<Vec<_>, _>(|node| self.sessions.is_negotiated(node)),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!(target: "service", "Error reading routing table for {id}: {err}");
|
error!(target: "service", "Error reading routing table for {rid}: {err}");
|
||||||
resp.send(FetchLookup::NotFound).ok();
|
resp.send(FetchLookup::NotFound).ok();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(seeds) = NonEmpty::from_vec(seeds) else {
|
debug!(
|
||||||
warn!(target: "service", "No seeds found to fetch from, for {}", id);
|
target: "service",
|
||||||
|
"Found {} connected seed(s) and {} unconnected seed(s) for {}",
|
||||||
|
connected.len(), unconnected.len(), rid
|
||||||
|
);
|
||||||
|
|
||||||
|
let Some(seeds) = NonEmpty::from_vec(connected) else {
|
||||||
|
warn!(target: "service", "No connected seeds found for {}", rid);
|
||||||
resp.send(FetchLookup::NotFound).ok();
|
resp.send(FetchLookup::NotFound).ok();
|
||||||
|
|
||||||
|
// TODO: Establish connections to unconnected seeds, and retry.
|
||||||
|
// TODO: Fetch requests should be queued and re-checked to see if they can
|
||||||
|
// be fulfilled everytime a new node connects.
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
debug!(target: "service", "Found {} seed(s) to fetch from, for {}", seeds.len(), id);
|
|
||||||
|
|
||||||
let (results_send, results) = chan::bounded(seeds.len());
|
let (results_send, results) = chan::bounded(seeds.len());
|
||||||
resp.send(FetchLookup::Found {
|
resp.send(FetchLookup::Found {
|
||||||
|
|
@ -432,15 +440,11 @@ where
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
self.fetch_reqs.insert(id, results_send);
|
self.fetch_reqs.insert(rid, results_send);
|
||||||
|
|
||||||
// TODO: Limit the number of seeds we fetch from? Randomize?
|
// TODO: Limit the number of seeds we fetch from? Randomize?
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
if let Some(session) = self.sessions.get_mut(&seed) {
|
self.fetch(rid, &seed);
|
||||||
Self::fetch(id, session, &mut self.reactor);
|
|
||||||
} else {
|
|
||||||
// TODO: Establish connection?
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Command::TrackRepo(id, resp) => {
|
Command::TrackRepo(id, resp) => {
|
||||||
|
|
@ -480,17 +484,24 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fetch(rid: Id, session: &mut Session, reactor: &mut Reactor) {
|
pub fn fetch(&mut self, rid: Id, from: &NodeId) {
|
||||||
|
let Some(session) = self.sessions.get_mut(from) else {
|
||||||
|
error!(target: "service", "Session {from} does not exist; cannot initiate fetch");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
debug_assert!(session.is_negotiated());
|
||||||
|
|
||||||
let seed = session.id;
|
let seed = session.id;
|
||||||
|
|
||||||
if let Some(fetch) = session.fetch(rid) {
|
if let Some(fetch) = session.fetch(rid) {
|
||||||
debug!(target: "service", "Fetch initiated for {rid} with {seed}..");
|
debug!(target: "service", "Fetch initiated for {rid} with {seed}..");
|
||||||
|
|
||||||
reactor.write(session.id, fetch);
|
self.reactor.write(session.id, fetch);
|
||||||
} else {
|
} else {
|
||||||
// TODO: If we can't fetch, it's because we're already fetching from
|
// TODO: If we can't fetch, it's because we're already fetching from
|
||||||
// this peer. So we need to queue the request, or find another peer.
|
// this peer. So we need to queue the request, or find another peer.
|
||||||
error!(target: "service",
|
error!(
|
||||||
|
target: "service",
|
||||||
"Unable to fetch {rid} from peer {seed} that is already being fetched from"
|
"Unable to fetch {rid} from peer {seed} that is already being fetched from"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -747,10 +758,7 @@ where
|
||||||
// Refs are only supposed to be relayed by peers who are tracking
|
// Refs are only supposed to be relayed by peers who are tracking
|
||||||
// the resource. Therefore, it's safe to fetch from the remote
|
// the resource. Therefore, it's safe to fetch from the remote
|
||||||
// peer, even though it isn't the announcer.
|
// peer, even though it isn't the announcer.
|
||||||
let Some(session) = self.sessions.get_mut(relayer) else {
|
self.fetch(message.id, relayer);
|
||||||
panic!(); // TODO
|
|
||||||
};
|
|
||||||
Self::fetch(message.id, session, &mut self.reactor);
|
|
||||||
|
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1322,6 +1330,11 @@ impl Sessions {
|
||||||
pub fn negotiated_mut(&mut self) -> impl Iterator<Item = (&NodeId, &mut Session)> {
|
pub fn negotiated_mut(&mut self) -> impl Iterator<Item = (&NodeId, &mut Session)> {
|
||||||
self.0.iter_mut().filter(move |(_, p)| p.is_connected())
|
self.0.iter_mut().filter(move |(_, p)| p.is_connected())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return whether this node has a fully established session.
|
||||||
|
pub fn is_negotiated(&self, id: &NodeId) -> bool {
|
||||||
|
self.0.get(id).map(|s| s.is_connected()).unwrap_or(false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for Sessions {
|
impl Deref for Sessions {
|
||||||
|
|
|
||||||
|
|
@ -136,6 +136,16 @@ impl Session {
|
||||||
matches!(self.state, State::Connected { .. })
|
matches!(self.state, State::Connected { .. })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_negotiated(&self) -> bool {
|
||||||
|
matches!(
|
||||||
|
self.state,
|
||||||
|
State::Connected {
|
||||||
|
initialized: true,
|
||||||
|
..
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn attempts(&self) -> usize {
|
pub fn attempts(&self) -> usize {
|
||||||
self.attempts
|
self.attempts
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue