Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge-queue: embarking main (2465f4b) and #5228 together #5241

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion zebra-state/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub use request::{FinalizedBlock, HashOrHeight, PreparedBlock, ReadRequest, Requ
pub use response::{ReadResponse, Response};
pub use service::{
chain_tip::{ChainTipChange, LatestChainTip, TipAction},
init, OutputIndex, OutputLocation, TransactionLocation,
init, spawn_init, OutputIndex, OutputLocation, TransactionLocation,
};

#[cfg(any(test, feature = "proptest-impl"))]
Expand Down
15 changes: 15 additions & 0 deletions zebra-state/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1292,6 +1292,21 @@ pub fn init(
)
}

/// Calls [`init`] with the provided [`Config`] and [`Network`] from a blocking task.
/// Returns a [`tokio::task::JoinHandle`] with a boxed state service,
/// a read state service, and receivers for state chain tip updates.
pub fn spawn_init(
config: Config,
network: Network,
) -> tokio::task::JoinHandle<(
BoxService<Request, Response, BoxError>,
ReadStateService,
LatestChainTip,
ChainTipChange,
)> {
tokio::task::spawn_blocking(move || init(config, network))
}

/// Returns a [`StateService`] with an ephemeral [`Config`] and a buffer with a single slot.
///
/// This can be used to create a state service for testing.
Expand Down
4 changes: 2 additions & 2 deletions zebrad/src/commands/copy_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ impl CopyStateCmd {
_source_read_only_state_service,
_source_latest_chain_tip,
_source_chain_tip_change,
) = old_zs::init(source_config.clone(), network);
) = old_zs::spawn_init(source_config.clone(), network).await?;

let elapsed = source_start_time.elapsed();
info!(?elapsed, "finished initializing source state service");
Expand All @@ -136,7 +136,7 @@ impl CopyStateCmd {
_target_read_only_state_service,
_target_latest_chain_tip,
_target_chain_tip_change,
) = new_zs::init(target_config.clone(), network);
) = new_zs::spawn_init(target_config.clone(), network).await?;

let elapsed = target_start_time.elapsed();
info!(?elapsed, "finished initializing target state service");
Expand Down
5 changes: 4 additions & 1 deletion zebrad/src/commands/start.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,11 @@ impl StartCmd {
info!(?config);

info!("initializing node state");
info!("opening database, this may take a couple minutes");

let (state_service, read_only_state_service, latest_chain_tip, chain_tip_change) =
zebra_state::init(config.state.clone(), config.network.network);
zebra_state::spawn_init(config.state.clone(), config.network.network).await?;

let state = ServiceBuilder::new()
.buffer(Self::state_buffer_bound())
.service(state_service);
Expand Down
25 changes: 25 additions & 0 deletions zebrad/tests/acceptance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,31 @@ fn start_args() -> Result<()> {
Ok(())
}

#[tokio::test]
async fn db_init_outside_future_executor() -> Result<()> {
use std::time::{Duration, Instant};

let _init_guard = zebra_test::init();
let config = default_test_config()?;

let start = Instant::now();

let db_init_handle = zebra_state::spawn_init(config.state.clone(), config.network.network);

// it's faster to panic if it takes longer than expected, since the executor
// will wait indefinitely for blocking operation to finish once started
let block_duration = start.elapsed();
assert!(
block_duration < Duration::from_millis(5),
"futures executor was blocked longer than expected ({:?})",
block_duration,
);

db_init_handle.await?;

Ok(())
}

#[test]
fn persistent_mode() -> Result<()> {
let _init_guard = zebra_test::init();
Expand Down