Skip to content

Commit

Permalink
Add PostStart actor after PocketIcProxy actor to output info messages.
Browse files Browse the repository at this point in the history
  • Loading branch information
vincent-dfinity committed Oct 9, 2024
1 parent 1179330 commit 95f32db
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 7 deletions.
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 @@ -213,3 +215,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
56 changes: 56 additions & 0 deletions src/dfx/src/actors/post_start.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use crate::actors::post_start::signals::{PocketIcProxyReadySignal, PocketIcProxyReadySubscribe};
use crate::actors::pocketic_proxy::PocketIcProxy;
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, "The dfx server is running in the background.")
} else {
info!(logger, "The dfx server is running.\nYou can start a new terminal to continue developing, or quit with 'Ctrl-C'.");
}
}
}
15 changes: 12 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 @@ -264,6 +265,10 @@ pub fn exec(
}
local_server_descriptor.describe(env.get_logger());

// Get the original background flag set by the user from the command arguments.
// Get it from the environment variable as the `--background` flag will be ignored by the send_background() method.
let original_background = std::env::var("original_background").is_ok();

write_pid(&pid_file_path);
fs::write(&webserver_port_path, address_and_port.port().to_string())?;

Expand Down Expand Up @@ -413,7 +418,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, original_background, Some(proxy))?;

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

Expand Down Expand Up @@ -574,7 +582,8 @@ fn send_background() -> DfxResult<()> {
.skip(1)
.filter(|a| !a.eq("--background"))
.filter(|a| !a.eq("--clean")),
);
)
.env("original_background", "true"); // Set the `original_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 95f32db

Please sign in to comment.