From a3b39ee42c3a0d3df6f6a3b55a57160759d43df3 Mon Sep 17 00:00:00 2001 From: projectmoon Date: Wed, 19 May 2021 21:34:11 +0000 Subject: [PATCH] Use ON CONFLICT and transactions where appropriate. --- src/db/sqlite/rooms.rs | 50 ++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/src/db/sqlite/rooms.rs b/src/db/sqlite/rooms.rs index 9e89850..14e8ce4 100644 --- a/src/db/sqlite/rooms.rs +++ b/src/db/sqlite/rooms.rs @@ -51,18 +51,15 @@ impl Rooms for Database { } async fn insert_room_info(&self, info: &RoomInfo) -> Result<(), DataError> { - //Clear out old info first, because we want this to be an "upsert." - sqlx::query("DELETE FROM room_info where room_id = ?") - .bind(&info.room_id) - .execute(&self.conn) - .await - .ok(); - - sqlx::query(r#"INSERT INTO room_info (room_id, room_name) VALUES (?, ?)"#) - .bind(&info.room_id) - .bind(&info.room_name) - .execute(&self.conn) - .await?; + sqlx::query( + r#"INSERT INTO room_info (room_id, room_name) VALUES (?, ?) + ON CONFLICT(room_id) DO UPDATE SET room_name = ?"#, + ) + .bind(&info.room_id) + .bind(&info.room_name) + .bind(&info.room_name) + .execute(&self.conn) + .await?; Ok(()) } @@ -70,7 +67,7 @@ impl Rooms for Database { async fn get_room_info(&self, room_id: &str) -> Result, DataError> { let info = sqlx::query!( r#"SELECT room_id, room_name FROM room_info - WHERE room_id = ?"#, + WHERE room_id = ?"#, room_id ) .fetch_optional(&self.conn) @@ -85,7 +82,7 @@ impl Rooms for Database { async fn get_rooms_for_user(&self, user_id: &str) -> Result, DataError> { let room_ids = sqlx::query!( r#"SELECT room_id FROM room_users - WHERE username = ?"#, + WHERE username = ?"#, user_id ) .fetch_all(&self.conn) @@ -107,16 +104,14 @@ impl Rooms for Database { } async fn add_user_to_room(&self, username: &str, room_id: &str) -> Result<(), DataError> { - // This is here because it is possible to process a bunch of - // user join/leave events at once, and we don't want to cause - // constraint violation errors. - self.remove_user_from_room(username, room_id).await.ok(); - - sqlx::query("INSERT INTO room_users (room_id, username) VALUES (?, ?)") - .bind(room_id) - .bind(username) - .execute(&self.conn) - .await?; + sqlx::query( + "INSERT INTO room_users (room_id, username) VALUES (?, ?) + ON CONFLICT DO NOTHING", + ) + .bind(room_id) + .bind(username) + .execute(&self.conn) + .await?; Ok(()) } @@ -134,16 +129,19 @@ impl Rooms for Database { async fn clear_info(&self, room_id: &str) -> Result<(), DataError> { // We do not clear event history here, because if we rejoin a // room, we would re-process events we've already seen. + let mut tx = self.conn.begin().await?; + sqlx::query("DELETE FROM room_info where room_id = ?") .bind(room_id) - .execute(&self.conn) + .execute(&mut tx) .await?; sqlx::query("DELETE FROM room_users where room_id = ?") .bind(room_id) - .execute(&self.conn) + .execute(&mut tx) .await?; + tx.commit().await?; Ok(()) } }