Skip to content

Commit

Permalink
feat(next/dev): allow to retry bind (#2480)
Browse files Browse the repository at this point in the history
  • Loading branch information
kwonoj committed Oct 30, 2022
1 parent 1fee821 commit 85ce6ce
Showing 1 changed file with 79 additions and 22 deletions.
101 changes: 79 additions & 22 deletions crates/next-dev/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::{
collections::HashSet,
env::current_dir,
future::join,
net::IpAddr,
net::{IpAddr, SocketAddr},
path::MAIN_SEPARATOR,
sync::Arc,
time::{Duration, Instant},
Expand Down Expand Up @@ -52,6 +52,7 @@ pub struct NextDevServerBuilder {
log_level: IssueSeverity,
show_all: bool,
log_detail: bool,
allow_retry: bool,
}

impl NextDevServerBuilder {
Expand All @@ -75,6 +76,7 @@ impl NextDevServerBuilder {
log_level: IssueSeverity::Warning,
show_all: false,
log_detail: false,
allow_retry: false,
}
}

Expand Down Expand Up @@ -118,6 +120,11 @@ impl NextDevServerBuilder {
self
}

pub fn allow_retry(mut self, allow_retry: bool) -> NextDevServerBuilder {
self.allow_retry = allow_retry;
self
}

pub fn log_detail(mut self, log_detail: bool) -> NextDevServerBuilder {
self.log_detail = log_detail;
self
Expand All @@ -143,29 +150,78 @@ impl NextDevServerBuilder {
let console_ui = Arc::new(ConsoleUi::new(log_options));
let console_ui_to_dev_server = console_ui.clone();

let server = DevServer::listen(
turbo_tasks.clone(),
move || {
source(
root_dir.clone(),
project_dir.clone(),
entry_requests.clone(),
eager_compile,
turbo_tasks.clone().into(),
console_ui.clone().into(),
browserslist_query.clone(),
server_component_externals.clone(),
)
},
(
self.hostname.context("hostname must be set")?,
self.port.context("port must be set")?,
let start_port = self.port.context("port must be set")?;
let host = self.hostname.context("hostname must be set")?;

let mut err: Option<anyhow::Error> = None;

let tasks = turbo_tasks.clone();
let source = move || {
source(
root_dir.clone(),
project_dir.clone(),
entry_requests.clone(),
eager_compile,
turbo_tasks.clone().into(),
console_ui.clone().into(),
browserslist_query.clone(),
server_component_externals.clone(),
)
.into(),
console_ui_to_dev_server,
);
};

// Retry to listen on the different port if the port is already in use.
for retry_count in 0..10 {
let current_port = start_port + retry_count;
let addr = SocketAddr::new(host, current_port);

let listen_result = DevServer::listen(
tasks.clone(),
source.clone(),
addr,
console_ui_to_dev_server.clone(),
);

match listen_result {
Ok(server) => {
return Ok(server);
}
Err(e) => {
let should_retry = if self.allow_retry {
// Returned error from `listen` is not `std::io::Error` but `anyhow::Error`,
// so we need to access its source to check if it is
// `std::io::ErrorKind::AddrInUse`.
e.source()
.map(|e| {
e.source()
.map(|e| {
e.downcast_ref::<std::io::Error>()
.map(|e| e.kind() == std::io::ErrorKind::AddrInUse)
== Some(true)
})
.unwrap_or_else(|| false)
})
.unwrap_or_else(|| false)
} else {
false
};

if !should_retry {
return Err(e);
} else {
println!(
"{} - Port {} is in use, trying {} instead",
"warn ".yellow(),
current_port,
current_port + 1
);
}

err = Some(e);
}
}
}

server
Err(err.expect("Should have an error if we get here"))
}
}

Expand Down Expand Up @@ -331,6 +387,7 @@ pub async fn start_server(options: &DevServerOptions) -> Result<()> {
.port(options.port)
.log_detail(options.log_detail)
.show_all(options.show_all)
.allow_retry(options.allow_retry)
.log_level(
options
.log_level
Expand Down

0 comments on commit 85ce6ce

Please sign in to comment.