diff --git a/e2e/tests-dfx/start.bash b/e2e/tests-dfx/start.bash index 918409e57a..0062cec23d 100644 --- a/e2e/tests-dfx/start.bash +++ b/e2e/tests-dfx/start.bash @@ -79,7 +79,7 @@ teardown() { @test "start and stop outside project" { assert_command dfx_start - assert_contains "Success! The dfx server is running in the background." + assert_contains "Replica API running in the background" mkdir subdir cd subdir || exit 1 diff --git a/src/dfx/src/actors/canister_http_adapter.rs b/src/dfx/src/actors/canister_http_adapter.rs index f42b1c89d8..854b8fcac9 100644 --- a/src/dfx/src/actors/canister_http_adapter.rs +++ b/src/dfx/src/actors/canister_http_adapter.rs @@ -12,7 +12,7 @@ use actix::{ }; use anyhow::bail; use crossbeam::channel::{unbounded, Receiver, Sender}; -use slog::{debug, info, Logger}; +use slog::{debug, Logger}; use std::path::{Path, PathBuf}; use std::thread::JoinHandle; use std::time::Duration; @@ -126,7 +126,7 @@ impl Actor for CanisterHttpAdapter { } fn stopping(&mut self, _ctx: &mut Self::Context) -> Running { - info!(self.logger, "Stopping canister http adapter..."); + debug!(self.logger, "Stopping canister http adapter..."); if let Some(sender) = self.stop_sender.take() { let _ = sender.send(()); } @@ -135,7 +135,7 @@ impl Actor for CanisterHttpAdapter { let _ = join.join(); } - info!(self.logger, "Stopped."); + debug!(self.logger, "Stopped."); Running::Stop } } diff --git a/src/dfx/src/actors/mod.rs b/src/dfx/src/actors/mod.rs index 77293a7f42..599d74b7e0 100644 --- a/src/dfx/src/actors/mod.rs +++ b/src/dfx/src/actors/mod.rs @@ -6,6 +6,7 @@ use crate::actors::replica::{BitcoinIntegrationConfig, Replica}; use crate::actors::shutdown_controller::ShutdownController; use crate::lib::environment::Environment; use crate::lib::error::DfxResult; +use crate::lib::progress_bar::ProgressBar; use actix::{Actor, Addr, Recipient}; use anyhow::Context; use dfx_core::config::model::local_server_descriptor::LocalServerDescriptor; @@ -233,11 +234,12 @@ pub fn start_post_start_actor( env: &dyn Environment, background: bool, pocketic_proxy: Option>, + spinner: ProgressBar, ) -> DfxResult> { let config = post_start::Config { logger: env.get_logger().clone(), background, pocketic_proxy, }; - Ok(PostStart::new(config).start()) + Ok(PostStart::new(config, spinner).start()) } diff --git a/src/dfx/src/actors/pocketic.rs b/src/dfx/src/actors/pocketic.rs index ae2c4bd7ce..10cd0c48c1 100644 --- a/src/dfx/src/actors/pocketic.rs +++ b/src/dfx/src/actors/pocketic.rs @@ -24,7 +24,7 @@ use dfx_core::config::model::replica_config::CachedConfig; use dfx_core::config::model::replica_config::ReplicaConfig; #[cfg(unix)] use dfx_core::json::save_json_file; -use slog::{debug, error, info, warn, Logger}; +use slog::{debug, error, warn, Logger}; use std::net::SocketAddr; use std::ops::ControlFlow::{self, *}; use std::path::{Path, PathBuf}; @@ -159,7 +159,7 @@ impl Actor for PocketIc { } fn stopping(&mut self, _ctx: &mut Self::Context) -> Running { - info!(self.logger, "Stopping PocketIC..."); + warn!(self.logger, "Stopping PocketIC..."); if let Some(sender) = self.stop_sender.take() { let _ = sender.send(()); } @@ -168,7 +168,7 @@ impl Actor for PocketIc { let _ = join.join(); } - info!(self.logger, "Stopped."); + warn!(self.logger, "Stopped."); Running::Stop } } @@ -435,7 +435,7 @@ async fn initialize_pocketic( initialize_bitcoin_canister(&agent, &logger, bitcoin_integration_config.clone()).await?; } - info!(logger, "Initialized PocketIC."); + debug!(logger, "Initialized PocketIC."); Ok(instance) } diff --git a/src/dfx/src/actors/pocketic_proxy.rs b/src/dfx/src/actors/pocketic_proxy.rs index b2e4fd3803..1684c65f0d 100644 --- a/src/dfx/src/actors/pocketic_proxy.rs +++ b/src/dfx/src/actors/pocketic_proxy.rs @@ -11,7 +11,7 @@ use actix::{ }; use anyhow::{anyhow, bail}; use crossbeam::channel::{unbounded, Receiver, Sender}; -use slog::{debug, error, info, Logger}; +use slog::{debug, error, Logger}; use std::net::SocketAddr; use std::ops::ControlFlow::{self, *}; use std::path::{Path, PathBuf}; @@ -120,7 +120,7 @@ impl PocketIcProxy { fn stop_pocketic_proxy(&mut self) { if self.stop_sender.is_some() || self.thread_join.is_some() { - info!(self.logger, "Stopping HTTP gateway..."); + debug!(self.logger, "Stopping HTTP gateway..."); if let Some(sender) = self.stop_sender.take() { let _ = sender.send(()); } @@ -128,7 +128,7 @@ impl PocketIcProxy { if let Some(join) = self.thread_join.take() { let _ = join.join(); } - info!(self.logger, "Stopped."); + debug!(self.logger, "Stopped."); } } @@ -211,9 +211,9 @@ impl Handler for PocketIcProxy { impl Handler for PocketIcProxy { type Result = (); - fn handle(&mut self, _msg: PocketIcProxyReadySignal, _ctx: &mut Self::Context) { + fn handle(&mut self, msg: PocketIcProxyReadySignal, _ctx: &mut Self::Context) { for sub in &self.ready_subscribers { - sub.do_send(PocketIcProxyReadySignal); + sub.do_send(msg); } } } @@ -309,10 +309,9 @@ fn pocketic_proxy_start_thread( } Ok(i) => i, }; - info!(logger, "Replica API running on {address}"); // Send PocketIcProxyReadySignal to PocketIcProxy. - addr.do_send(PocketIcProxyReadySignal); + addr.do_send(PocketIcProxyReadySignal(address)); // This waits for the child to stop, or the receiver to receive a message. // We don't restart pocket-ic if done = true. @@ -384,7 +383,7 @@ async fn initialize_gateway( CreateHttpGatewayResponse::Created(info) => info.instance_id, CreateHttpGatewayResponse::Error { message } => bail!("Gateway init error: {message}"), }; - info!(logger, "Initialized HTTP gateway."); + debug!(logger, "Initialized HTTP gateway."); Ok(instance) } diff --git a/src/dfx/src/actors/post_start.rs b/src/dfx/src/actors/post_start.rs index 35222e6e57..727045646d 100644 --- a/src/dfx/src/actors/post_start.rs +++ b/src/dfx/src/actors/post_start.rs @@ -1,14 +1,17 @@ use crate::actors::pocketic_proxy::PocketIcProxy; use crate::actors::post_start::signals::{PocketIcProxyReadySignal, PocketIcProxyReadySubscribe}; +use crate::lib::progress_bar::ProgressBar; use actix::{Actor, Addr, AsyncContext, Context, Handler}; use slog::{info, Logger}; pub mod signals { + use std::net::SocketAddr; + use actix::prelude::*; - #[derive(Message)] + #[derive(Message, Copy, Clone)] #[rtype(result = "()")] - pub struct PocketIcProxyReadySignal; + pub struct PocketIcProxyReadySignal(pub SocketAddr); #[derive(Message)] #[rtype(result = "()")] @@ -23,11 +26,12 @@ pub struct Config { pub struct PostStart { config: Config, + spinner: ProgressBar, } impl PostStart { - pub fn new(config: Config) -> Self { - Self { config } + pub fn new(config: Config, spinner: ProgressBar) -> Self { + Self { config, spinner } } } @@ -45,17 +49,16 @@ impl Actor for PostStart { impl Handler for PostStart { type Result = (); - fn handle(&mut self, _msg: PocketIcProxyReadySignal, _ctx: &mut Self::Context) -> Self::Result { + fn handle(&mut self, msg: PocketIcProxyReadySignal, _ctx: &mut Self::Context) -> Self::Result { let logger = &self.config.logger; + let address = msg.0; + self.spinner.finish_and_clear(); if self.config.background { - info!( - logger, - "Success! The dfx server is running in the background." - ) + info!(logger, "Replica API running in the background on {address}"); } else { info!( logger, - "Success! The dfx server is running.\nYou must open a new terminal to continue developing. If you'd prefer to stop, quit with 'Ctrl-C'." + "Replica API running on {address}. You must open a new terminal to continue developing. If you'd prefer to stop, quit with 'Ctrl-C'." ) } } diff --git a/src/dfx/src/actors/replica.rs b/src/dfx/src/actors/replica.rs index 841827330b..888ce5a87d 100644 --- a/src/dfx/src/actors/replica.rs +++ b/src/dfx/src/actors/replica.rs @@ -18,7 +18,7 @@ use actix::{ use anyhow::bail; use crossbeam::channel::{unbounded, Receiver, Sender}; use dfx_core::config::model::replica_config::ReplicaConfig; -use slog::{debug, error, info, Logger}; +use slog::{debug, error, Logger}; use std::path::{Path, PathBuf}; use std::thread::JoinHandle; use std::time::Duration; @@ -220,10 +220,10 @@ impl Actor for Replica { } fn stopping(&mut self, _ctx: &mut Self::Context) -> Running { - info!(self.logger, "Stopping the replica..."); + debug!(self.logger, "Stopping the replica..."); self.stop_replica(); - info!(self.logger, "Stopped."); + debug!(self.logger, "Stopped."); Running::Stop } } @@ -466,7 +466,7 @@ async fn initialize_replica( initialize_bitcoin_canister(&agent, &logger, bitcoin_integration_config).await?; } - info!(logger, "Initialized replica."); + debug!(logger, "Initialized replica."); Ok(()) } diff --git a/src/dfx/src/actors/shutdown_controller.rs b/src/dfx/src/actors/shutdown_controller.rs index d016d904f5..01eb24a77a 100644 --- a/src/dfx/src/actors/shutdown_controller.rs +++ b/src/dfx/src/actors/shutdown_controller.rs @@ -1,7 +1,7 @@ use crate::actors::shutdown_controller::signals::outbound::Shutdown; use crate::actors::shutdown_controller::signals::ShutdownTrigger; use actix::{Actor, Addr, AsyncContext, Context, Handler, Recipient}; -use slog::Logger; +use slog::{info, Logger}; use std::time::Duration; pub mod signals { @@ -29,7 +29,7 @@ pub struct Config { } pub struct ShutdownController { - _logger: Logger, + logger: Logger, shutdown_subscribers: Vec>, } @@ -39,7 +39,7 @@ impl ShutdownController { let logger = (config.logger.clone()).unwrap_or_else(|| Logger::root(slog::Discard, slog::o!())); ShutdownController { - _logger: logger, + logger, shutdown_subscribers: Vec::new(), } } @@ -56,10 +56,12 @@ impl ShutdownController { .map(|recipient| recipient.send(Shutdown {})) .map(|response| response.then(|_| future::ok::<(), ()>(()))) .collect(); + let subscribers = self.shutdown_subscribers.clone(); + let logger = self.logger.clone(); futures::future::join_all(futures) .into_actor(self) - .then(|_, _, ctx| { + .then(move |_, _, ctx| { // Once all shutdowns have completed, we can schedule a stop of the actix system. It is // performed with a slight delay to give pending synced futures a chance to perform their // error handlers. @@ -69,7 +71,10 @@ impl ShutdownController { // be able to print error messages. let when = Duration::from_secs(0) + Duration::from_millis(100); - ctx.run_later(when, |_, _| { + ctx.run_later(when, move |_, _| { + if !subscribers.iter().any(|s| s.connected()) { + info!(logger, "All local network processes stopped"); + } System::current().stop(); }); diff --git a/src/dfx/src/commands/start.rs b/src/dfx/src/commands/start.rs index 083ccd3a05..3533d857e1 100644 --- a/src/dfx/src/commands/start.rs +++ b/src/dfx/src/commands/start.rs @@ -360,7 +360,7 @@ pub fn exec( save_json_file(&previous_config_path, &effective_config)?; let network_descriptor = network_descriptor.clone(); - + let spinner = env.new_spinner("Starting local network...".into()); let system = actix::System::new(); let _proxy = system.block_on(async move { let shutdown_controller = start_shutdown_controller(env)?; @@ -425,7 +425,7 @@ pub fn exec( pocketic_proxy_port_file_path, )?; - let post_start = start_post_start_actor(env, running_in_background, Some(proxy))?; + let post_start = start_post_start_actor(env, running_in_background, Some(proxy), spinner)?; Ok::<_, Error>(post_start) })?;