diff --git a/src/args.rs b/src/args.rs index b921f71..1decc11 100644 --- a/src/args.rs +++ b/src/args.rs @@ -165,7 +165,9 @@ pub struct DeployAndWaitArgs { #[arg(long = "observer-host")] pub observer_host: Option, - /// Observer node gRPC port for finalization checks (falls back to 40452 if not specified) + /// Observer node gRPC port for finalization checks (falls back to 40452 if not specified). + /// The observer HTTP port is this value + 1. For a standalone node (no separate observer), + /// pass an observer port whose +1 equals the node's HTTP port. #[arg(long = "observer-port")] pub observer_port: Option, @@ -569,7 +571,9 @@ pub struct BondValidatorArgs { #[arg(long = "observer-host")] pub observer_host: Option, - /// Observer node gRPC port for finalization checks (falls back to 40452 if not specified) + /// Observer node gRPC port for finalization checks (falls back to 40452 if not specified). + /// The observer HTTP port is this value + 1. For a standalone node (no separate observer), + /// pass an observer port whose +1 equals the node's HTTP port. #[arg(long = "observer-port")] pub observer_port: Option, @@ -666,7 +670,9 @@ pub struct TransferArgs { #[arg(long = "observer-host")] pub observer_host: Option, - /// Observer node gRPC port for finalization checks (falls back to 40452 if not specified) + /// Observer node gRPC port for finalization checks (falls back to 40452 if not specified). + /// The observer HTTP port is this value + 1. For a standalone node (no separate observer), + /// pass an observer port whose +1 equals the node's HTTP port. #[arg(long = "observer-port")] pub observer_port: Option, diff --git a/src/connection_manager.rs b/src/connection_manager.rs index 2b04048..8b19f9e 100644 --- a/src/connection_manager.rs +++ b/src/connection_manager.rs @@ -268,38 +268,73 @@ impl F1r3flyConnectionManager { total_timeout_secs: u64, poll_interval_secs: u64, ) -> Result, ConnectionError> { - let api = self.observer_api()?; + let observer_api = self.observer_api()?; + let node_api = self.api(); let http_port = self.observer_http_port(); let max_attempts = (total_timeout_secs / poll_interval_secs.max(1)).max(1) as u32; for attempt in 1..=max_attempts { - match api + match observer_api .deploy_finalization_status(deploy_sig_hex, http_port) .await { - Ok(Some(status)) => { - if status.is_terminal() { - tracing::debug!( - deploy_sig = deploy_sig_hex, - state = %status.state, - attempt, - "Deploy reached terminal state" - ); - return Ok(Some(status)); - } + Ok(Some(status)) if status.is_terminal() => { + tracing::debug!( + deploy_sig = deploy_sig_hex, + state = %status.state, + attempt, + "Deploy reached terminal state" + ); + return Ok(Some(status)); } + // Non-terminal status — keep polling to the next attempt. + Ok(Some(_)) => {} Ok(None) => { // 404 — endpoint not available on this node version. // Caller falls back to legacy flow. return Ok(None); } Err(e) => { - tracing::warn!( - deploy_sig = deploy_sig_hex, - attempt, - error = %e, - "deploy-finalization-status query failed; will retry" - ); + // Observer is unavailable => fallback to deploy-node (its HTTP port). + match &node_api { + Ok(na) => { + match na + .deploy_finalization_status(deploy_sig_hex, self.config.http_port) + .await + { + Ok(Some(status)) if status.is_terminal() => { + tracing::debug!( + deploy_sig = deploy_sig_hex, + state = %status.state, + attempt, + "Deploy reached terminal state (node API)" + ); + return Ok(Some(status)); + } + // Non-terminal status from node API is expected while polling. + // Keep silent and continue to the next poll attempt. + Ok(Some(_)) => {} + Ok(None) => return Ok(None), + Err(node_err) => { + tracing::warn!( + deploy_sig = deploy_sig_hex, + attempt, + observer_error = %e, + node_error = %node_err, + "deploy-finalization-status failed on observer and fallback node; will retry" + ); + } + } + } + Err(_) => { + tracing::warn!( + deploy_sig = deploy_sig_hex, + attempt, + observer_error = %e, + "deploy-finalization-status failed on observer and no fallback node connection; will retry" + ); + } + } } }