use tokio::sync::watch;
use zebra_chain::chain_sync_status::ChainSyncStatus;
use super::RecentSyncLengths;
#[cfg(any(test, feature = "proptest-impl"))]
pub mod mock;
#[cfg(test)]
mod tests;
#[derive(Clone, Debug)]
pub struct SyncStatus {
latest_sync_length: watch::Receiver<Vec<usize>>,
}
impl SyncStatus {
const MIN_DIST_FROM_TIP: usize = 20;
pub fn new() -> (Self, RecentSyncLengths) {
let (recent_sync_lengths, latest_sync_length) = RecentSyncLengths::new();
let status = SyncStatus { latest_sync_length };
(status, recent_sync_lengths)
}
pub async fn wait_until_close_to_tip(&mut self) -> Result<(), watch::error::RecvError> {
while !self.is_close_to_tip() {
self.latest_sync_length.changed().await?;
}
Ok(())
}
}
impl ChainSyncStatus for SyncStatus {
fn is_close_to_tip(&self) -> bool {
let sync_lengths = self.latest_sync_length.borrow();
if sync_lengths.is_empty() {
return false;
}
let sum = sync_lengths
.iter()
.fold(0usize, |sum, rhs| sum.saturating_add(*rhs));
let avg = sum / sync_lengths.len();
avg < Self::MIN_DIST_FROM_TIP
}
}