WIP - Start work on reconnect logic

This commit is contained in:
Max Brunsfeld
2021-09-08 18:20:32 -07:00
parent edbd424b75
commit 6baa9fe37b
2 changed files with 82 additions and 4 deletions
+65
View File
@@ -653,4 +653,69 @@ mod tests {
);
});
}
#[gpui::test]
async fn test_channel_reconnect(mut cx: TestAppContext) {
let user_id = 5;
let mut client = Client::new();
let server = FakeServer::for_client(user_id, &mut client, &cx).await;
let user_store = Arc::new(UserStore::new(client.clone()));
let channel = cx.add_model(|cx| {
Channel::new(
ChannelDetails {
id: 1,
name: "general".into(),
},
user_store,
client.clone(),
cx,
)
});
let join_channel = server.receive::<proto::JoinChannel>().await.unwrap();
server
.respond(
join_channel.receipt(),
proto::JoinChannelResponse {
messages: vec![
proto::ChannelMessage {
id: 10,
body: "a".into(),
timestamp: 1000,
sender_id: 5,
},
proto::ChannelMessage {
id: 11,
body: "b".into(),
timestamp: 1001,
sender_id: 5,
},
],
done: false,
},
)
.await;
let get_users = server.receive::<proto::GetUsers>().await.unwrap();
assert_eq!(get_users.payload.user_ids, vec![5]);
server
.respond(
get_users.receipt(),
proto::GetUsersResponse {
users: vec![proto::User {
id: 5,
github_login: "nathansobo".into(),
avatar_url: "http://avatar.com/nathansobo".into(),
}],
},
)
.await;
// Disconnect, wait for the client to reconnect.
server.disconnect().await;
cx.foreground().advance_clock(Duration::from_secs(10));
let get_messages = server.receive::<proto::GetChannelMessages>().await.unwrap();
}
}
+17 -4
View File
@@ -146,14 +146,27 @@ impl Client {
}));
}
Status::ConnectionLost => {
state._maintain_connection = Some(cx.foreground().spawn(async move {
// TODO: try to reconnect
let this = self.clone();
let foreground = cx.foreground();
state._maintain_connection = Some(cx.spawn(|cx| async move {
let mut delay_seconds = 5;
while let Err(error) = this.authenticate_and_connect(&cx).await {
log::error!("failed to connect {}", error);
let delay = Duration::from_secs(delay_seconds);
this.set_status(
Status::ReconnectionError {
next_reconnection: Instant::now() + delay,
},
&cx,
);
foreground.sleep(delay).await;
delay_seconds = (delay_seconds * 2).min(300);
}
}));
}
Status::Disconnected => {
_ => {
state._maintain_connection.take();
}
_ => {}
}
}