/// Update the peer set from the network.
///
/// - Ask a few live `Responded` peers to send us more peers.
/// - Process all completed peer responses, adding new peers in the
///   `NeverAttempted` state.
///
/// ## Correctness
///
/// The crawler exits when update returns an error, so it must only return
/// errors on permanent failures.
///
/// The handshaker sets up the peer message receiver so it also sends a
/// `Responded` peer address update.
///
/// `report_failed` puts peers into the `Failed` state.
///
/// `next` puts peers into the `AttemptPending` state.
Update the peer set from the network.
Ask a few live `Responded` peers to send us more peers.
Process all completed peer responses, adding new peers in the
`NeverAttempted` state.
Update the peer set from the network . Ask a few live ` Responded ` peers to send us more peers . Process all completed peer responses adding new peers in the ` NeverAttempted ` state .
pub async fn update(&mut self) -> Result<(), BoxError> {
        // Opportunistically crawl the network on every update call to ensure
        // we're actively fetching peers. Continue independently of whether we
        // actually receive any peers, but always ask the network for more.
        //
        // Because requests are load-balanced across existing peers, we can make
        // multiple requests concurrently, which will be randomly assigned to
        // existing peers, but we don't make too many because update may be
        // called while the peer set is already loaded.
        let mut responses = FuturesUnordered::new();
        trace!("sending GetPeers requests");
        for _ in 0..constants::GET_ADDR_FANOUT {
            // CORRECTNESS
            //
            // avoid deadlocks when there are no connected peers, and:
            // - we're waiting on a handshake to complete so there are peers, or
            // - another task that handles or adds peers is waiting on this task to complete.
            let peer_service =
                match timeout(constants::REQUEST_TIMEOUT, self.peer_service.ready_and()).await {
                    // update must only return an error for permanent failures
                    Err(temporary_error) => {
                        info!(
                            ?temporary_error,
                            "timeout waiting for the peer service to become ready"
                        );
                        return Ok(());
                    }
                    Ok(Err(permanent_error)) => Err(permanent_error)?,
                    Ok(Ok(peer_service)) => peer_service,
                };
            responses.push(peer_service.call(Request::Peers));
        }
        while let Some(rsp) = responses.next().await {
            match rsp {
                Ok(Response::Peers(rsp_addrs)) => {
                    // Filter new addresses to ensure that gossiped addresses are actually new
                    let peer_set = &self.peer_set;
                    // TODO: reduce mutex contention by moving the filtering into
                    // the address book itself
                    let new_addrs = rsp_addrs
                        .iter()
                        .filter(|meta| !peer_set.lock().unwrap().contains_addr(&meta.addr))
                        .collect::<Vec<_>>();
                    trace!(
                        ?rsp_addrs,
                        new_addr_count = ?new_addrs.len(),
                        "got response to GetPeers"
                    );
                    // New addresses are deserialized in the `NeverAttempted` state
                    peer_set
                        .lock()
                        .unwrap()
                        .extend(new_addrs.into_iter().cloned());
                }
                Err(e) => {
                    // since we do a fanout, and new updates are triggered by
                    // each demand, we can ignore errors in individual responses
                    trace!(?e, "got error in GetPeers request");
                }
                Ok(_) => unreachable!("Peers requests always return Peers responses"),
            }
        }
        Ok(())
    }
pub async fn update ( & mut self ) -> Result < ( ) , BoxError > { // Opportunistically crawl the network on every update call to ensure // we're actively fetching peers. Continue independently of whether we // actually receive any peers, but always ask the network for more. // // Because requests are load-balanced across existing peers, we can make // multiple requests concurrently, which will be randomly assigned to // existing peers, but we don't make too many because update may be // called while the peer set is already loaded. let mut responses = FuturesUnordered :: new ( ) ; trace ! ( " " ) ; for _ in 0 .. constants :: GET_ADDR_FANOUT { // CORRECTNESS // // avoid deadlocks when there are no connected peers, and: // - we're waiting on a handshake to complete so there are peers, or // - another task that handles or adds peers is waiting on this task to complete. let peer_service = match timeout ( constants :: REQUEST_TIMEOUT , self . peer_service . ready_and ( ) ) . await { // update must only return an error for permanent failures Err ( temporary_error ) => { info ! ( temporary_error " " ) ; return Ok ( ( ) ) ; } Ok ( Err ( permanent_error ) ) => Err ( permanent_error ) ? , Ok ( Ok ( peer_service ) ) => peer_service , } ; responses . push ( peer_service . call ( Request :: Peers ) ) ; } while let Some ( rsp ) = responses . next ( ) . await { match rsp { Ok ( Response :: Peers ( rsp_addrs ) ) => { // Filter new addresses to ensure that gossiped addresses are actually new let peer_set = & self . peer_set ; // TODO: reduce mutex contention by moving the filtering into // the address book itself let new_addrs = rsp_addrs . iter ( ) . filter ( | meta | ! peer_set . lock ( ) . unwrap ( ) . contains_addr ( & meta . addr ) ) . collect :: < Vec < _ > > ( ) ; trace ! ( rsp_addrs new_addr_count new_addrs len ( ) " " ) ; // New addresses are deserialized in the `NeverAttempted` state peer_set . lock ( ) . unwrap ( ) . extend ( new_addrs . into_iter ( ) . cloned ( ) ) ; } Err ( e ) => { // since we do a fanout, and new updates are triggered by // each demand, we can ignore errors in individual responses trace ! ( e " " ) ; } Ok ( _ ) => unreachable ! ( " " ) , } } Ok ( ( ) ) }
Update the peer set from the network.
Update the peer set from the network .
&mut self
<not_specific>
correctness
The crawler exits when update returns an error, so it must only return
errors on permanent failures.

The handshaker sets up the peer message receiver so it also sends a
`Responded` peer address update.

`report_failed` puts peers into the `Failed` state.

`next` puts peers into the `AttemptPending` state.
The crawler exits when update returns an error so it must only return errors on permanent failures . The handshaker sets up the peer message receiver so it also sends a ` Responded ` peer address update . ` report_failed ` puts peers into the ` Failed ` state . ` next ` puts peers into the ` AttemptPending ` state .