fix(web_ui): cap bind_with_retry at 12 attempts, then return AddrInUse
This commit is contained in:
parent
bdfeac80a7
commit
7c851c5dd3
1 changed files with 17 additions and 15 deletions
|
|
@ -192,12 +192,16 @@ fn bind_unix(path: &Path) -> Result<tokio::net::UnixListener> {
|
|||
Ok(listener)
|
||||
}
|
||||
|
||||
/// Bind a TCP listener with `SO_REUSEADDR` set, retrying on
|
||||
/// `AddrInUse` indefinitely with exponential backoff capped at 2s.
|
||||
/// First 12 attempts log at WARN; subsequent attempts log at INFO so
|
||||
/// a long-held stale socket doesn't flood the journal.
|
||||
/// Maximum bind attempts before `bind_with_retry` gives up on `AddrInUse`.
|
||||
const MAX_BIND_ATTEMPTS: u32 = 12;
|
||||
|
||||
/// Bind a TCP listener with `SO_REUSEADDR` set, retrying on `AddrInUse` with
|
||||
/// exponential backoff capped at 2s, up to [`MAX_BIND_ATTEMPTS`] attempts. If
|
||||
/// the port is still held after the final attempt, returns the `AddrInUse`
|
||||
/// error rather than looping forever (a genuine collision needs the operator,
|
||||
/// not an unbounded wait).
|
||||
///
|
||||
/// Uncapped retry + dashboard-banner-on-real-collision rationale:
|
||||
/// Retry rationale + dashboard-banner-on-real-collision:
|
||||
/// see [`docs/web-ui/shape.md::Listener bind`](../../../docs/web-ui/shape.md).
|
||||
async fn bind_with_retry(addr: SocketAddr, label: &str) -> Result<tokio::net::TcpListener> {
|
||||
let mut delay_ms = 250u64;
|
||||
|
|
@ -215,17 +219,15 @@ async fn bind_with_retry(addr: SocketAddr, label: &str) -> Result<tokio::net::Tc
|
|||
}
|
||||
Err(e) if e.kind() == std::io::ErrorKind::AddrInUse => {
|
||||
let attempt = attempts + 1;
|
||||
if attempt <= 12 {
|
||||
tracing::warn!(
|
||||
%addr, attempt,
|
||||
"{label}: AddrInUse, retrying in {delay_ms}ms"
|
||||
);
|
||||
} else {
|
||||
tracing::info!(
|
||||
%addr, attempt,
|
||||
"{label}: AddrInUse still holding, retrying in {delay_ms}ms"
|
||||
);
|
||||
if attempt >= MAX_BIND_ATTEMPTS {
|
||||
return Err(e).with_context(|| {
|
||||
format!("bind {label} on {addr}: still AddrInUse after {attempt} attempts")
|
||||
});
|
||||
}
|
||||
tracing::warn!(
|
||||
%addr, attempt,
|
||||
"{label}: AddrInUse, retrying in {delay_ms}ms"
|
||||
);
|
||||
tokio::time::sleep(std::time::Duration::from_millis(delay_ms)).await;
|
||||
attempts += 1;
|
||||
delay_ms = (delay_ms * 2).min(2000);
|
||||
|
|
|
|||
Loading…
Reference in a new issue