Remove participants from live-kit rooms when they leave zed rooms

This commit is contained in:
Antonio Scandurra 2022-10-17 14:03:44 +02:00
parent c9225bb87c
commit cce00526b9
4 changed files with 71 additions and 29 deletions

View file

@ -2,6 +2,9 @@ DATABASE_URL = "postgres://postgres@localhost/zed"
HTTP_PORT = 8080
API_TOKEN = "secret"
INVITE_LINK_PREFIX = "http://localhost:3000/invites/"
LIVE_KIT_SERVER = "http://localhost:7880"
LIVE_KIT_KEY = "devkey"
LIVE_KIT_SECRET = "secret"
# HONEYCOMB_API_KEY=
# HONEYCOMB_DATASET=

View file

@ -473,6 +473,7 @@ impl Server {
let mut projects_to_unshare = Vec::new();
let mut contacts_to_update = HashSet::default();
let mut room_left = None;
{
let mut store = self.store().await;
let removed_connection = store.remove_connection(connection_id)?;
@ -501,23 +502,24 @@ impl Server {
});
}
if let Some(room) = removed_connection.room {
self.room_updated(&room);
room_left = Some(self.room_left(&room, removed_connection.user_id));
}
contacts_to_update.insert(removed_connection.user_id);
for connection_id in removed_connection.canceled_call_connection_ids {
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
.room_id
.and_then(|room_id| store.room(room_id))
{
self.room_updated(room);
}
contacts_to_update.insert(removed_connection.user_id);
};
if let Some(room_left) = room_left {
room_left.await.trace_err();
}
for user_id in contacts_to_update {
self.update_user_contacts(user_id).await.trace_err();
}
@ -682,6 +684,7 @@ impl Server {
async fn leave_room(self: Arc<Server>, message: TypedEnvelope<proto::LeaveRoom>) -> Result<()> {
let mut contacts_to_update = HashSet::default();
let room_left;
{
let mut store = self.store().await;
let user_id = store.user_id_for_connection(message.sender_id)?;
@ -720,9 +723,8 @@ impl Server {
}
}
if let Some(room) = left_room.room {
self.room_updated(room);
}
self.room_updated(&left_room.room);
room_left = self.room_left(&left_room.room, user_id);
for connection_id in left_room.canceled_call_connection_ids {
self.peer
@ -732,6 +734,7 @@ impl Server {
}
}
room_left.await.trace_err();
for user_id in contacts_to_update {
self.update_user_contacts(user_id).await?;
}
@ -880,6 +883,20 @@ impl Server {
}
}
fn room_left(&self, room: &proto::Room, user_id: UserId) -> impl Future<Output = Result<()>> {
let client = self.app_state.live_kit_client.clone();
let room_name = room.live_kit_room.clone();
async move {
if let Some(client) = client {
client
.remove_participant(room_name, user_id.to_string())
.await?;
}
Ok(())
}
}
async fn share_project(
self: Arc<Server>,
request: TypedEnvelope<proto::ShareProject>,

View file

@ -4,7 +4,7 @@ use collections::{btree_map, BTreeMap, BTreeSet, HashMap, HashSet};
use nanoid::nanoid;
use rpc::{proto, ConnectionId};
use serde::Serialize;
use std::{mem, path::PathBuf, str, time::Duration};
use std::{borrow::Cow, mem, path::PathBuf, str, time::Duration};
use time::OffsetDateTime;
use tracing::instrument;
use util::post_inc;
@ -85,12 +85,12 @@ pub struct Channel {
pub type ReplicaId = u16;
#[derive(Default)]
pub struct RemovedConnectionState {
pub struct RemovedConnectionState<'a> {
pub user_id: UserId,
pub hosted_projects: Vec<Project>,
pub guest_projects: Vec<LeftProject>,
pub contact_ids: HashSet<UserId>,
pub room_id: Option<RoomId>,
pub room: Option<Cow<'a, proto::Room>>,
pub canceled_call_connection_ids: Vec<ConnectionId>,
}
@ -103,7 +103,7 @@ pub struct LeftProject {
}
pub struct LeftRoom<'a> {
pub room: Option<&'a proto::Room>,
pub room: Cow<'a, proto::Room>,
pub unshared_projects: Vec<Project>,
pub left_projects: Vec<LeftProject>,
pub canceled_call_connection_ids: Vec<ConnectionId>,
@ -218,7 +218,7 @@ impl Store {
let left_room = self.leave_room(room_id, connection_id)?;
result.hosted_projects = left_room.unshared_projects;
result.guest_projects = left_room.left_projects;
result.room_id = Some(room_id);
result.room = Some(Cow::Owned(left_room.room.into_owned()));
result.canceled_call_connection_ids = left_room.canceled_call_connection_ids;
}
@ -495,12 +495,14 @@ impl Store {
}
});
if room.participants.is_empty() && room.pending_participant_user_ids.is_empty() {
self.rooms.remove(&room_id);
}
let room = if room.participants.is_empty() && room.pending_participant_user_ids.is_empty() {
Cow::Owned(self.rooms.remove(&room_id).unwrap())
} else {
Cow::Borrowed(self.rooms.get(&room_id).unwrap())
};
Ok(LeftRoom {
room: self.rooms.get(&room_id),
room,
unshared_projects,
left_projects,
canceled_call_connection_ids,

View file

@ -2,13 +2,14 @@ use crate::{proto, token};
use anyhow::{anyhow, Result};
use prost::Message;
use reqwest::header::CONTENT_TYPE;
use std::future::Future;
use std::{future::Future, sync::Arc};
#[derive(Clone)]
pub struct Client {
http: reqwest::Client,
uri: String,
key: String,
secret: String,
uri: Arc<str>,
key: Arc<str>,
secret: Arc<str>,
}
impl Client {
@ -19,9 +20,9 @@ impl Client {
Self {
http: reqwest::Client::new(),
uri,
key,
secret,
uri: uri.into(),
key: key.into(),
secret: secret.into(),
}
}
@ -49,7 +50,26 @@ impl Client {
proto::DeleteRoomRequest { room: name },
);
async move {
response.await?;
let _: proto::DeleteRoomResponse = response.await?;
Ok(())
}
}
pub fn remove_participant(
&self,
room: String,
identity: String,
) -> impl Future<Output = Result<()>> {
let response = self.request(
"twirp/livekit.RoomService/RemoveParticipant",
token::VideoGrant {
room_admin: Some(true),
..Default::default()
},
proto::RoomParticipantIdentity { room, identity },
);
async move {
let _: proto::RemoveParticipantResponse = response.await?;
Ok(())
}
}