Refactor Database::remove_contact

Petros Amoiridis and Antonio Scandurra created

Refactor it to avoid sending irrelevant messages to update the UI.

Co-Authored-By: Antonio Scandurra <me@as-cii.com>

Change summary

crates/collab/src/db.rs  | 25 ++++++++++++++++---------
crates/collab/src/rpc.rs | 24 +++++++++++++++---------
2 files changed, 31 insertions(+), 18 deletions(-)

Detailed changes

crates/collab/src/db.rs 🔗

@@ -595,7 +595,16 @@ impl Database {
         .await
     }
 
-    pub async fn remove_contact(&self, requester_id: UserId, responder_id: UserId) -> Result<()> {
+    /// Returns a bool indicating whether the removed contact had originally accepted or not
+    ///
+    /// Deletes the contact identified by the requester and responder ids, and then returns
+    /// whether the deleted contact had originally accepted or was a pending contact request.
+    ///
+    /// # Arguments
+    ///
+    /// * `requester_id` - The user that initiates this request
+    /// * `responder_id` - The user that will be removed
+    pub async fn remove_contact(&self, requester_id: UserId, responder_id: UserId) -> Result<bool> {
         self.transaction(|tx| async move {
             let (id_a, id_b) = if responder_id < requester_id {
                 (responder_id, requester_id)
@@ -603,20 +612,18 @@ impl Database {
                 (requester_id, responder_id)
             };
 
-            let result = contact::Entity::delete_many()
+            let contact = contact::Entity::find()
                 .filter(
                     contact::Column::UserIdA
                         .eq(id_a)
                         .and(contact::Column::UserIdB.eq(id_b)),
                 )
-                .exec(&*tx)
-                .await?;
+                .one(&*tx)
+                .await?
+                .ok_or_else(|| anyhow!("no such contact"))?;
 
-            if result.rows_affected == 1 {
-                Ok(())
-            } else {
-                Err(anyhow!("no such contact"))?
-            }
+            contact::Entity::delete_by_id(contact.id).exec(&*tx).await?;
+            Ok(contact.accepted)
         })
         .await
     }

crates/collab/src/rpc.rs 🔗

@@ -1961,25 +1961,31 @@ async fn remove_contact(
     let requester_id = session.user_id;
     let responder_id = UserId::from_proto(request.user_id);
     let db = session.db().await;
-    db.remove_contact(requester_id, responder_id).await?;
+    let contact_accepted = db.remove_contact(requester_id, responder_id).await?;
 
     let pool = session.connection_pool().await;
     // Update outgoing contact requests of requester
     let mut update = proto::UpdateContacts::default();
-    update.remove_contacts.push(responder_id.to_proto());
-    update
-        .remove_outgoing_requests
-        .push(responder_id.to_proto());
+    if contact_accepted {
+        update.remove_contacts.push(responder_id.to_proto());
+    } else {
+        update
+            .remove_outgoing_requests
+            .push(responder_id.to_proto());
+    }
     for connection_id in pool.user_connection_ids(requester_id) {
         session.peer.send(connection_id, update.clone())?;
     }
 
     // Update incoming contact requests of responder
     let mut update = proto::UpdateContacts::default();
-    update.remove_contacts.push(requester_id.to_proto());
-    update
-        .remove_incoming_requests
-        .push(requester_id.to_proto());
+    if contact_accepted {
+        update.remove_contacts.push(requester_id.to_proto());
+    } else {
+        update
+            .remove_incoming_requests
+            .push(requester_id.to_proto());
+    }
     for connection_id in pool.user_connection_ids(responder_id) {
         session.peer.send(connection_id, update.clone())?;
     }