Skip to main content

max / makenotwork

1013 B · 37 lines History Blame Raw
1 use super::{PgPool, Uuid};
2
3 /// Toggle endorsement: insert if missing, delete if exists. Returns true if now endorsed.
4 /// Uses a transaction to prevent race conditions between concurrent toggle requests.
5 #[tracing::instrument(skip_all)]
6 pub async fn toggle_endorsement(
7 pool: &PgPool,
8 post_id: Uuid,
9 endorser_id: Uuid,
10 ) -> Result<bool, sqlx::Error> {
11 let mut tx = pool.begin().await?;
12
13 let result = sqlx::query!(
14 "INSERT INTO post_endorsements (post_id, endorser_id) VALUES ($1, $2) ON CONFLICT DO NOTHING",
15 post_id,
16 endorser_id,
17 )
18 .execute(&mut *tx)
19 .await?;
20
21 if result.rows_affected() == 0 {
22 // Already existed; remove it
23 sqlx::query!(
24 "DELETE FROM post_endorsements WHERE post_id = $1 AND endorser_id = $2",
25 post_id,
26 endorser_id,
27 )
28 .execute(&mut *tx)
29 .await?;
30 tx.commit().await?;
31 Ok(false)
32 } else {
33 tx.commit().await?;
34 Ok(true)
35 }
36 }
37