ssh remote: Handle disconnect on project and show overlay (#19014)

Demo:



https://github.com/user-attachments/assets/e5edf8f3-8c15-482e-a792-6eb619f83de4


Release Notes:

- N/A

---------

Co-authored-by: Bennet <bennet@zed.dev>
This commit is contained in:
Thorsten Ball 2024-10-10 12:59:09 +02:00 committed by GitHub
parent e3ff2ced79
commit b75532fad7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 264 additions and 78 deletions

View file

@ -5,4 +5,5 @@ pub mod ssh_session;
pub use ssh_session::{
ConnectionState, SshClientDelegate, SshConnectionOptions, SshPlatform, SshRemoteClient,
SshRemoteEvent,
};

View file

@ -17,7 +17,8 @@ use futures::{
StreamExt as _,
};
use gpui::{
AppContext, AsyncAppContext, Context, Model, ModelContext, SemanticVersion, Task, WeakModel,
AppContext, AsyncAppContext, Context, EventEmitter, Model, ModelContext, SemanticVersion, Task,
WeakModel,
};
use parking_lot::Mutex;
use rpc::{
@ -315,6 +316,10 @@ impl State {
matches!(self, Self::ReconnectFailed { .. })
}
fn is_reconnect_exhausted(&self) -> bool {
matches!(self, Self::ReconnectExhausted { .. })
}
fn is_reconnecting(&self) -> bool {
matches!(self, Self::Reconnecting { .. })
}
@ -376,7 +381,7 @@ impl State {
}
/// The state of the ssh connection.
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ConnectionState {
Connecting,
Connected,
@ -411,6 +416,13 @@ impl Drop for SshRemoteClient {
}
}
#[derive(Debug)]
pub enum SshRemoteEvent {
Disconnected,
}
impl EventEmitter<SshRemoteEvent> for SshRemoteClient {}
impl SshRemoteClient {
pub fn new(
unique_identifier: String,
@ -672,6 +684,9 @@ impl SshRemoteClient {
if this.state_is(State::is_reconnect_failed) {
this.reconnect(cx)
} else if this.state_is(State::is_reconnect_exhausted) {
cx.emit(SshRemoteEvent::Disconnected);
Ok(())
} else {
log::debug!("State has transition from Reconnecting into new state while attempting reconnect. Ignoring new state.");
Ok(())
@ -851,11 +866,15 @@ impl SshRemoteClient {
log::error!("failed to reconnect because server is not running");
this.update(&mut cx, |this, cx| {
this.set_state(State::ServerNotRunning, cx);
cx.emit(SshRemoteEvent::Disconnected);
})?;
}
}
} else if exit_code > 0 {
log::error!("proxy process terminated unexpectedly");
this.update(&mut cx, |this, cx| {
this.reconnect(cx).ok();
})?;
}
}
Ok(None) => {}
@ -963,6 +982,11 @@ impl SshRemoteClient {
self.connection_options.connection_string()
}
pub fn connection_options(&self) -> SshConnectionOptions {
self.connection_options.clone()
}
#[cfg(not(any(test, feature = "test-support")))]
pub fn connection_state(&self) -> ConnectionState {
self.state
.lock()
@ -971,6 +995,15 @@ impl SshRemoteClient {
.unwrap_or(ConnectionState::Disconnected)
}
#[cfg(any(test, feature = "test-support"))]
pub fn connection_state(&self) -> ConnectionState {
ConnectionState::Connected
}
pub fn is_disconnected(&self) -> bool {
self.connection_state() == ConnectionState::Disconnected
}
#[cfg(any(test, feature = "test-support"))]
pub fn fake(
client_cx: &mut gpui::TestAppContext,