fix(hang): Stop blocking some Zebra futures for up to a minute using a CPU busy-loop, Credit: Ziggurat Team (#6763), james_katz (#7000) (#7103)
* Stop busy-waiting in a Future for 45 seconds every minute * Use the correct elapsed time calculation * Add some TODOs for making the structure of the loop and wait times clearer
This commit is contained in:
parent
5eea111922
commit
322cbec817
|
@ -1,8 +1,12 @@
|
||||||
//! Progress tracking for blockchain syncing.
|
//! Progress tracking for blockchain syncing.
|
||||||
|
|
||||||
use std::{cmp::min, ops::Add, time::Duration};
|
use std::{
|
||||||
|
cmp::min,
|
||||||
|
ops::Add,
|
||||||
|
time::{Duration, Instant},
|
||||||
|
};
|
||||||
|
|
||||||
use chrono::{TimeZone, Utc};
|
use chrono::Utc;
|
||||||
use num_integer::div_ceil;
|
use num_integer::div_ceil;
|
||||||
|
|
||||||
use zebra_chain::{
|
use zebra_chain::{
|
||||||
|
@ -118,17 +122,15 @@ pub async fn show_block_chain_progress(
|
||||||
let mut last_state_change_height = Height(0);
|
let mut last_state_change_height = Height(0);
|
||||||
|
|
||||||
// The last time we logged an update.
|
// The last time we logged an update.
|
||||||
// Initialised with the unix epoch, to simplify the code while still staying in the std range.
|
let mut last_log_time = Instant::now();
|
||||||
let mut last_log_time = Utc
|
|
||||||
.timestamp_opt(0, 0)
|
|
||||||
.single()
|
|
||||||
.expect("in-range number of seconds and valid nanosecond");
|
|
||||||
|
|
||||||
#[cfg(feature = "progress-bar")]
|
#[cfg(feature = "progress-bar")]
|
||||||
let block_bar = howudoin::new().label("Blocks");
|
let block_bar = howudoin::new().label("Blocks");
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let now = Utc::now();
|
let now = Utc::now();
|
||||||
|
let instant_now = Instant::now();
|
||||||
|
|
||||||
let is_syncer_stopped = sync_status.is_close_to_tip();
|
let is_syncer_stopped = sync_status.is_close_to_tip();
|
||||||
|
|
||||||
if let Some(estimated_height) =
|
if let Some(estimated_height) =
|
||||||
|
@ -142,6 +144,8 @@ pub async fn show_block_chain_progress(
|
||||||
let network_upgrade = NetworkUpgrade::current(network, current_height);
|
let network_upgrade = NetworkUpgrade::current(network, current_height);
|
||||||
|
|
||||||
// Send progress reports for block height
|
// Send progress reports for block height
|
||||||
|
//
|
||||||
|
// TODO: split the progress bar height update into its own function.
|
||||||
#[cfg(feature = "progress-bar")]
|
#[cfg(feature = "progress-bar")]
|
||||||
if matches!(howudoin::cancelled(), Some(true)) {
|
if matches!(howudoin::cancelled(), Some(true)) {
|
||||||
block_bar.close();
|
block_bar.close();
|
||||||
|
@ -152,16 +156,17 @@ pub async fn show_block_chain_progress(
|
||||||
.desc(network_upgrade.to_string());
|
.desc(network_upgrade.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip logging if it isn't time for it yet
|
// Skip logging and status updates if it isn't time for them yet.
|
||||||
let elapsed_since_log = (now - last_log_time)
|
let elapsed_since_log = instant_now.saturating_duration_since(last_log_time);
|
||||||
.to_std()
|
|
||||||
.expect("elapsed times are in range");
|
|
||||||
if elapsed_since_log < LOG_INTERVAL {
|
if elapsed_since_log < LOG_INTERVAL {
|
||||||
|
tokio::time::sleep(PROGRESS_BAR_INTERVAL).await;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
last_log_time = now;
|
last_log_time = instant_now;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: split logging / status updates into their own function.
|
||||||
|
|
||||||
// Work out the sync progress towards the estimated tip.
|
// Work out the sync progress towards the estimated tip.
|
||||||
let sync_progress = f64::from(current_height.0) / f64::from(estimated_height.0);
|
let sync_progress = f64::from(current_height.0) / f64::from(estimated_height.0);
|
||||||
let sync_percent = format!(
|
let sync_percent = format!(
|
||||||
|
|
Loading…
Reference in New Issue