Skip to content

Commit

Permalink
Merge pull request #2467 from maqi/rename_continuous_bootstrap
Browse files Browse the repository at this point in the history
chore(node): rename continuous bootstrap to network discover
  • Loading branch information
maqi authored Nov 27, 2024
2 parents fd4db21 + 6c8d9fb commit 52db692
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 48 deletions.
85 changes: 44 additions & 41 deletions sn_networking/src/bootstrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,37 +12,37 @@ use tokio::time::Duration;

use crate::target_arch::{interval, Instant, Interval};

/// The default interval at which NetworkDiscovery is triggered. The interval is increased as more peers are added to the
/// routing table.
pub(crate) const BOOTSTRAP_INTERVAL: Duration = Duration::from_secs(10);
/// The default interval at which NetworkDiscovery is triggered.
/// The interval is increased as more peers are added to the routing table.
pub(crate) const NETWORK_DISCOVER_INTERVAL: Duration = Duration::from_secs(10);

/// Every BOOTSTRAP_CONNECTED_PEERS_STEP connected peer, we step up the BOOTSTRAP_INTERVAL to slow down bootstrapping
/// process
const BOOTSTRAP_CONNECTED_PEERS_STEP: u32 = 5;
/// Every NETWORK_DISCOVER_CONNECTED_PEERS_STEP connected peer,
/// we step up the NETWORK_DISCOVER_INTERVAL to slow down process.
const NETWORK_DISCOVER_CONNECTED_PEERS_STEP: u32 = 5;

/// If the previously added peer has been before LAST_PEER_ADDED_TIME_LIMIT, then we should slowdown the bootstrapping
/// process. This is to make sure we don't flood the network with `FindNode` msgs.
/// Slow down the process if the previously added peer has been before LAST_PEER_ADDED_TIME_LIMIT.
/// This is to make sure we don't flood the network with `FindNode` msgs.
const LAST_PEER_ADDED_TIME_LIMIT: Duration = Duration::from_secs(180);

/// A minimum interval to prevent bootstrap got triggered too often
const LAST_BOOTSTRAP_TRIGGERED_TIME_LIMIT: Duration = Duration::from_secs(30);
/// A minimum interval to prevent network discovery got triggered too often
const LAST_NETWORK_DISCOVER_TRIGGERED_TIME_LIMIT: Duration = Duration::from_secs(30);

/// The bootstrap interval to use if we haven't added any new peers in a while.
/// The network discovery interval to use if we haven't added any new peers in a while.
const NO_PEER_ADDED_SLOWDOWN_INTERVAL_MAX_S: u64 = 600;

