The smokesignal.events web application
1//! Storage module for LFG (Looking For Group) records.
2//!
3//! This module provides query helpers for LFG records stored in the `atproto_records` table.
4//! For writes, use `atproto_record_upsert()` and `atproto_record_delete()` from the
5//! `atproto_record` module.
6//!
7//! Records are stored as `AtprotoRecord` and can be deserialized to `Lfg` using:
8//! ```ignore
9//! let lfg: Lfg = serde_json::from_value(record.record.0.clone())?;
10//! ```
11
12use super::StoragePool;
13use super::atproto_record::AtprotoRecord;
14use super::errors::StorageError;
15use crate::atproto::lexicon::lfg::NSID;
16
17/// Get the active LFG record for a DID from atproto_records.
18///
19/// Returns the most recent active LFG record for the given DID, or None if
20/// no active record exists.
21pub async fn lfg_get_active_by_did(
22 pool: &StoragePool,
23 did: &str,
24) -> Result<Option<AtprotoRecord>, StorageError> {
25 let record = sqlx::query_as::<_, AtprotoRecord>(
26 r#"
27 SELECT aturi, did, cid, collection, indexed_at, record
28 FROM atproto_records
29 WHERE did = $1
30 AND collection = $2
31 AND (record->>'active')::boolean = true
32 AND (record->>'endsAt')::timestamptz > NOW()
33 ORDER BY indexed_at DESC
34 LIMIT 1
35 "#,
36 )
37 .bind(did)
38 .bind(NSID)
39 .fetch_optional(pool)
40 .await
41 .map_err(StorageError::UnableToExecuteQuery)?;
42
43 Ok(record)
44}
45
46/// Get an LFG record by AT-URI from atproto_records.
47pub async fn lfg_get_by_aturi(
48 pool: &StoragePool,
49 aturi: &str,
50) -> Result<Option<AtprotoRecord>, StorageError> {
51 let record = sqlx::query_as::<_, AtprotoRecord>(
52 r#"
53 SELECT aturi, did, cid, collection, indexed_at, record
54 FROM atproto_records
55 WHERE aturi = $1
56 AND collection = $2
57 "#,
58 )
59 .bind(aturi)
60 .bind(NSID)
61 .fetch_optional(pool)
62 .await
63 .map_err(StorageError::UnableToExecuteQuery)?;
64
65 Ok(record)
66}
67
68/// Get all LFG records for a DID (including inactive/expired).
69///
70/// Used for tag history lookups.
71pub async fn lfg_get_all_by_did(
72 pool: &StoragePool,
73 did: &str,
74 limit: i64,
75) -> Result<Vec<AtprotoRecord>, StorageError> {
76 let records = sqlx::query_as::<_, AtprotoRecord>(
77 r#"
78 SELECT aturi, did, cid, collection, indexed_at, record
79 FROM atproto_records
80 WHERE did = $1
81 AND collection = $2
82 ORDER BY indexed_at DESC
83 LIMIT $3
84 "#,
85 )
86 .bind(did)
87 .bind(NSID)
88 .bind(limit)
89 .fetch_all(pool)
90 .await
91 .map_err(StorageError::UnableToExecuteQuery)?;
92
93 Ok(records)
94}