change(state): Only do continuous format checks in CI (#7627)

* Only do continuous format checks if enabled by a config

* Run continuous format checks in CI
This commit is contained in:
teor 2023-09-28 07:42:43 +10:00 committed by GitHub
parent 90df59af55
commit 0faa0697d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 46 additions and 27 deletions

View File

@ -5740,6 +5740,7 @@ dependencies = [
"hex", "hex",
"hex-literal", "hex-literal",
"howudoin", "howudoin",
"humantime-serde",
"indexmap 2.0.0", "indexmap 2.0.0",
"insta", "insta",
"itertools 0.11.0", "itertools 0.11.0",

View File

@ -49,6 +49,7 @@ dirs = "5.0.1"
futures = "0.3.28" futures = "0.3.28"
hex = "0.4.3" hex = "0.4.3"
hex-literal = "0.4.1" hex-literal = "0.4.1"
humantime-serde = "1.1.1"
indexmap = "2.0.0" indexmap = "2.0.0"
itertools = "0.11.0" itertools = "0.11.0"
lazy_static = "1.4.0" lazy_static = "1.4.0"

View File

@ -4,6 +4,7 @@ use std::{
fs::{self, canonicalize, remove_dir_all, DirEntry, ReadDir}, fs::{self, canonicalize, remove_dir_all, DirEntry, ReadDir},
io::ErrorKind, io::ErrorKind,
path::{Path, PathBuf}, path::{Path, PathBuf},
time::Duration,
}; };
use semver::Version; use semver::Version;
@ -83,11 +84,6 @@ pub struct Config {
/// [`cache_dir`]: struct.Config.html#structfield.cache_dir /// [`cache_dir`]: struct.Config.html#structfield.cache_dir
pub ephemeral: bool, pub ephemeral: bool,
/// Commit blocks to the finalized state up to this height, then exit Zebra.
///
/// Set to `None` by default: Zebra continues syncing indefinitely.
pub debug_stop_at_height: Option<u32>,
/// Whether to delete the old database directories when present. /// Whether to delete the old database directories when present.
/// ///
/// Set to `true` by default. If this is set to `false`, /// Set to `true` by default. If this is set to `false`,
@ -95,6 +91,21 @@ pub struct Config {
/// deleted. /// deleted.
pub delete_old_database: bool, pub delete_old_database: bool,
// Debug configs
//
/// Commit blocks to the finalized state up to this height, then exit Zebra.
///
/// Set to `None` by default: Zebra continues syncing indefinitely.
pub debug_stop_at_height: Option<u32>,
/// While Zebra is running, check state validity this often.
///
/// Set to `None` by default: Zebra only checks state format validity on startup and shutdown.
#[serde(with = "humantime_serde")]
pub debug_validity_check_interval: Option<Duration>,
// Elasticsearch configs
//
#[cfg(feature = "elasticsearch")] #[cfg(feature = "elasticsearch")]
/// The elasticsearch database url. /// The elasticsearch database url.
pub elasticsearch_url: String, pub elasticsearch_url: String,
@ -162,8 +173,9 @@ impl Default for Config {
Self { Self {
cache_dir, cache_dir,
ephemeral: false, ephemeral: false,
debug_stop_at_height: None,
delete_old_database: true, delete_old_database: true,
debug_stop_at_height: None,
debug_validity_check_interval: None,
#[cfg(feature = "elasticsearch")] #[cfg(feature = "elasticsearch")]
elasticsearch_url: "https://localhost:9200".to_string(), elasticsearch_url: "https://localhost:9200".to_string(),
#[cfg(feature = "elasticsearch")] #[cfg(feature = "elasticsearch")]

View File

@ -1,7 +1,5 @@
//! Constants that impact state behaviour. //! Constants that impact state behaviour.
use std::time::Duration;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use regex::Regex; use regex::Regex;
use semver::Version; use semver::Version;
@ -69,12 +67,6 @@ pub fn latest_version_for_adding_subtrees() -> Version {
/// Use [`Config::version_file_path()`] to get the path to this file. /// Use [`Config::version_file_path()`] to get the path to this file.
pub(crate) const DATABASE_FORMAT_VERSION_FILE_NAME: &str = "version"; pub(crate) const DATABASE_FORMAT_VERSION_FILE_NAME: &str = "version";
/// The interval between database format checks for newly added blocks.
///
/// This should be short enough that format bugs cause CI test failures,
/// but long enough that it doesn't impact performance.
pub(crate) const DATABASE_FORMAT_CHECK_INTERVAL: Duration = Duration::from_secs(5 * 60);
/// The maximum number of blocks to check for NU5 transactions, /// The maximum number of blocks to check for NU5 transactions,
/// before we assume we are on a pre-NU5 legacy chain. /// before we assume we are on a pre-NU5 legacy chain.
/// ///

View File

@ -2,7 +2,6 @@
use std::{ use std::{
cmp::Ordering, cmp::Ordering,
convert::Infallible,
sync::{mpsc, Arc}, sync::{mpsc, Arc},
thread::{self, JoinHandle}, thread::{self, JoinHandle},
}; };
@ -23,9 +22,7 @@ use DbFormatChange::*;
use crate::{ use crate::{
config::write_database_format_version_to_disk, config::write_database_format_version_to_disk,
constants::{ constants::{latest_version_for_adding_subtrees, DATABASE_FORMAT_VERSION},
latest_version_for_adding_subtrees, DATABASE_FORMAT_CHECK_INTERVAL, DATABASE_FORMAT_VERSION,
},
database_format_version_in_code, database_format_version_on_disk, database_format_version_in_code, database_format_version_on_disk,
service::finalized_state::{DiskWriteBatch, ZebraDb}, service::finalized_state::{DiskWriteBatch, ZebraDb},
Config, Config,
@ -94,11 +91,11 @@ pub enum DbFormatChange {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct DbFormatChangeThreadHandle { pub struct DbFormatChangeThreadHandle {
/// A handle to the format change/check thread. /// A handle to the format change/check thread.
/// This thread continues running so it can perform periodic format checks. /// If configured, this thread continues running so it can perform periodic format checks.
/// ///
/// Panics from this thread are propagated into Zebra's state service. /// Panics from this thread are propagated into Zebra's state service.
/// The task returns an error if the upgrade was cancelled by a shutdown. /// The task returns an error if the upgrade was cancelled by a shutdown.
update_task: Option<Arc<JoinHandle<Result<Infallible, CancelFormatChange>>>>, update_task: Option<Arc<JoinHandle<Result<(), CancelFormatChange>>>>,
/// A channel that tells the running format thread to finish early. /// A channel that tells the running format thread to finish early.
cancel_handle: mpsc::SyncSender<CancelFormatChange>, cancel_handle: mpsc::SyncSender<CancelFormatChange>,
@ -258,10 +255,11 @@ impl DbFormatChange {
handle handle
} }
/// Run the initial format change or check to the database, then periodically check the format /// Run the initial format change or check to the database. Under the default runtime config,
/// of newly added blocks matches the current format. /// this method returns after the format change or check.
/// ///
/// This method runs until it is cancelled or panics. /// But if runtime validity checks are enabled, this method periodically checks the format of
/// newly added blocks matches the current format. It will run until it is cancelled or panics.
fn format_change_run_loop( fn format_change_run_loop(
self, self,
config: Config, config: Config,
@ -269,7 +267,7 @@ impl DbFormatChange {
initial_tip_height: Option<Height>, initial_tip_height: Option<Height>,
upgrade_db: ZebraDb, upgrade_db: ZebraDb,
cancel_receiver: mpsc::Receiver<CancelFormatChange>, cancel_receiver: mpsc::Receiver<CancelFormatChange>,
) -> Result<Infallible, CancelFormatChange> { ) -> Result<(), CancelFormatChange> {
self.run_format_change_or_check( self.run_format_change_or_check(
&config, &config,
network, network,
@ -278,11 +276,15 @@ impl DbFormatChange {
&cancel_receiver, &cancel_receiver,
)?; )?;
let Some(debug_validity_check_interval) = config.debug_validity_check_interval else {
return Ok(());
};
loop { loop {
// We've just run a format check, so sleep first, then run another one. // We've just run a format check, so sleep first, then run another one.
// But return early if there is a cancel signal. // But return early if there is a cancel signal.
if !matches!( if !matches!(
cancel_receiver.recv_timeout(DATABASE_FORMAT_CHECK_INTERVAL), cancel_receiver.recv_timeout(debug_validity_check_interval),
Err(mpsc::RecvTimeoutError::Timeout) Err(mpsc::RecvTimeoutError::Timeout)
) { ) {
return Err(CancelFormatChange); return Err(CancelFormatChange);

View File

@ -30,9 +30,15 @@ use crate::common::{
test_type::TestType, test_type::TestType,
}; };
/// Path to a directory containing a cached Zebra state. /// The environmental variable that holds the path to a directory containing a cached Zebra state.
pub const ZEBRA_CACHED_STATE_DIR: &str = "ZEBRA_CACHED_STATE_DIR"; pub const ZEBRA_CACHED_STATE_DIR: &str = "ZEBRA_CACHED_STATE_DIR";
/// In integration tests, the interval between database format checks for newly added blocks.
///
/// This should be short enough that format bugs cause CI test failures,
/// but long enough that it doesn't impact performance.
pub const DATABASE_FORMAT_CHECK_INTERVAL: Duration = Duration::from_secs(5 * 60);
/// Type alias for a boxed state service. /// Type alias for a boxed state service.
pub type BoxStateService = pub type BoxStateService =
BoxService<zebra_state::Request, zebra_state::Response, zebra_state::BoxError>; BoxService<zebra_state::Request, zebra_state::Response, zebra_state::BoxError>;

View File

@ -21,6 +21,8 @@ use zebrad::{
config::ZebradConfig, config::ZebradConfig,
}; };
use crate::common::cached_state::DATABASE_FORMAT_CHECK_INTERVAL;
/// Returns a config with: /// Returns a config with:
/// - a Zcash listener on an unused port on IPv4 localhost, and /// - a Zcash listener on an unused port on IPv4 localhost, and
/// - an ephemeral state, /// - an ephemeral state,
@ -61,9 +63,12 @@ pub fn default_test_config() -> Result<ZebradConfig> {
..tracing::Config::default() ..tracing::Config::default()
}; };
let mut state = zebra_state::Config::ephemeral();
state.debug_validity_check_interval = Some(DATABASE_FORMAT_CHECK_INTERVAL);
let config = ZebradConfig { let config = ZebradConfig {
network, network,
state: zebra_state::Config::ephemeral(), state,
sync, sync,
mempool, mempool,
consensus, consensus,