1use async_trait::async_trait;
6use puerto_core::RepositoryError;
7use puerto_core::mail::SentMails;
8use sqlx::PgPool;
9use uuid::Uuid;
10
11use crate::map_sqlx_error;
12
13pub struct PgSentMails {
15 pool: PgPool,
16}
17
18impl PgSentMails {
19 pub fn new(pool: PgPool) -> Self {
20 Self { pool }
21 }
22}
23
24#[async_trait]
25impl SentMails for PgSentMails {
26 async fn was_sent(&self, event_id: Uuid, mail: &str) -> Result<bool, RepositoryError> {
27 sqlx::query_scalar(
28 "SELECT EXISTS (SELECT 1 FROM sent_mails WHERE event_id = $1 AND mail = $2)",
29 )
30 .bind(event_id)
31 .bind(mail)
32 .fetch_one(&self.pool)
33 .await
34 .map_err(|err| {
35 tracing::error!(error = %err, %event_id, mail, "sent_mails: read failed");
36 map_sqlx_error(&err)
37 })
38 }
39
40 async fn mark_sent(&self, event_id: Uuid, mail: &str) -> Result<(), RepositoryError> {
41 sqlx::query(
42 "INSERT INTO sent_mails (event_id, mail) VALUES ($1, $2) \
43 ON CONFLICT (event_id, mail) DO NOTHING",
44 )
45 .bind(event_id)
46 .bind(mail)
47 .execute(&self.pool)
48 .await
49 .map(|_| ())
50 .map_err(|err| {
51 tracing::error!(error = %err, %event_id, mail, "sent_mails: mark failed");
52 map_sqlx_error(&err)
53 })
54 }
55}