Undo making project optional on stored follower states
Following works without a project, but following in unshared projects does not need to be replicated to other participants.
This commit is contained in:
parent
ce940da8e9
commit
e9c1ad6acd
9 changed files with 47 additions and 93 deletions
|
@ -58,7 +58,7 @@ pub struct ActiveCall {
|
||||||
_subscriptions: Vec<client::Subscription>,
|
_subscriptions: Vec<client::Subscription>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
|
||||||
struct Follower {
|
struct Follower {
|
||||||
project_id: Option<u64>,
|
project_id: Option<u64>,
|
||||||
peer_id: PeerId,
|
peer_id: PeerId,
|
||||||
|
|
|
@ -62,7 +62,7 @@ pub struct Room {
|
||||||
leave_when_empty: bool,
|
leave_when_empty: bool,
|
||||||
client: Arc<Client>,
|
client: Arc<Client>,
|
||||||
user_store: ModelHandle<UserStore>,
|
user_store: ModelHandle<UserStore>,
|
||||||
follows_by_leader_id_project_id: HashMap<(PeerId, Option<u64>), Vec<PeerId>>,
|
follows_by_leader_id_project_id: HashMap<(PeerId, u64), Vec<PeerId>>,
|
||||||
subscriptions: Vec<client::Subscription>,
|
subscriptions: Vec<client::Subscription>,
|
||||||
pending_room_update: Option<Task<()>>,
|
pending_room_update: Option<Task<()>>,
|
||||||
maintain_connection: Option<Task<Option<()>>>,
|
maintain_connection: Option<Task<Option<()>>>,
|
||||||
|
@ -584,7 +584,7 @@ impl Room {
|
||||||
|
|
||||||
pub fn followers_for(&self, leader_id: PeerId, project_id: u64) -> &[PeerId] {
|
pub fn followers_for(&self, leader_id: PeerId, project_id: u64) -> &[PeerId] {
|
||||||
self.follows_by_leader_id_project_id
|
self.follows_by_leader_id_project_id
|
||||||
.get(&(leader_id, Some(project_id)))
|
.get(&(leader_id, project_id))
|
||||||
.map_or(&[], |v| v.as_slice())
|
.map_or(&[], |v| v.as_slice())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -176,7 +176,7 @@ CREATE TABLE "servers" (
|
||||||
CREATE TABLE "followers" (
|
CREATE TABLE "followers" (
|
||||||
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
|
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
"room_id" INTEGER NOT NULL REFERENCES rooms (id) ON DELETE CASCADE,
|
"room_id" INTEGER NOT NULL REFERENCES rooms (id) ON DELETE CASCADE,
|
||||||
"project_id" INTEGER REFERENCES projects (id) ON DELETE CASCADE,
|
"project_id" INTEGER NOT NULL REFERENCES projects (id) ON DELETE CASCADE,
|
||||||
"leader_connection_server_id" INTEGER NOT NULL REFERENCES servers (id) ON DELETE CASCADE,
|
"leader_connection_server_id" INTEGER NOT NULL REFERENCES servers (id) ON DELETE CASCADE,
|
||||||
"leader_connection_id" INTEGER NOT NULL,
|
"leader_connection_id" INTEGER NOT NULL,
|
||||||
"follower_connection_server_id" INTEGER NOT NULL REFERENCES servers (id) ON DELETE CASCADE,
|
"follower_connection_server_id" INTEGER NOT NULL REFERENCES servers (id) ON DELETE CASCADE,
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
ALTER TABLE followers ALTER COLUMN project_id DROP NOT NULL;
|
|
|
@ -862,83 +862,34 @@ impl Database {
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn check_can_follow(
|
pub async fn check_room_participants(
|
||||||
&self,
|
&self,
|
||||||
room_id: RoomId,
|
room_id: RoomId,
|
||||||
project_id: Option<ProjectId>,
|
|
||||||
leader_id: ConnectionId,
|
|
||||||
follower_id: ConnectionId,
|
|
||||||
) -> Result<()> {
|
|
||||||
let mut found_leader = false;
|
|
||||||
let mut found_follower = false;
|
|
||||||
self.transaction(|tx| async move {
|
|
||||||
if let Some(project_id) = project_id {
|
|
||||||
let mut rows = project_collaborator::Entity::find()
|
|
||||||
.filter(project_collaborator::Column::ProjectId.eq(project_id))
|
|
||||||
.stream(&*tx)
|
|
||||||
.await?;
|
|
||||||
while let Some(row) = rows.next().await {
|
|
||||||
let row = row?;
|
|
||||||
let connection = row.connection();
|
|
||||||
if connection == leader_id {
|
|
||||||
found_leader = true;
|
|
||||||
} else if connection == follower_id {
|
|
||||||
found_follower = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let mut rows = room_participant::Entity::find()
|
|
||||||
.filter(room_participant::Column::RoomId.eq(room_id))
|
|
||||||
.stream(&*tx)
|
|
||||||
.await?;
|
|
||||||
while let Some(row) = rows.next().await {
|
|
||||||
let row = row?;
|
|
||||||
if let Some(connection) = row.answering_connection() {
|
|
||||||
if connection == leader_id {
|
|
||||||
found_leader = true;
|
|
||||||
} else if connection == follower_id {
|
|
||||||
found_follower = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !found_leader || !found_follower {
|
|
||||||
Err(anyhow!("not a room participant"))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn check_can_unfollow(
|
|
||||||
&self,
|
|
||||||
room_id: RoomId,
|
|
||||||
project_id: Option<ProjectId>,
|
|
||||||
leader_id: ConnectionId,
|
leader_id: ConnectionId,
|
||||||
follower_id: ConnectionId,
|
follower_id: ConnectionId,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
self.transaction(|tx| async move {
|
self.transaction(|tx| async move {
|
||||||
follower::Entity::find()
|
use room_participant::Column;
|
||||||
|
|
||||||
|
let count = room_participant::Entity::find()
|
||||||
.filter(
|
.filter(
|
||||||
Condition::all()
|
Condition::all().add(Column::RoomId.eq(room_id)).add(
|
||||||
.add(follower::Column::RoomId.eq(room_id))
|
Condition::any()
|
||||||
.add(follower::Column::ProjectId.eq(project_id))
|
.add(Column::AnsweringConnectionId.eq(leader_id.id as i32).and(
|
||||||
.add(follower::Column::LeaderConnectionId.eq(leader_id.id as i32))
|
Column::AnsweringConnectionServerId.eq(leader_id.owner_id as i32),
|
||||||
.add(follower::Column::FollowerConnectionId.eq(follower_id.id as i32))
|
))
|
||||||
.add(
|
.add(Column::AnsweringConnectionId.eq(follower_id.id as i32).and(
|
||||||
follower::Column::LeaderConnectionServerId
|
Column::AnsweringConnectionServerId.eq(follower_id.owner_id as i32),
|
||||||
.eq(leader_id.owner_id as i32),
|
)),
|
||||||
)
|
),
|
||||||
.add(
|
|
||||||
follower::Column::FollowerConnectionServerId
|
|
||||||
.eq(follower_id.owner_id as i32),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
.one(&*tx)
|
.count(&*tx)
|
||||||
.await?
|
.await?;
|
||||||
.ok_or_else(|| anyhow!("not a follower"))?;
|
|
||||||
|
if count < 2 {
|
||||||
|
Err(anyhow!("not room participants"))?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
@ -947,7 +898,7 @@ impl Database {
|
||||||
pub async fn follow(
|
pub async fn follow(
|
||||||
&self,
|
&self,
|
||||||
room_id: RoomId,
|
room_id: RoomId,
|
||||||
project_id: Option<ProjectId>,
|
project_id: ProjectId,
|
||||||
leader_connection: ConnectionId,
|
leader_connection: ConnectionId,
|
||||||
follower_connection: ConnectionId,
|
follower_connection: ConnectionId,
|
||||||
) -> Result<RoomGuard<proto::Room>> {
|
) -> Result<RoomGuard<proto::Room>> {
|
||||||
|
@ -977,7 +928,7 @@ impl Database {
|
||||||
pub async fn unfollow(
|
pub async fn unfollow(
|
||||||
&self,
|
&self,
|
||||||
room_id: RoomId,
|
room_id: RoomId,
|
||||||
project_id: Option<ProjectId>,
|
project_id: ProjectId,
|
||||||
leader_connection: ConnectionId,
|
leader_connection: ConnectionId,
|
||||||
follower_connection: ConnectionId,
|
follower_connection: ConnectionId,
|
||||||
) -> Result<RoomGuard<proto::Room>> {
|
) -> Result<RoomGuard<proto::Room>> {
|
||||||
|
|
|
@ -1154,7 +1154,7 @@ impl Database {
|
||||||
followers.push(proto::Follower {
|
followers.push(proto::Follower {
|
||||||
leader_id: Some(db_follower.leader_connection().into()),
|
leader_id: Some(db_follower.leader_connection().into()),
|
||||||
follower_id: Some(db_follower.follower_connection().into()),
|
follower_id: Some(db_follower.follower_connection().into()),
|
||||||
project_id: db_follower.project_id.map(|id| id.to_proto()),
|
project_id: db_follower.project_id.to_proto(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ pub struct Model {
|
||||||
#[sea_orm(primary_key)]
|
#[sea_orm(primary_key)]
|
||||||
pub id: FollowerId,
|
pub id: FollowerId,
|
||||||
pub room_id: RoomId,
|
pub room_id: RoomId,
|
||||||
pub project_id: Option<ProjectId>,
|
pub project_id: ProjectId,
|
||||||
pub leader_connection_server_id: ServerId,
|
pub leader_connection_server_id: ServerId,
|
||||||
pub leader_connection_id: i32,
|
pub leader_connection_id: i32,
|
||||||
pub follower_connection_server_id: ServerId,
|
pub follower_connection_server_id: ServerId,
|
||||||
|
|
|
@ -1901,7 +1901,7 @@ async fn follow(
|
||||||
session
|
session
|
||||||
.db()
|
.db()
|
||||||
.await
|
.await
|
||||||
.check_can_follow(room_id, project_id, leader_id, session.connection_id)
|
.check_room_participants(room_id, leader_id, session.connection_id)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let mut response_payload = session
|
let mut response_payload = session
|
||||||
|
@ -1913,12 +1913,14 @@ async fn follow(
|
||||||
.retain(|view| view.leader_id != Some(follower_id.into()));
|
.retain(|view| view.leader_id != Some(follower_id.into()));
|
||||||
response.send(response_payload)?;
|
response.send(response_payload)?;
|
||||||
|
|
||||||
let room = session
|
if let Some(project_id) = project_id {
|
||||||
.db()
|
let room = session
|
||||||
.await
|
.db()
|
||||||
.follow(room_id, project_id, leader_id, follower_id)
|
.await
|
||||||
.await?;
|
.follow(room_id, project_id, leader_id, follower_id)
|
||||||
room_updated(&room, &session.peer);
|
.await?;
|
||||||
|
room_updated(&room, &session.peer);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1935,19 +1937,21 @@ async fn unfollow(request: proto::Unfollow, session: Session) -> Result<()> {
|
||||||
session
|
session
|
||||||
.db()
|
.db()
|
||||||
.await
|
.await
|
||||||
.check_can_unfollow(room_id, project_id, leader_id, session.connection_id)
|
.check_room_participants(room_id, leader_id, session.connection_id)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
session
|
session
|
||||||
.peer
|
.peer
|
||||||
.forward_send(session.connection_id, leader_id, request)?;
|
.forward_send(session.connection_id, leader_id, request)?;
|
||||||
|
|
||||||
let room = session
|
if let Some(project_id) = project_id {
|
||||||
.db()
|
let room = session
|
||||||
.await
|
.db()
|
||||||
.unfollow(room_id, project_id, leader_id, follower_id)
|
.await
|
||||||
.await?;
|
.unfollow(room_id, project_id, leader_id, follower_id)
|
||||||
room_updated(&room, &session.peer);
|
.await?;
|
||||||
|
room_updated(&room, &session.peer);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -273,7 +273,7 @@ message ParticipantProject {
|
||||||
message Follower {
|
message Follower {
|
||||||
PeerId leader_id = 1;
|
PeerId leader_id = 1;
|
||||||
PeerId follower_id = 2;
|
PeerId follower_id = 2;
|
||||||
optional uint64 project_id = 3;
|
uint64 project_id = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ParticipantLocation {
|
message ParticipantLocation {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue