Leave room when Room
entity is dropped
This commit is contained in:
parent
573086eed2
commit
e55e7e4844
6 changed files with 89 additions and 20 deletions
|
@ -62,7 +62,7 @@ fn init_logger() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gpui::test(iterations = 10)]
|
#[gpui::test(iterations = 10)]
|
||||||
async fn test_share_project_in_room(
|
async fn test_basic_calls(
|
||||||
deterministic: Arc<Deterministic>,
|
deterministic: Arc<Deterministic>,
|
||||||
cx_a: &mut TestAppContext,
|
cx_a: &mut TestAppContext,
|
||||||
cx_b: &mut TestAppContext,
|
cx_b: &mut TestAppContext,
|
||||||
|
@ -111,6 +111,7 @@ async fn test_share_project_in_room(
|
||||||
let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
|
let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
|
||||||
// room.publish_project(project_a.clone()).await.unwrap();
|
// room.publish_project(project_a.clone()).await.unwrap();
|
||||||
|
|
||||||
|
// Call user B from client A.
|
||||||
let mut incoming_call_b = client_b
|
let mut incoming_call_b = client_b
|
||||||
.user_store
|
.user_store
|
||||||
.update(cx_b, |user, _| user.incoming_call());
|
.update(cx_b, |user, _| user.incoming_call());
|
||||||
|
@ -128,6 +129,7 @@ async fn test_share_project_in_room(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// User B receives the call and joins the room.
|
||||||
let call_b = incoming_call_b.next().await.unwrap().unwrap();
|
let call_b = incoming_call_b.next().await.unwrap().unwrap();
|
||||||
let room_b = cx_b
|
let room_b = cx_b
|
||||||
.update(|cx| Room::join(&call_b, client_b.clone(), cx))
|
.update(|cx| Room::join(&call_b, client_b.clone(), cx))
|
||||||
|
@ -151,11 +153,12 @@ async fn test_share_project_in_room(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Call user C from client B.
|
||||||
let mut incoming_call_c = client_c
|
let mut incoming_call_c = client_c
|
||||||
.user_store
|
.user_store
|
||||||
.update(cx_c, |user, _| user.incoming_call());
|
.update(cx_c, |user, _| user.incoming_call());
|
||||||
room_a
|
room_b
|
||||||
.update(cx_a, |room, cx| room.call(client_c.user_id().unwrap(), cx))
|
.update(cx_b, |room, cx| room.call(client_c.user_id().unwrap(), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -175,6 +178,7 @@ async fn test_share_project_in_room(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// User C receives the call, but declines it.
|
||||||
let _call_c = incoming_call_c.next().await.unwrap().unwrap();
|
let _call_c = incoming_call_c.next().await.unwrap().unwrap();
|
||||||
client_c
|
client_c
|
||||||
.user_store
|
.user_store
|
||||||
|
@ -198,6 +202,17 @@ async fn test_share_project_in_room(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// User A leaves the room.
|
||||||
|
cx_a.update(|_| drop(room_a));
|
||||||
|
deterministic.run_until_parked();
|
||||||
|
assert_eq!(
|
||||||
|
participants(&room_b, &client_b, cx_b).await,
|
||||||
|
RoomParticipants {
|
||||||
|
remote: Default::default(),
|
||||||
|
pending: Default::default()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
struct RoomParticipants {
|
struct RoomParticipants {
|
||||||
remote: Vec<String>,
|
remote: Vec<String>,
|
||||||
|
|
|
@ -153,6 +153,7 @@ impl Server {
|
||||||
.add_request_handler(Server::ping)
|
.add_request_handler(Server::ping)
|
||||||
.add_request_handler(Server::create_room)
|
.add_request_handler(Server::create_room)
|
||||||
.add_request_handler(Server::join_room)
|
.add_request_handler(Server::join_room)
|
||||||
|
.add_message_handler(Server::leave_room)
|
||||||
.add_request_handler(Server::call)
|
.add_request_handler(Server::call)
|
||||||
.add_message_handler(Server::decline_call)
|
.add_message_handler(Server::decline_call)
|
||||||
.add_request_handler(Server::register_project)
|
.add_request_handler(Server::register_project)
|
||||||
|
@ -627,6 +628,14 @@ impl Server {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn leave_room(self: Arc<Server>, message: TypedEnvelope<proto::LeaveRoom>) -> Result<()> {
|
||||||
|
let room_id = message.payload.id;
|
||||||
|
let mut store = self.store().await;
|
||||||
|
let room = store.leave_room(room_id, message.sender_id)?;
|
||||||
|
self.room_updated(room);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
async fn call(
|
async fn call(
|
||||||
self: Arc<Server>,
|
self: Arc<Server>,
|
||||||
request: TypedEnvelope<proto::Call>,
|
request: TypedEnvelope<proto::Call>,
|
||||||
|
|
|
@ -38,7 +38,7 @@ struct ConnectionState {
|
||||||
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Serialize)]
|
#[derive(Copy, Clone, Eq, PartialEq, Serialize)]
|
||||||
enum RoomState {
|
enum RoomState {
|
||||||
Joined,
|
Joined { room_id: RoomId },
|
||||||
Calling { room_id: RoomId },
|
Calling { room_id: RoomId },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,13 +370,13 @@ impl Store {
|
||||||
|
|
||||||
let room_id = post_inc(&mut self.next_room_id);
|
let room_id = post_inc(&mut self.next_room_id);
|
||||||
self.rooms.insert(room_id, room);
|
self.rooms.insert(room_id, room);
|
||||||
user_connection_state.room = Some(RoomState::Joined);
|
user_connection_state.room = Some(RoomState::Joined { room_id });
|
||||||
Ok(room_id)
|
Ok(room_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn join_room(
|
pub fn join_room(
|
||||||
&mut self,
|
&mut self,
|
||||||
room_id: u64,
|
room_id: RoomId,
|
||||||
connection_id: ConnectionId,
|
connection_id: ConnectionId,
|
||||||
) -> Result<(&proto::Room, Vec<ConnectionId>)> {
|
) -> Result<(&proto::Room, Vec<ConnectionId>)> {
|
||||||
let connection = self
|
let connection = self
|
||||||
|
@ -417,11 +417,44 @@ impl Store {
|
||||||
)),
|
)),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
user_connection_state.room = Some(RoomState::Joined);
|
user_connection_state.room = Some(RoomState::Joined { room_id });
|
||||||
|
|
||||||
Ok((room, recipient_connection_ids))
|
Ok((room, recipient_connection_ids))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn leave_room(
|
||||||
|
&mut self,
|
||||||
|
room_id: RoomId,
|
||||||
|
connection_id: ConnectionId,
|
||||||
|
) -> Result<&proto::Room> {
|
||||||
|
let connection = self
|
||||||
|
.connections
|
||||||
|
.get_mut(&connection_id)
|
||||||
|
.ok_or_else(|| anyhow!("no such connection"))?;
|
||||||
|
let user_id = connection.user_id;
|
||||||
|
|
||||||
|
let mut user_connection_state = self
|
||||||
|
.connections_by_user_id
|
||||||
|
.get_mut(&user_id)
|
||||||
|
.ok_or_else(|| anyhow!("no such connection"))?;
|
||||||
|
anyhow::ensure!(
|
||||||
|
user_connection_state
|
||||||
|
.room
|
||||||
|
.map_or(false, |room| room == RoomState::Joined { room_id }),
|
||||||
|
"cannot leave a room before joining it"
|
||||||
|
);
|
||||||
|
|
||||||
|
let room = self
|
||||||
|
.rooms
|
||||||
|
.get_mut(&room_id)
|
||||||
|
.ok_or_else(|| anyhow!("no such room"))?;
|
||||||
|
room.participants
|
||||||
|
.retain(|participant| participant.peer_id != connection_id.0);
|
||||||
|
user_connection_state.room = None;
|
||||||
|
|
||||||
|
Ok(room)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn call(
|
pub fn call(
|
||||||
&mut self,
|
&mut self,
|
||||||
room_id: RoomId,
|
room_id: RoomId,
|
||||||
|
|
|
@ -31,6 +31,19 @@ impl Entity for Room {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Room {
|
impl Room {
|
||||||
|
fn new(id: u64, client: Arc<Client>, cx: &mut ModelContext<Self>) -> Self {
|
||||||
|
Self {
|
||||||
|
id,
|
||||||
|
local_participant: LocalParticipant {
|
||||||
|
projects: Default::default(),
|
||||||
|
},
|
||||||
|
remote_participants: Default::default(),
|
||||||
|
pending_user_ids: Default::default(),
|
||||||
|
_subscriptions: vec![client.add_message_handler(cx.handle(), Self::handle_room_updated)],
|
||||||
|
client,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create(
|
pub fn create(
|
||||||
client: Arc<Client>,
|
client: Arc<Client>,
|
||||||
cx: &mut MutableAppContext,
|
cx: &mut MutableAppContext,
|
||||||
|
@ -56,19 +69,6 @@ impl Room {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new(id: u64, client: Arc<Client>, cx: &mut ModelContext<Self>) -> Self {
|
|
||||||
Self {
|
|
||||||
id,
|
|
||||||
local_participant: LocalParticipant {
|
|
||||||
projects: Default::default(),
|
|
||||||
},
|
|
||||||
remote_participants: Default::default(),
|
|
||||||
pending_user_ids: Default::default(),
|
|
||||||
_subscriptions: vec![client.add_message_handler(cx.handle(), Self::handle_room_updated)],
|
|
||||||
client,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn remote_participants(&self) -> &HashMap<PeerId, RemoteParticipant> {
|
pub fn remote_participants(&self) -> &HashMap<PeerId, RemoteParticipant> {
|
||||||
&self.remote_participants
|
&self.remote_participants
|
||||||
}
|
}
|
||||||
|
@ -148,3 +148,9 @@ impl Room {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Drop for Room {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
let _ = self.client.send(proto::LeaveRoom { id: self.id });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ message Envelope {
|
||||||
CreateRoomResponse create_room_response = 9;
|
CreateRoomResponse create_room_response = 9;
|
||||||
JoinRoom join_room = 10;
|
JoinRoom join_room = 10;
|
||||||
JoinRoomResponse join_room_response = 11;
|
JoinRoomResponse join_room_response = 11;
|
||||||
|
LeaveRoom leave_room = 1002;
|
||||||
Call call = 12;
|
Call call = 12;
|
||||||
IncomingCall incoming_call = 1000;
|
IncomingCall incoming_call = 1000;
|
||||||
CancelCall cancel_call = 1001;
|
CancelCall cancel_call = 1001;
|
||||||
|
@ -149,6 +150,10 @@ message JoinRoomResponse {
|
||||||
Room room = 1;
|
Room room = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message LeaveRoom {
|
||||||
|
uint64 id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
message Room {
|
message Room {
|
||||||
repeated Participant participants = 1;
|
repeated Participant participants = 1;
|
||||||
repeated uint64 pending_user_ids = 2;
|
repeated uint64 pending_user_ids = 2;
|
||||||
|
|
|
@ -131,6 +131,7 @@ messages!(
|
||||||
(JoinRoomResponse, Foreground),
|
(JoinRoomResponse, Foreground),
|
||||||
(LeaveChannel, Foreground),
|
(LeaveChannel, Foreground),
|
||||||
(LeaveProject, Foreground),
|
(LeaveProject, Foreground),
|
||||||
|
(LeaveRoom, Foreground),
|
||||||
(OpenBufferById, Background),
|
(OpenBufferById, Background),
|
||||||
(OpenBufferByPath, Background),
|
(OpenBufferByPath, Background),
|
||||||
(OpenBufferForSymbol, Background),
|
(OpenBufferForSymbol, Background),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue