Initial tracking of unfollows on collab server

Julia created

Change summary

crates/collab/src/db.rs  | 41 +++++++++++++++++++++++++++++++++++++++++
crates/collab/src/rpc.rs | 22 ++++++++++++++++++----
2 files changed, 59 insertions(+), 4 deletions(-)

Detailed changes

crates/collab/src/db.rs 🔗

@@ -1747,6 +1747,47 @@ impl Database {
         .await
     }
 
+    pub async fn unfollow(
+        &self,
+        room_id: RoomId,
+        project_id: ProjectId,
+        leader_connection: ConnectionId,
+        follower_connection: ConnectionId,
+    ) -> Result<RoomGuard<proto::Room>> {
+        self.room_transaction(|tx| async move {
+            follower::Entity::delete_many()
+                .filter(
+                    Condition::all()
+                        .add(follower::Column::RoomId.eq(room_id))
+                        .add(follower::Column::ProjectId.eq(project_id))
+                        .add(
+                            Condition::any()
+                                .add(
+                                    follower::Column::LeaderConnectionServerId
+                                        .eq(leader_connection.owner_id)
+                                        .and(
+                                            follower::Column::LeaderConnectionId
+                                                .eq(leader_connection.id),
+                                        ),
+                                )
+                                .add(
+                                    follower::Column::FollowerConnectionServerId
+                                        .eq(follower_connection.owner_id)
+                                        .and(
+                                            follower::Column::FollowerConnectionId
+                                                .eq(follower_connection.id),
+                                        ),
+                                ),
+                        ),
+                )
+                .exec(&*tx)
+                .await?;
+
+            Ok((room_id, self.get_room(room_id, &*tx).await?))
+        })
+        .await
+    }
+
     pub async fn update_room_participant_location(
         &self,
         room_id: RoomId,

crates/collab/src/rpc.rs 🔗

@@ -1719,13 +1719,14 @@ async fn follow(
     response: Response<proto::Follow>,
     session: Session,
 ) -> Result<()> {
-    let project_id = ProjectId::from_proto(request.project_id);
     let room_id = RoomId::from_proto(request.project_id);
+    let project_id = ProjectId::from_proto(request.project_id);
     let leader_id = request
         .leader_id
         .ok_or_else(|| anyhow!("invalid leader id"))?
         .into();
     let follower_id = session.connection_id;
+
     {
         let project_connection_ids = session
             .db()
@@ -1758,22 +1759,35 @@ async fn follow(
 }
 
 async fn unfollow(request: proto::Unfollow, session: Session) -> Result<()> {
+    let room_id = RoomId::from_proto(request.project_id);
     let project_id = ProjectId::from_proto(request.project_id);
     let leader_id = request
         .leader_id
         .ok_or_else(|| anyhow!("invalid leader id"))?
         .into();
-    let project_connection_ids = session
+    let follower_id = session.connection_id;
+
+    if !session
         .db()
         .await
         .project_connection_ids(project_id, session.connection_id)
-        .await?;
-    if !project_connection_ids.contains(&leader_id) {
+        .await?
+        .contains(&leader_id)
+    {
         Err(anyhow!("no such peer"))?;
     }
+
     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);
+
     Ok(())
 }