Add iteration functions to `AddressBook`.

The disconnected_peers() function allows us to prevent duplicate
connections without maintaining shared state between the peerset and the
dial-additional-peers task.
This commit is contained in:
Henry de Valence 2019-10-17 16:25:24 -07:00 committed by Deirdre Connolly
parent b03a83fa86
commit 0bfd57def2
2 changed files with 38 additions and 12 deletions

View File

@ -28,21 +28,12 @@ impl AddressBook {
/// Update the address book with `event`, a [`MetaAddr`] representing
/// observation of a peer.
pub fn update(&mut self, event: MetaAddr) {
use chrono::Duration as CD;
use std::collections::hash_map::Entry;
trace!(
debug!(
?event,
data.total = self.by_time.len(),
// This would be cleaner if it used "variables" but keeping
// it inside the trace! invocation prevents running the range
// query unless the output will actually be used.
data.recent = self
.by_time
.range(
(Utc::now() - CD::from_std(constants::LIVE_PEER_DURATION).unwrap())..Utc::now()
)
.count()
data.recent = (self.by_time.len() - self.disconnected_peers().count()),
);
let MetaAddr {
@ -73,4 +64,39 @@ impl AddressBook {
}
}
}
/// Return an iterator over all peers, ordered from most recently seen to
/// least recently seen.
pub fn peers<'a>(&'a self) -> impl Iterator<Item = MetaAddr> + 'a {
self.by_time.iter().rev().map(from_by_time_kv)
}
/// Return an iterator over peers known to be disconnected, ordered from most
/// recently seen to least recently seen.
pub fn disconnected_peers<'a>(&'a self) -> impl Iterator<Item = MetaAddr> + 'a {
use chrono::Duration as CD;
use std::ops::Bound::{Excluded, Unbounded};
// LIVE_PEER_DURATION represents the time interval in which we are
// guaranteed to receive at least one message from a peer or close the
// connection. Therefore, if the last-seen timestamp is older than
// LIVE_PEER_DURATION ago, we know we must have disconnected from it.
let cutoff = Utc::now() - CD::from_std(constants::LIVE_PEER_DURATION).unwrap();
self.by_time
.range((Unbounded, Excluded(cutoff)))
.rev()
.map(from_by_time_kv)
}
}
// Helper impl to convert by_time Iterator Items back to MetaAddrs
// This could easily be a From impl, but trait impls are public, and this shouldn't be.
fn from_by_time_kv(by_time_kv: (&DateTime<Utc>, &(SocketAddr, PeerServices))) -> MetaAddr {
let (last_seen, (addr, services)) = by_time_kv;
MetaAddr {
last_seen: last_seen.clone(),
addr: addr.clone(),
services: services.clone(),
}
}

View File

@ -108,7 +108,7 @@ impl ConnectCmd {
addrs.into_iter().map(|meta| meta.addr).collect::<Vec<_>>()
};
let (mut peer_set, _address_book) = zebra_network::init(config, node);
let (mut peer_set, address_book) = zebra_network::init(config, node);
info!("waiting for peer_set ready");
peer_set.ready().await.map_err(Error::from_boxed_compat)?;