Parallelize requests within Validators::update

This commit is contained in:
Luke Parker
2025-01-05 00:17:05 -05:00
parent 479ca0410a
commit 2b8f481364
3 changed files with 60 additions and 35 deletions

View File

@@ -26,8 +26,9 @@ struct DialTask {
}
impl ContinuallyRan for DialTask {
// Only run every thirty seconds, not the default of every five
const DELAY_BETWEEN_ITERATIONS: u64 = 30;
// Only run every five minutes, not the default of every five seconds
const DELAY_BETWEEN_ITERATIONS: u64 = 5 * 60;
const MAX_DELAY_BETWEEN_ITERATIONS: u64 = 10 * 60;
fn run_iteration(&mut self) -> impl Send + Future<Output = Result<bool, String>> {
async move {

View File

@@ -101,8 +101,8 @@ impl SwarmTask {
// Refresh the instance of validators we use to track peers/share with authenticate
() = tokio::time::sleep(time_till_refresh_validators) => {
const TIME_BETWEEN_REFRESH_VALIDATORS: Duration = Duration::from_secs(5);
const MAX_TIME_BETWEEN_REFRESH_VALIDATORS: Duration = Duration::from_secs(120);
const TIME_BETWEEN_REFRESH_VALIDATORS: Duration = Duration::from_secs(60);
const MAX_TIME_BETWEEN_REFRESH_VALIDATORS: Duration = Duration::from_secs(5 * 60);
let update = self.validators.write().await.update().await;
match update {

View File

@@ -4,6 +4,8 @@ use serai_client::{primitives::NetworkId, validator_sets::primitives::Session, S
use libp2p::PeerId;
use futures_util::stream::{StreamExt, FuturesUnordered};
use crate::p2p::peer_id_from_public;
pub(crate) struct Validators {
@@ -27,20 +29,43 @@ impl Validators {
let temporal_serai =
self.serai.as_of_latest_finalized_block().await.map_err(|e| format!("{e:?}"))?;
let temporal_serai = temporal_serai.validator_sets();
let mut session_changes = vec![];
{
// FuturesUnordered can be bad practice as it'll cause timeouts if infrequently polled, but
// we poll it till it yields all futures with the most minimal processing possible
let mut futures = FuturesUnordered::new();
for network in serai_client::primitives::NETWORKS {
if network == NetworkId::Serai {
continue;
}
let Some(session) = temporal_serai.session(network).await.map_err(|e| format!("{e:?}"))?
else {
continue;
let sessions = &self.sessions;
futures.push(async move {
let session = match temporal_serai.session(network).await {
Ok(Some(session)) => session,
Ok(None) => return Ok(None),
Err(e) => return Err(format!("{e:?}")),
};
// If the session has changed, populate it with the current validators
if self.sessions.get(&network) != Some(&session) {
let new_validators =
temporal_serai.active_network_validators(network).await.map_err(|e| format!("{e:?}"))?;
let new_validators =
new_validators.into_iter().map(peer_id_from_public).collect::<HashSet<_>>();
if sessions.get(&network) == Some(&session) {
Ok(None)
} else {
match temporal_serai.active_network_validators(network).await {
Ok(validators) => Ok(Some((network, session, validators))),
Err(e) => Err(format!("{e:?}")),
}
}
});
}
while let Some(session_change) = futures.next().await {
if let Some(session_change) = session_change? {
session_changes.push(session_change);
}
}
}
for (network, session, validators) in session_changes {
let validators = validators.into_iter().map(peer_id_from_public).collect::<HashSet<_>>();
// Remove the existing validators
for validator in self.by_network.remove(&network).unwrap_or_else(HashSet::new) {
@@ -54,15 +79,14 @@ impl Validators {
}
// Add the new validators
for validator in new_validators.iter().copied() {
for validator in validators.iter().copied() {
self.validators.entry(validator).or_insert_with(HashSet::new).insert(network);
}
self.by_network.insert(network, new_validators);
self.by_network.insert(network, validators);
// Update the session we have populated
self.sessions.insert(network, session);
}
}
Ok(removed)
}