diff options
Diffstat (limited to 'src/cli/target.rs')
| -rw-r--r-- | src/cli/target.rs | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/src/cli/target.rs b/src/cli/target.rs index 64c072f9..220410f9 100644 --- a/src/cli/target.rs +++ b/src/cli/target.rs @@ -79,6 +79,7 @@ pub(super) fn api_client() -> io::Result<ApiClient> { target.profile.id.as_str(), &target.profile.target, &target.profile.session, + true, ) .map_err(|error| { io::Error::new( @@ -98,6 +99,51 @@ pub(super) fn api_client() -> io::Result<ApiClient> { }) } +pub(super) fn server_status( + client: &ApiClient, +) -> Result<crate::api::RuntimeStatus, crate::api::client::ApiClientError> { + let probe = || { + if is_remote() { + client.status_with_timeout(std::time::Duration::from_secs(15)) + } else { + client.status() + } + }; + let error = match probe() { + Ok(status) => return Ok(status), + Err(error) => error, + }; + // Only this read-only probe may rediscover and retry. Requests that follow + // the probe must never be replayed after an ambiguous SSH failure. + TARGET.with(|target| { + let mut target = target.borrow_mut(); + let Some(target) = target.as_mut() else { + return Err(error); + }; + let Some(bridge) = target.bridge.as_ref() else { + return Err(error); + }; + let Some(failure) = bridge.reported_failure() else { + return Err(error); + }; + if !bridge.used_cached_metadata + || !crate::remote::SavedSshApiBridge::stale_metadata_failure(&failure) + { + return Err(failure.into()); + } + bridge.invalidate_metadata(); + target.bridge.take(); + target.bridge = Some(crate::remote::SavedSshApiBridge::start( + target.profile.id.as_str(), + &target.profile.target, + &target.profile.session, + false, + )?); + Ok(()) + })?; + probe() +} + pub(super) fn remote_error(error: io::Error) -> io::Error { TARGET.with(|target| { let target = target.borrow(); |
