Skip to main content

max / makenotwork

1.5 KB · 59 lines History Blame Raw
1 use sqlx::PgPool;
2 use uuid::Uuid;
3
4 use crate::error::Result;
5
6 /// Insert a new email signup, ignoring duplicates.
7 /// Returns the signup ID (new or existing).
8 #[tracing::instrument(skip_all)]
9 pub async fn insert_email_signup(pool: &PgPool, email: &str, source: &str) -> Result<Uuid> {
10 let id = sqlx::query_scalar!(
11 r#"
12 INSERT INTO email_signups (email, source)
13 VALUES ($1, $2)
14 ON CONFLICT (email) DO UPDATE SET email = EXCLUDED.email
15 RETURNING id
16 "#,
17 email,
18 source,
19 )
20 .fetch_one(pool)
21 .await?;
22 Ok(id)
23 }
24
25 /// Row returned by the admin email signups query.
26 pub struct DbEmailSignup {
27 pub email: String,
28 pub source: String,
29 pub created_at: chrono::DateTime<chrono::Utc>,
30 }
31
32 /// Get email signups ordered by newest first (capped at 500).
33 #[tracing::instrument(skip_all)]
34 pub async fn get_all_email_signups(pool: &PgPool) -> Result<Vec<DbEmailSignup>> {
35 let rows = sqlx::query_as!(
36 DbEmailSignup,
37 r#"
38 SELECT email, source,
39 created_at as "created_at: chrono::DateTime<chrono::Utc>"
40 FROM email_signups
41 ORDER BY created_at DESC
42 LIMIT 500
43 "#,
44 )
45 .fetch_all(pool)
46 .await?;
47 Ok(rows)
48 }
49
50 /// Count total email signups.
51 #[tracing::instrument(skip_all)]
52 pub async fn count_email_signups(pool: &PgPool) -> Result<i64> {
53 let count = sqlx::query_scalar!("SELECT COUNT(*) FROM email_signups")
54 .fetch_one(pool)
55 .await?
56 .unwrap_or(0);
57 Ok(count)
58 }
59