From a3e75540af95766c98a1beea68814819dfb974f7 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Thu, 9 May 2024 16:17:13 -0600 Subject: [PATCH] Reduce serializability of project delete (#11628) This may reduce locks when deleting projects. Release Notes: - N/A --- crates/collab/src/db.rs | 2 +- crates/collab/src/db/queries/projects.rs | 17 +++++++---- crates/collab/src/rpc.rs | 39 +++++++++++++++--------- 3 files changed, 37 insertions(+), 21 deletions(-) diff --git a/crates/collab/src/db.rs b/crates/collab/src/db.rs index b2cb5ac90bf3..94ccaffb9750 100644 --- a/crates/collab/src/db.rs +++ b/crates/collab/src/db.rs @@ -415,7 +415,7 @@ impl Database { if is_serialization_error(error) && prev_attempt_count < SLEEPS.len() { let base_delay = SLEEPS[prev_attempt_count]; let randomized_delay = base_delay * self.rng.lock().await.gen_range(0.5..=2.0); - log::info!( + log::warn!( "retrying transaction after serialization error. delay: {} ms.", randomized_delay ); diff --git a/crates/collab/src/db/queries/projects.rs b/crates/collab/src/db/queries/projects.rs index b9e917bbbc75..2a7c3e1f8c21 100644 --- a/crates/collab/src/db/queries/projects.rs +++ b/crates/collab/src/db/queries/projects.rs @@ -130,13 +130,21 @@ impl Database { .await } + pub async fn delete_project(&self, project_id: ProjectId) -> Result<()> { + self.weak_transaction(|tx| async move { + project::Entity::delete_by_id(project_id).exec(&*tx).await?; + Ok(()) + }) + .await + } + /// Unshares the given project. pub async fn unshare_project( &self, project_id: ProjectId, connection: ConnectionId, user_id: Option, - ) -> Result, Vec)>> { + ) -> Result, Vec)>> { self.project_transaction(project_id, |tx| async move { let guest_connection_ids = self.project_guest_connection_ids(project_id, &tx).await?; let project = project::Entity::find_by_id(project_id) @@ -149,10 +157,7 @@ impl Database { None }; if project.host_connection()? == connection { - project::Entity::delete(project.into_active_model()) - .exec(&*tx) - .await?; - return Ok((room, guest_connection_ids)); + return Ok((true, room, guest_connection_ids)); } if let Some(dev_server_project_id) = project.dev_server_project_id { if let Some(user_id) = user_id { @@ -169,7 +174,7 @@ impl Database { }) .exec(&*tx) .await?; - return Ok((room, guest_connection_ids)); + return Ok((false, room, guest_connection_ids)); } } diff --git a/crates/collab/src/rpc.rs b/crates/collab/src/rpc.rs index bad78b845ae0..c7b8f32bde30 100644 --- a/crates/collab/src/rpc.rs +++ b/crates/collab/src/rpc.rs @@ -2032,23 +2032,34 @@ async fn unshare_project_internal( user_id: Option, session: &Session, ) -> Result<()> { - let (room, guest_connection_ids) = &*session - .db() - .await - .unshare_project(project_id, connection_id, user_id) - .await?; + let delete = { + let room_guard = session + .db() + .await + .unshare_project(project_id, connection_id, user_id) + .await?; - let message = proto::UnshareProject { - project_id: project_id.to_proto(), + let (delete, room, guest_connection_ids) = &*room_guard; + + let message = proto::UnshareProject { + project_id: project_id.to_proto(), + }; + + broadcast( + Some(connection_id), + guest_connection_ids.iter().copied(), + |conn_id| session.peer.send(conn_id, message.clone()), + ); + if let Some(room) = room { + room_updated(room, &session.peer); + } + + *delete }; - broadcast( - Some(connection_id), - guest_connection_ids.iter().copied(), - |conn_id| session.peer.send(conn_id, message.clone()), - ); - if let Some(room) = room { - room_updated(room, &session.peer); + if delete { + let db = session.db().await; + db.delete_project(project_id).await?; } Ok(())