Fix error when deleting rooms containing projects on refresh

Antonio Scandurra created

A foreign key violation was causing the server to never delete stale
rooms during `Database::refresh_room` due to having one or more project
records referencing the room.

Change summary

crates/collab/src/db.rs                      |  4 ++++
crates/collab/src/rpc.rs                     |  7 +++++--
crates/collab/src/tests/integration_tests.rs | 14 +++++++++++---
3 files changed, 20 insertions(+), 5 deletions(-)

Detailed changes

crates/collab/src/db.rs 🔗

@@ -191,6 +191,10 @@ impl Database {
                     .filter(room_participant::Column::RoomId.eq(room_id))
                     .exec(&*tx)
                     .await?;
+                project::Entity::delete_many()
+                    .filter(project::Column::RoomId.eq(room_id))
+                    .exec(&*tx)
+                    .await?;
                 room::Entity::delete_by_id(room_id).exec(&*tx).await?;
             }
 

crates/collab/src/rpc.rs 🔗

@@ -270,8 +270,11 @@ impl Server {
                         let mut live_kit_room = String::new();
                         let mut delete_live_kit_room = false;
 
-                        if let Ok(mut refreshed_room) =
-                            app_state.db.refresh_room(room_id, server_id).await
+                        if let Some(mut refreshed_room) = app_state
+                            .db
+                            .refresh_room(room_id, server_id)
+                            .await
+                            .trace_err()
                         {
                             tracing::info!(
                                 room_id = room_id.0,

crates/collab/src/tests/integration_tests.rs 🔗

@@ -733,6 +733,14 @@ async fn test_server_restarts(
     deterministic.forbid_parking();
     let mut server = TestServer::start(&deterministic).await;
     let client_a = server.create_client(cx_a, "user_a").await;
+    client_a
+        .fs
+        .insert_tree("/a", json!({ "a.txt": "a-contents" }))
+        .await;
+
+    // Invite client B to collaborate on a project
+    let (project_a, _) = client_a.build_local_project("/a", cx_a).await;
+
     let client_b = server.create_client(cx_b, "user_b").await;
     let client_c = server.create_client(cx_c, "user_c").await;
     let client_d = server.create_client(cx_d, "user_d").await;
@@ -753,19 +761,19 @@ async fn test_server_restarts(
     // User A calls users B, C, and D.
     active_call_a
         .update(cx_a, |call, cx| {
-            call.invite(client_b.user_id().unwrap(), None, cx)
+            call.invite(client_b.user_id().unwrap(), Some(project_a.clone()), cx)
         })
         .await
         .unwrap();
     active_call_a
         .update(cx_a, |call, cx| {
-            call.invite(client_c.user_id().unwrap(), None, cx)
+            call.invite(client_c.user_id().unwrap(), Some(project_a.clone()), cx)
         })
         .await
         .unwrap();
     active_call_a
         .update(cx_a, |call, cx| {
-            call.invite(client_d.user_id().unwrap(), None, cx)
+            call.invite(client_d.user_id().unwrap(), Some(project_a.clone()), cx)
         })
         .await
         .unwrap();