From e1f80452bbe8cc0f37e59642db3bfb077b680cb5 Mon Sep 17 00:00:00 2001 From: Wei Zhang Date: Sat, 14 Dec 2024 01:47:04 +0800 Subject: [PATCH 1/4] fix(graphQL): fix error when retry mark notifications read Signed-off-by: Wei Zhang --- ee/tabby-db/schema/schema.sql | 2 +- ee/tabby-db/schema/schema.svg | 86 +++++++++---------- ee/tabby-db/src/notifications.rs | 10 ++- .../src/service/notification.rs | 73 ++++++++++++++++ 4 files changed, 125 insertions(+), 46 deletions(-) diff --git a/ee/tabby-db/schema/schema.sql b/ee/tabby-db/schema/schema.sql index ef1e248389cc..7d9aa5b5bcd4 100644 --- a/ee/tabby-db/schema/schema.sql +++ b/ee/tabby-db/schema/schema.sql @@ -232,7 +232,7 @@ CREATE TABLE notifications( -- content of notification, in markdown format. content TEXT NOT NULL ); -CREATE TABLE readed_notifications( +CREATE TABLE read_notifications( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, user_id INTEGER NOT NULL, notification_id INTEGER NOT NULL, diff --git a/ee/tabby-db/schema/schema.svg b/ee/tabby-db/schema/schema.svg index a5c49d083675..b990bf544729 100644 --- a/ee/tabby-db/schema/schema.svg +++ b/ee/tabby-db/schema/schema.svg @@ -316,7 +316,7 @@ name - + password_reset:e->users:w @@ -365,43 +365,43 @@ - + -readed_notifications - -readed_notifications - -🔑 - -id - -  - -user_id - -  - -notification_id - -  - -created_at - -  - -updated_at - - - -readed_notifications:e->notifications:w - +read_notifications + +read_notifications + +🔑 + +id + +  + +user_id + +  + +notification_id + +  + +created_at + +  + +updated_at + + + +read_notifications:e->notifications:w + - - -readed_notifications:e->users:w - - + + +read_notifications:e->users:w + + @@ -430,7 +430,7 @@ created_at - + refresh_tokens:e->users:w @@ -550,7 +550,7 @@ updated_at - + source_id_read_access_policies:e->user_groups:w @@ -628,13 +628,13 @@ relevant_questions - + thread_messages:e->threads:w - + threads:e->users:w @@ -682,7 +682,7 @@ updated_at - + user_completions:e->users:w @@ -714,7 +714,7 @@ payload - + user_events:e->users:w @@ -750,13 +750,13 @@ updated_at - + user_group_memberships:e->user_groups:w - + user_group_memberships:e->users:w diff --git a/ee/tabby-db/src/notifications.rs b/ee/tabby-db/src/notifications.rs index ceb2a855867b..50f94506f80b 100644 --- a/ee/tabby-db/src/notifications.rs +++ b/ee/tabby-db/src/notifications.rs @@ -33,7 +33,13 @@ impl DbConn { pub async fn mark_notification_read(&self, id: i64, user_id: i64) -> Result<()> { query!( - "INSERT INTO read_notifications (notification_id, user_id) VALUES (?, ?)", + "INSERT INTO read_notifications (notification_id, user_id) + SELECT ?, ? + WHERE NOT EXISTS ( + SELECT 1 FROM read_notifications WHERE notification_id = ? AND user_id = ? + )", + id, + user_id, id, user_id ) @@ -59,7 +65,7 @@ impl DbConn { let query = format!( r#" -INSERT INTO read_notifications (notification_id, user_id) +INSERT OR IGNORE INTO read_notifications (notification_id, user_id) SELECT notifications.id, ? diff --git a/ee/tabby-webserver/src/service/notification.rs b/ee/tabby-webserver/src/service/notification.rs index 2200bdb6b266..3910120a1563 100644 --- a/ee/tabby-webserver/src/service/notification.rs +++ b/ee/tabby-webserver/src/service/notification.rs @@ -419,4 +419,77 @@ mod tests { assert_eq!(notifications.len(), 1); assert!(notifications[0].read); } + + #[tokio::test] + async fn test_admin_mark_single_then_all() { + let db = DbConn::new_in_memory().await.unwrap(); + let service = create(db.clone()); + + let user = db + .create_user("test1".into(), None, true, None) + .await + .unwrap() + .as_id(); + let notification = db + .create_notification("admin", "notification1") + .await + .unwrap() + .as_id(); + db.create_notification("admin", "notification2") + .await + .unwrap(); + + // mark single notification + service.mark_read(&user, Some(¬ification)).await.unwrap(); + let notifications = service.list(&user).await.unwrap(); + assert_eq!(notifications.len(), 2); + assert!(notifications[0].read); + assert!(!notifications[1].read); + + // mark all notifications + service.mark_read(&user, None).await.unwrap(); + let notifications = service.list(&user).await.unwrap(); + assert_eq!(notifications.len(), 2); + assert!(notifications[0].read); + assert!(notifications[1].read); + } + + #[tokio::test] + async fn test_admin_mark_single_twice() { + let db = DbConn::new_in_memory().await.unwrap(); + let service = create(db.clone()); + + let user = db + .create_user("test1".into(), None, true, None) + .await + .unwrap() + .as_id(); + let notification = db + .create_notification("admin", "notification1") + .await + .unwrap() + .as_id(); + + service.mark_read(&user, Some(¬ification)).await.unwrap(); + assert!(service.mark_read(&user, Some(¬ification)).await.is_ok()); + } + + #[tokio::test] + async fn test_admin_mark_all_twice() { + let db = DbConn::new_in_memory().await.unwrap(); + let service = create(db.clone()); + + let user = db + .create_user("test1".into(), None, true, None) + .await + .unwrap() + .as_id(); + db.create_notification("admin", "notification1") + .await + .unwrap() + .as_id(); + + service.mark_read(&user, None).await.unwrap(); + assert!(service.mark_read(&user, None).await.is_ok()); + } } From 534403baef63828069cefed3b07460429e04cac5 Mon Sep 17 00:00:00 2001 From: Wei Zhang Date: Sat, 14 Dec 2024 11:16:19 +0800 Subject: [PATCH 2/4] fix: duplicated queried read notifications Signed-off-by: Wei Zhang --- ee/tabby-db/src/notifications.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ee/tabby-db/src/notifications.rs b/ee/tabby-db/src/notifications.rs index 50f94506f80b..c550f58a5a2d 100644 --- a/ee/tabby-db/src/notifications.rs +++ b/ee/tabby-db/src/notifications.rs @@ -65,7 +65,7 @@ impl DbConn { let query = format!( r#" -INSERT OR IGNORE INTO read_notifications (notification_id, user_id) +INSERT INTO read_notifications (notification_id, user_id) SELECT notifications.id, ? @@ -77,7 +77,7 @@ ON notifications.id = read_notifications.notification_id AND read_notifications.user_id = ? WHERE - {} + ({}) AND read_notifications.notification_id IS NULL; "#, recipient_clause From cd0152e7379422f2f497cc113f6a52c71101f6ec Mon Sep 17 00:00:00 2001 From: Wei Zhang Date: Sat, 14 Dec 2024 11:32:34 +0800 Subject: [PATCH 3/4] fix: fix test for retry mark all Signed-off-by: Wei Zhang --- ee/tabby-webserver/src/service/notification.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ee/tabby-webserver/src/service/notification.rs b/ee/tabby-webserver/src/service/notification.rs index 3910120a1563..84f1ee00249b 100644 --- a/ee/tabby-webserver/src/service/notification.rs +++ b/ee/tabby-webserver/src/service/notification.rs @@ -176,7 +176,7 @@ mod tests { assert!(service .mark_read(&user_id, Some(¬ification_id)) .await - .is_err()) + .is_ok()) } #[tokio::test] From 860ca46d2b7f676fcb0f6a0dbf23f99a36802097 Mon Sep 17 00:00:00 2001 From: Wei Zhang Date: Sat, 14 Dec 2024 23:23:30 +0800 Subject: [PATCH 4/4] chore: use upsert to handle conflict Signed-off-by: Wei Zhang --- ee/tabby-db/src/notifications.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/ee/tabby-db/src/notifications.rs b/ee/tabby-db/src/notifications.rs index c550f58a5a2d..9482e4b4d3b4 100644 --- a/ee/tabby-db/src/notifications.rs +++ b/ee/tabby-db/src/notifications.rs @@ -34,14 +34,11 @@ impl DbConn { pub async fn mark_notification_read(&self, id: i64, user_id: i64) -> Result<()> { query!( "INSERT INTO read_notifications (notification_id, user_id) - SELECT ?, ? - WHERE NOT EXISTS ( - SELECT 1 FROM read_notifications WHERE notification_id = ? AND user_id = ? - )", + VALUES (?, ?) + ON CONFLICT (notification_id, user_id) + DO NOTHING", id, user_id, - id, - user_id ) .execute(&self.pool) .await?;