From 8e7f96cebc027960ed92a3e7051401d77732415a Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 11 Oct 2022 11:54:32 +0200 Subject: [PATCH] Update contacts when automatically canceling calls --- crates/collab/src/integration_tests.rs | 72 ++++++++++++++++++++++++++ crates/collab/src/rpc.rs | 30 +++++++---- 2 files changed, 91 insertions(+), 11 deletions(-) diff --git a/crates/collab/src/integration_tests.rs b/crates/collab/src/integration_tests.rs index 42c95c4b2e..27fb1a9bfb 100644 --- a/crates/collab/src/integration_tests.rs +++ b/crates/collab/src/integration_tests.rs @@ -4549,6 +4549,78 @@ async fn test_contacts( ] ); + active_call_a.update(cx_a, |call, cx| call.hang_up(cx).unwrap()); + deterministic.run_until_parked(); + assert_eq!( + contacts(&client_a, cx_a), + [ + ("user_b".to_string(), "online", "free"), + ("user_c".to_string(), "online", "free") + ] + ); + assert_eq!( + contacts(&client_b, cx_b), + [ + ("user_a".to_string(), "online", "free"), + ("user_c".to_string(), "online", "free") + ] + ); + assert_eq!( + contacts(&client_c, cx_c), + [ + ("user_a".to_string(), "online", "free"), + ("user_b".to_string(), "online", "free") + ] + ); + + active_call_a + .update(cx_a, |call, cx| { + call.invite(client_b.user_id().unwrap(), None, cx) + }) + .await + .unwrap(); + deterministic.run_until_parked(); + assert_eq!( + contacts(&client_a, cx_a), + [ + ("user_b".to_string(), "online", "busy"), + ("user_c".to_string(), "online", "free") + ] + ); + assert_eq!( + contacts(&client_b, cx_b), + [ + ("user_a".to_string(), "online", "busy"), + ("user_c".to_string(), "online", "free") + ] + ); + assert_eq!( + contacts(&client_c, cx_c), + [ + ("user_a".to_string(), "online", "busy"), + ("user_b".to_string(), "online", "busy") + ] + ); + + server.forbid_connections(); + server.disconnect_client(client_a.current_user_id(cx_a)); + deterministic.advance_clock(rpc::RECEIVE_TIMEOUT); + assert_eq!(contacts(&client_a, cx_a), []); + assert_eq!( + contacts(&client_b, cx_b), + [ + ("user_a".to_string(), "offline", "free"), + ("user_c".to_string(), "online", "free") + ] + ); + assert_eq!( + contacts(&client_c, cx_c), + [ + ("user_a".to_string(), "offline", "free"), + ("user_b".to_string(), "online", "free") + ] + ); + #[allow(clippy::type_complexity)] fn contacts( client: &TestClient, diff --git a/crates/collab/src/rpc.rs b/crates/collab/src/rpc.rs index febdfe4434..84449e79d5 100644 --- a/crates/collab/src/rpc.rs +++ b/crates/collab/src/rpc.rs @@ -22,7 +22,7 @@ use axum::{ routing::get, Extension, Router, TypedHeader, }; -use collections::HashMap; +use collections::{HashMap, HashSet}; use futures::{ channel::mpsc, future::{self, BoxFuture}, @@ -474,7 +474,7 @@ impl Server { self.peer.disconnect(connection_id); let mut projects_to_unshare = Vec::new(); - let removed_user_id; + let mut contacts_to_update = HashSet::default(); { let mut store = self.store().await; let removed_connection = store.remove_connection(connection_id)?; @@ -507,6 +507,7 @@ impl Server { self.peer .send(connection_id, proto::CallCanceled {}) .trace_err(); + contacts_to_update.extend(store.user_id_for_connection(connection_id).ok()); } if let Some(room) = removed_connection @@ -516,10 +517,12 @@ impl Server { self.room_updated(room); } - removed_user_id = removed_connection.user_id; + contacts_to_update.insert(removed_connection.user_id); }; - self.update_user_contacts(removed_user_id).await.trace_err(); + for user_id in contacts_to_update { + self.update_user_contacts(user_id).await.trace_err(); + } for project_id in projects_to_unshare { self.app_state @@ -632,11 +635,12 @@ impl Server { } async fn leave_room(self: Arc, message: TypedEnvelope) -> Result<()> { - let user_id; + let mut contacts_to_update = HashSet::default(); { let mut store = self.store().await; - user_id = store.user_id_for_connection(message.sender_id)?; + let user_id = store.user_id_for_connection(message.sender_id)?; let left_room = store.leave_room(message.payload.id, message.sender_id)?; + contacts_to_update.insert(user_id); for project in left_room.unshared_projects { for connection_id in project.connection_ids() { @@ -670,17 +674,21 @@ impl Server { } } + if let Some(room) = left_room.room { + self.room_updated(room); + } + for connection_id in left_room.canceled_call_connection_ids { self.peer .send(connection_id, proto::CallCanceled {}) .trace_err(); - } - - if let Some(room) = left_room.room { - self.room_updated(room); + contacts_to_update.extend(store.user_id_for_connection(connection_id).ok()); } } - self.update_user_contacts(user_id).await?; + + for user_id in contacts_to_update { + self.update_user_contacts(user_id).await?; + } Ok(()) }