Skip to content
Open
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
96 changes: 65 additions & 31 deletions crates/cli/src/subcommands/dev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -751,7 +751,7 @@ pub async fn exec(mut config: Config, args: &ArgMatches) -> Result<(), anyhow::E
.and_then(|c| c.get_one::<String>("server").ok().flatten());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let server_for_client = server_opt_client.as_deref().unwrap_or(resolved_server);
let server_host_url = config.get_host_url(Some(server_for_client))?;
let _client_handle = if let Some(ref cmd) = client_command {
let mut client_handle = if let Some(ref cmd) = client_command {
let mut child = start_client_process(cmd, &project_dir, db_name_for_client, &server_host_url)?;

// Give the process a moment to fail fast (e.g., command not found, missing deps)
Expand Down Expand Up @@ -802,40 +802,74 @@ pub async fn exec(mut config: Config, args: &ArgMatches) -> Result<(), anyhow::E

let mut debounce_timer;
loop {
if rx.recv().is_ok() {
debounce_timer = std::time::Instant::now();
while debounce_timer.elapsed() < Duration::from_millis(300) {
if rx.recv_timeout(Duration::from_millis(100)).is_ok() {
debounce_timer = std::time::Instant::now();
// Use recv_timeout so we can periodically check if the client process exited
match rx.recv_timeout(Duration::from_secs(1)) {
Err(std::sync::mpsc::RecvTimeoutError::Disconnected) => break Ok(()),
Ok(()) => {
debounce_timer = std::time::Instant::now();
while debounce_timer.elapsed() < Duration::from_millis(300) {
if rx.recv_timeout(Duration::from_millis(100)).is_ok() {
debounce_timer = std::time::Instant::now();
}
}
}

println!("\n{}", "File change detected, rebuilding...".yellow());
match generate_build_and_publish(
&config,
&project_dir,
loaded_config_dir.as_deref(),
&spacetimedb_dir,
&module_bindings_dir,
client_language,
clear_database,
&publish_configs,
&generate_configs_from_file,
using_spacetime_config,
server_from_cli,
force,
skip_publish,
skip_generate,
)
.await
{
Ok(_) => {}
Err(e) => {
eprintln!("{} {}", "Error:".red().bold(), e);
println!("{}", "Waiting for next change...".dimmed());
println!("\n{}", "File change detected, rebuilding...".yellow());
match generate_build_and_publish(
&config,
&project_dir,
loaded_config_dir.as_deref(),
&spacetimedb_dir,
&module_bindings_dir,
client_language,
clear_database,
&publish_configs,
&generate_configs_from_file,
using_spacetime_config,
server_from_cli,
force,
skip_publish,
skip_generate,
)
.await
{
Ok(_) => {}
Err(e) => {
eprintln!("{} {}", "Error:".red().bold(), e);
println!("{}", "Waiting for next change...".dimmed());
}
}
}
}
Err(std::sync::mpsc::RecvTimeoutError::Timeout) => {
// No rebuild yet. Check if the client process has exited.
let Some(ref mut child) = client_handle else {
continue;
};
match child.try_wait() {
Ok(None) => {}
Ok(Some(status)) => {
client_handle = None;
let code = status
.code()
.map(|c| c.to_string())
.unwrap_or_else(|| "unknown".to_string());
println!(
"\n{} {}. {}",
"Client process exited with code".yellow(),
code,
"File watcher is still active.".dimmed()
);
}
Err(e) => {
client_handle = None;
eprintln!(
"\n{} Failed to check client process status: {}",
"Warning:".yellow().bold(),
e
);
}
}
}
};
}
}

Expand Down
Loading