Skip to content

Commit

Permalink
chore: improve dfx start messages. (#3946)
Browse files Browse the repository at this point in the history
  • Loading branch information
vincent-dfinity authored Nov 12, 2024
1 parent ba7e922 commit a08f9de
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 8 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ How to resolve the error:
Run the command with '--ic' flag if you want to manage the cycles on the mainnet.
```

### chore: improve `dfx start` messages.

For `dfx start`, show below messages to users to indicate what to do next.
```
Success! The dfx server is running.
You must open a new terminal to continue developing. If you'd prefer to stop, quit with 'Ctrl-C'.
```

# 0.24.2

### feat: Support canister log allowed viewer list
Expand Down
3 changes: 2 additions & 1 deletion e2e/tests-dfx/start.bash
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ teardown() {
}

@test "start and stop outside project" {
dfx_start
assert_command dfx_start
assert_contains "Success! The dfx server is running in the background."

mkdir subdir
cd subdir || exit 1
Expand Down
16 changes: 16 additions & 0 deletions src/dfx/src/actors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use dfx_core::config::model::replica_config::ReplicaConfig;
use fn_error_context::context;
use pocketic_proxy::signals::PortReadySubscribe;
use pocketic_proxy::{PocketIcProxy, PocketIcProxyConfig};
use post_start::PostStart;
use std::fs;
use std::path::PathBuf;

Expand All @@ -22,6 +23,7 @@ pub mod btc_adapter;
pub mod canister_http_adapter;
pub mod pocketic;
pub mod pocketic_proxy;
pub mod post_start;
pub mod replica;
mod shutdown;
pub mod shutdown_controller;
Expand Down Expand Up @@ -214,3 +216,17 @@ pub fn start_pocketic_actor(
};
Ok(pocketic::PocketIc::new(actor_config).start())
}

#[context("Failed to start PostStart actor.")]
pub fn start_post_start_actor(
env: &dyn Environment,
background: bool,
pocketic_proxy: Option<Addr<PocketIcProxy>>,
) -> DfxResult<Addr<PostStart>> {
let config = post_start::Config {
logger: env.get_logger().clone(),
background,
pocketic_proxy,
};
Ok(PostStart::new(config).start())
}
36 changes: 32 additions & 4 deletions src/dfx/src/actors/pocketic_proxy.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::actors::pocketic_proxy::signals::{PortReadySignal, PortReadySubscribe};
use crate::actors::post_start::signals::{PocketIcProxyReadySignal, PocketIcProxyReadySubscribe};
use crate::actors::shutdown::{wait_for_child_or_receiver, ChildOrReceiver};
use crate::actors::shutdown_controller::signals::outbound::Shutdown;
use crate::actors::shutdown_controller::signals::ShutdownSubscribe;
Expand Down Expand Up @@ -70,6 +71,9 @@ pub struct PocketIcProxy {

stop_sender: Option<Sender<()>>,
thread_join: Option<JoinHandle<()>>,

/// Ready Signal subscribers.
ready_subscribers: Vec<Recipient<PocketIcProxyReadySignal>>,
}

impl PocketIcProxy {
Expand All @@ -81,10 +85,11 @@ impl PocketIcProxy {
stop_sender: None,
thread_join: None,
logger,
ready_subscribers: Vec::new(),
}
}

fn start_pocketic_proxy(&mut self, replica_url: Url) -> DfxResult {
fn start_pocketic_proxy(&mut self, replica_url: Url, addr: Addr<Self>) -> DfxResult {
let logger = self.logger.clone();
let config = &self.config.pocketic_proxy_config;
let pocketic_proxy_path = self.config.pocketic_proxy_path.clone();
Expand All @@ -100,6 +105,7 @@ impl PocketIcProxy {
pocketic_proxy_path,
pocketic_proxy_pid_path,
pocketic_proxy_port_path,
addr,
receiver,
config.verbose,
config.domains.clone(),
Expand Down Expand Up @@ -164,7 +170,7 @@ impl Actor for PocketIcProxy {
.do_send(ShutdownSubscribe(ctx.address().recipient::<Shutdown>()));

if let Some(replica_url) = &self.config.pocketic_proxy_config.replica_url {
self.start_pocketic_proxy(replica_url.clone())
self.start_pocketic_proxy(replica_url.clone(), ctx.address())
.expect("Could not start PocketIC HTTP gateway");
}
}
Expand All @@ -179,7 +185,7 @@ impl Actor for PocketIcProxy {
impl Handler<PortReadySignal> for PocketIcProxy {
type Result = ();

fn handle(&mut self, msg: PortReadySignal, _ctx: &mut Self::Context) {
fn handle(&mut self, msg: PortReadySignal, ctx: &mut Self::Context) {
debug!(
self.logger,
"replica ready on {}, so re/starting HTTP gateway", msg.url
Expand All @@ -189,11 +195,29 @@ impl Handler<PortReadySignal> for PocketIcProxy {

let replica_url = Url::parse(&msg.url).unwrap();

self.start_pocketic_proxy(replica_url)
self.start_pocketic_proxy(replica_url, ctx.address())
.expect("Could not start PocketIC HTTP gateway");
}
}

impl Handler<PocketIcProxyReadySubscribe> for PocketIcProxy {
type Result = ();

fn handle(&mut self, msg: PocketIcProxyReadySubscribe, _ctx: &mut Self::Context) {
self.ready_subscribers.push(msg.0);
}
}

impl Handler<PocketIcProxyReadySignal> for PocketIcProxy {
type Result = ();

fn handle(&mut self, _msg: PocketIcProxyReadySignal, _ctx: &mut Self::Context) {
for sub in &self.ready_subscribers {
sub.do_send(PocketIcProxyReadySignal);
}
}
}

impl Handler<Shutdown> for PocketIcProxy {
type Result = ResponseActFuture<Self, Result<(), ()>>;

Expand All @@ -217,6 +241,7 @@ fn pocketic_proxy_start_thread(
pocketic_proxy_path: PathBuf,
pocketic_proxy_pid_path: PathBuf,
pocketic_proxy_port_path: PathBuf,
addr: Addr<PocketIcProxy>,
receiver: Receiver<()>,
verbose: bool,
domains: Option<Vec<String>>,
Expand Down Expand Up @@ -277,6 +302,9 @@ fn pocketic_proxy_start_thread(
}
info!(logger, "Replica API running on {address}");

// Send PocketIcProxyReadySignal to PocketIcProxy.
addr.do_send(PocketIcProxyReadySignal);

// This waits for the child to stop, or the receiver to receive a message.
// We don't restart pocket-ic if done = true.
match wait_for_child_or_receiver(&mut child, &receiver) {
Expand Down
62 changes: 62 additions & 0 deletions src/dfx/src/actors/post_start.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use crate::actors::pocketic_proxy::PocketIcProxy;
use crate::actors::post_start::signals::{PocketIcProxyReadySignal, PocketIcProxyReadySubscribe};
use actix::{Actor, Addr, AsyncContext, Context, Handler};
use slog::{info, Logger};

pub mod signals {
use actix::prelude::*;

#[derive(Message)]
#[rtype(result = "()")]
pub struct PocketIcProxyReadySignal;

#[derive(Message)]
#[rtype(result = "()")]
pub struct PocketIcProxyReadySubscribe(pub Recipient<PocketIcProxyReadySignal>);
}

pub struct Config {
pub logger: Logger,
pub background: bool,
pub pocketic_proxy: Option<Addr<PocketIcProxy>>,
}

pub struct PostStart {
config: Config,
}

impl PostStart {
pub fn new(config: Config) -> Self {
Self { config }
}
}

impl Actor for PostStart {
type Context = Context<Self>;

fn started(&mut self, ctx: &mut Self::Context) {
// Register the PostStart recipent to PocketIcProxy.
if let Some(pocketic_proxy) = &self.config.pocketic_proxy {
pocketic_proxy.do_send(PocketIcProxyReadySubscribe(ctx.address().recipient()));
}
}
}

impl Handler<PocketIcProxyReadySignal> for PostStart {
type Result = ();

fn handle(&mut self, _msg: PocketIcProxyReadySignal, _ctx: &mut Self::Context) -> Self::Result {
let logger = &self.config.logger;
if self.config.background {
info!(
logger,
"Success! The dfx server is running in the background."
)
} 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'."
)
}
}
}
16 changes: 13 additions & 3 deletions src/dfx/src/commands/start.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::actors::pocketic_proxy::{signals::PortReadySubscribe, PocketIcProxyConfig};
use crate::actors::{
start_btc_adapter_actor, start_canister_http_adapter_actor, start_pocketic_actor,
start_pocketic_proxy_actor, start_replica_actor, start_shutdown_controller,
start_pocketic_proxy_actor, start_post_start_actor, start_replica_actor,
start_shutdown_controller,
};
use crate::config::dfx_version_str;
use crate::error_invalid_argument;
Expand Down Expand Up @@ -49,6 +50,10 @@ pub struct StartOpts {
#[arg(long)]
background: bool,

/// Indicates if the actual dfx process is running in the background.
#[arg(long, env = "DFX_RUNNING_IN_BACKGROUND", hide = true)]
running_in_background: bool,

/// Cleans the state of the current project.
#[arg(long)]
clean: bool,
Expand Down Expand Up @@ -138,6 +143,7 @@ pub fn exec(
StartOpts {
host,
background,
running_in_background,
clean,
force,
bitcoin_node,
Expand Down Expand Up @@ -413,7 +419,10 @@ pub fn exec(
pocketic_proxy_pid_file_path,
pocketic_proxy_port_file_path,
)?;
Ok::<_, Error>(proxy)

let post_start = start_post_start_actor(env, running_in_background, Some(proxy))?;

Ok::<_, Error>(post_start)
})?;
system.run()?;

Expand Down Expand Up @@ -574,7 +583,8 @@ fn send_background() -> DfxResult<()> {
.skip(1)
.filter(|a| !a.eq("--background"))
.filter(|a| !a.eq("--clean")),
);
)
.env("DFX_RUNNING_IN_BACKGROUND", "true"); // Set the `DFX_RUNNING_IN_BACKGROUND` environment variable which will be used by the second start.

cmd.spawn().context("Failed to spawn child process.")?;
Ok(())
Expand Down

0 comments on commit a08f9de

Please sign in to comment.