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:
Max Brunsfeld 2023-09-28 14:21:44 -07:00
parent ce940da8e9
commit e9c1ad6acd
9 changed files with 47 additions and 93 deletions

View file

@ -176,7 +176,7 @@ CREATE TABLE "servers" (
CREATE TABLE "followers" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
"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_id" INTEGER NOT NULL,
"follower_connection_server_id" INTEGER NOT NULL REFERENCES servers (id) ON DELETE CASCADE,

View file

@ -1 +0,0 @@
ALTER TABLE followers ALTER COLUMN project_id DROP NOT NULL;

View file

@ -862,83 +862,34 @@ impl Database {
.await
}
pub async fn check_can_follow(
pub async fn check_room_participants(
&self,
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,
follower_id: ConnectionId,
) -> Result<()> {
self.transaction(|tx| async move {
follower::Entity::find()
use room_participant::Column;
let count = room_participant::Entity::find()
.filter(
Condition::all()
.add(follower::Column::RoomId.eq(room_id))
.add(follower::Column::ProjectId.eq(project_id))
.add(follower::Column::LeaderConnectionId.eq(leader_id.id as i32))
.add(follower::Column::FollowerConnectionId.eq(follower_id.id as i32))
.add(
follower::Column::LeaderConnectionServerId
.eq(leader_id.owner_id as i32),
)
.add(
follower::Column::FollowerConnectionServerId
.eq(follower_id.owner_id as i32),
),
Condition::all().add(Column::RoomId.eq(room_id)).add(
Condition::any()
.add(Column::AnsweringConnectionId.eq(leader_id.id as i32).and(
Column::AnsweringConnectionServerId.eq(leader_id.owner_id as i32),
))
.add(Column::AnsweringConnectionId.eq(follower_id.id as i32).and(
Column::AnsweringConnectionServerId.eq(follower_id.owner_id as i32),
)),
),
)
.one(&*tx)
.await?
.ok_or_else(|| anyhow!("not a follower"))?;
.count(&*tx)
.await?;
if count < 2 {
Err(anyhow!("not room participants"))?;
}
Ok(())
})
.await
@ -947,7 +898,7 @@ impl Database {
pub async fn follow(
&self,
room_id: RoomId,
project_id: Option<ProjectId>,
project_id: ProjectId,
leader_connection: ConnectionId,
follower_connection: ConnectionId,
) -> Result<RoomGuard<proto::Room>> {
@ -977,7 +928,7 @@ impl Database {
pub async fn unfollow(
&self,
room_id: RoomId,
project_id: Option<ProjectId>,
project_id: ProjectId,
leader_connection: ConnectionId,
follower_connection: ConnectionId,
) -> Result<RoomGuard<proto::Room>> {

View file

@ -1154,7 +1154,7 @@ impl Database {
followers.push(proto::Follower {
leader_id: Some(db_follower.leader_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(),
});
}

View file

@ -8,7 +8,7 @@ pub struct Model {
#[sea_orm(primary_key)]
pub id: FollowerId,
pub room_id: RoomId,
pub project_id: Option<ProjectId>,
pub project_id: ProjectId,
pub leader_connection_server_id: ServerId,
pub leader_connection_id: i32,
pub follower_connection_server_id: ServerId,

View file

@ -1901,7 +1901,7 @@ async fn follow(
session
.db()
.await
.check_can_follow(room_id, project_id, leader_id, session.connection_id)
.check_room_participants(room_id, leader_id, session.connection_id)
.await?;
let mut response_payload = session
@ -1913,12 +1913,14 @@ async fn follow(
.retain(|view| view.leader_id != Some(follower_id.into()));
response.send(response_payload)?;
let room = session
.db()
.await
.follow(room_id, project_id, leader_id, follower_id)
.await?;
room_updated(&room, &session.peer);
if let Some(project_id) = project_id {
let room = session
.db()
.await
.follow(room_id, project_id, leader_id, follower_id)
.await?;
room_updated(&room, &session.peer);
}
Ok(())
}
@ -1935,19 +1937,21 @@ async fn unfollow(request: proto::Unfollow, session: Session) -> Result<()> {
session
.db()
.await
.check_can_unfollow(room_id, project_id, leader_id, session.connection_id)
.check_room_participants(room_id, leader_id, session.connection_id)
.await?;
session
.peer
.forward_send(session.connection_id, leader_id, request)?;
let room = session
.db()
.await
.unfollow(room_id, project_id, leader_id, follower_id)
.await?;
room_updated(&room, &session.peer);
if let Some(project_id) = project_id {
let room = session
.db()
.await
.unfollow(room_id, project_id, leader_id, follower_id)
.await?;
room_updated(&room, &session.peer);
}
Ok(())
}