impl SwarmDriver {
/// This functions triggers network discovery based on when the last peer was added to the RT and the number of
/// peers in RT. The function also returns a new bootstrap interval that is proportional to the number of
/// peers in RT, so more peers in RT, the longer the interval.
pub(crate) async fn run_bootstrap_continuously(
/// This functions triggers network discovery based on when the last peer was added to the RT
/// and the number of peers in RT. The function also returns a new interval that is proportional
/// to the number of peers in RT, so more peers in RT, the longer the interval.
pub(crate) async fn run_network_discover_continuously(
&mut self,
current_bootstrap_interval: Duration,
current_interval: Duration,
) -> Option<Interval> {
let (should_bootstrap, new_interval) = self
let (should_discover, new_interval) = self
.bootstrap
.should_we_bootstrap(self.peers_in_rt as u32, current_bootstrap_interval)
.should_we_discover(self.peers_in_rt as u32, current_interval)
.await;
if should_bootstrap {
if should_discover {
self.trigger_network_discovery();
}
new_interval
Expand Down Expand Up @@ -71,32 +71,33 @@ impl SwarmDriver {
}

/// Tracks and helps with the continuous kad::bootstrapping process
pub(crate) struct ContinuousBootstrap {
pub(crate) struct ContinuousNetworkDiscover {
initial_bootstrap_done: bool,
last_peer_added_instant: Instant,
last_bootstrap_triggered: Option<Instant>,
last_network_discover_triggered: Option<Instant>,
}

impl ContinuousBootstrap {
impl ContinuousNetworkDiscover {
pub(crate) fn new() -> Self {
Self {
initial_bootstrap_done: false,
last_peer_added_instant: Instant::now(),
last_bootstrap_triggered: None,
last_network_discover_triggered: None,
}
}

/// The Kademlia Bootstrap request has been sent successfully.
pub(crate) fn initiated(&mut self) {
self.last_bootstrap_triggered = Some(Instant::now());
self.last_network_discover_triggered = Some(Instant::now());
}

/// Notify about a newly added peer to the RT. This will help with slowing down the bootstrap process.
/// Notify about a newly added peer to the RT. This will help with slowing down the process.
/// Returns `true` if we have to perform the initial bootstrapping.
pub(crate) fn notify_new_peer(&mut self) -> bool {
self.last_peer_added_instant = Instant::now();
// true to kick off the initial bootstrapping. `run_bootstrap_continuously` might kick of so soon that we might
// not have a single peer in the RT and we'd not perform any bootstrapping for a while.
// true to kick off the initial bootstrapping.
// `run_network_discover_continuously` might kick of so soon that we might
// not have a single peer in the RT and we'd not perform any network discovery for a while.
if !self.initial_bootstrap_done {
self.initial_bootstrap_done = true;
true
Expand All @@ -106,22 +107,24 @@ impl ContinuousBootstrap {
}

/// Returns `true` if we should carry out the Kademlia Bootstrap process immediately.
/// Also optionally returns the new interval to re-bootstrap.
/// Also optionally returns the new interval for network discovery.
#[cfg_attr(target_arch = "wasm32", allow(clippy::unused_async))]
pub(crate) async fn should_we_bootstrap(
pub(crate) async fn should_we_discover(
&self,
peers_in_rt: u32,
current_interval: Duration,
) -> (bool, Option<Interval>) {
let is_ongoing = if let Some(last_bootstrap_triggered) = self.last_bootstrap_triggered {
last_bootstrap_triggered.elapsed() < LAST_BOOTSTRAP_TRIGGERED_TIME_LIMIT
let is_ongoing = if let Some(last_network_discover_triggered) =
self.last_network_discover_triggered
{
last_network_discover_triggered.elapsed() < LAST_NETWORK_DISCOVER_TRIGGERED_TIME_LIMIT
} else {
false
};
let should_bootstrap = !is_ongoing && peers_in_rt >= 1;
let should_network_discover = !is_ongoing && peers_in_rt >= 1;

// if it has been a while (LAST_PEER_ADDED_TIME_LIMIT) since we have added a new peer to our RT, then, slowdown
// the bootstrapping process.
// if it has been a while (LAST_PEER_ADDED_TIME_LIMIT) since we have added a new peer,
// slowdown the network discovery process.
// Don't slow down if we haven't even added one peer to our RT.
if self.last_peer_added_instant.elapsed() > LAST_PEER_ADDED_TIME_LIMIT && peers_in_rt != 0 {
// To avoid a heart beat like cpu usage due to the 1K candidates generation,
Expand All @@ -132,7 +135,7 @@ impl ContinuousBootstrap {
let no_peer_added_slowdown_interval_duration =
Duration::from_secs(no_peer_added_slowdown_interval);
info!(
"It has been {LAST_PEER_ADDED_TIME_LIMIT:?} since we last added a peer to RT. Slowing down the continuous bootstrapping process. Old interval: {current_interval:?}, New interval: {no_peer_added_slowdown_interval_duration:?}"
"It has been {LAST_PEER_ADDED_TIME_LIMIT:?} since we last added a peer to RT. Slowing down the continuous network discovery process. Old interval: {current_interval:?}, New interval: {no_peer_added_slowdown_interval_duration:?}"
);

// `Interval` ticks immediately for Tokio, but not for `wasmtimer`, which is used for wasm32.
Expand All @@ -141,15 +144,15 @@ impl ContinuousBootstrap {
#[cfg(not(target_arch = "wasm32"))]
new_interval.tick().await;

return (should_bootstrap, Some(new_interval));
return (should_network_discover, Some(new_interval));
}

// increment bootstrap_interval in steps of BOOTSTRAP_INTERVAL every BOOTSTRAP_CONNECTED_PEERS_STEP
let step = peers_in_rt / BOOTSTRAP_CONNECTED_PEERS_STEP;
// increment network_discover_interval in steps of NETWORK_DISCOVER_INTERVAL every NETWORK_DISCOVER_CONNECTED_PEERS_STEP
let step = peers_in_rt / NETWORK_DISCOVER_CONNECTED_PEERS_STEP;
let step = std::cmp::max(1, step);
let new_interval = BOOTSTRAP_INTERVAL * step;
let new_interval = NETWORK_DISCOVER_INTERVAL * step;
let new_interval = if new_interval > current_interval {
info!("More peers have been added to our RT!. Slowing down the continuous bootstrapping process. Old interval: {current_interval:?}, New interval: {new_interval:?}");
info!("More peers have been added to our RT!. Slowing down the continuous network discovery process. Old interval: {current_interval:?}, New interval: {new_interval:?}");

// `Interval` ticks immediately for Tokio, but not for `wasmtimer`, which is used for wasm32.
#[cfg_attr(target_arch = "wasm32", allow(unused_mut))]
Expand All @@ -161,6 +164,6 @@ impl ContinuousBootstrap {
} else {
None
};
(should_bootstrap, new_interval)
(should_network_discover, new_interval)
}
}
14 changes: 7 additions & 7 deletions sn_networking/src/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
// permissions and limitations relating to use of the SAFE Network Software.

use crate::{
bootstrap::{ContinuousBootstrap, BOOTSTRAP_INTERVAL},
bootstrap::{ContinuousNetworkDiscover, NETWORK_DISCOVER_INTERVAL},
circular_vec::CircularVec,
cmd::{LocalSwarmCmd, NetworkSwarmCmd},
error::{NetworkError, Result},
Expand Down Expand Up @@ -688,7 +688,7 @@ impl NetworkBuilder {

let swarm = Swarm::new(transport, behaviour, peer_id, swarm_config);

let bootstrap = ContinuousBootstrap::new();
let bootstrap = ContinuousNetworkDiscover::new();
let replication_fetcher = ReplicationFetcher::new(peer_id, network_event_sender.clone());
let mut relay_manager = RelayManager::new(peer_id);
if !is_client {
Expand Down Expand Up @@ -798,7 +798,7 @@ pub struct SwarmDriver {
#[cfg(feature = "open-metrics")]
pub(crate) close_group: Vec<PeerId>,
pub(crate) peers_in_rt: usize,
pub(crate) bootstrap: ContinuousBootstrap,
pub(crate) bootstrap: ContinuousNetworkDiscover,
pub(crate) external_address_manager: ExternalAddressManager,
pub(crate) relay_manager: RelayManager,
/// The peers that are closer to our PeerId. Includes self.
Expand Down Expand Up @@ -852,7 +852,7 @@ impl SwarmDriver {
/// and command receiver messages, ensuring efficient handling of multiple
/// asynchronous tasks.
pub async fn run(mut self) {
let mut bootstrap_interval = interval(BOOTSTRAP_INTERVAL);
let mut network_discover_interval = interval(NETWORK_DISCOVER_INTERVAL);
let mut set_farthest_record_interval = interval(CLOSET_RECORD_CHECK_INTERVAL);
let mut relay_manager_reservation_interval = interval(RELAY_MANAGER_RESERVATION_INTERVAL);

Expand Down Expand Up @@ -915,9 +915,9 @@ impl SwarmDriver {
// thereafter we can check our intervals

// runs every bootstrap_interval time
_ = bootstrap_interval.tick() => {
if let Some(new_interval) = self.run_bootstrap_continuously(bootstrap_interval.period()).await {
bootstrap_interval = new_interval;
_ = network_discover_interval.tick() => {
if let Some(new_interval) = self.run_network_discover_continuously(network_discover_interval.period()).await {
network_discover_interval = new_interval;
}
}
_ = set_farthest_record_interval.tick() => {
Expand Down

0 comments on commit 52db692

Please sign in to comment.