systemprompt_users/sessions/
fingerprint.rs1use super::SessionRepository;
7use crate::Result;
8use systemprompt_identifiers::SessionId;
9
10impl SessionRepository {
11 pub async fn fingerprint_session_ids(
12 &self,
13 fingerprint: &str,
14 window_days: i64,
15 ) -> Result<Vec<SessionId>> {
16 let window_days = i32::try_from(window_days).unwrap_or(i32::MAX);
17 Ok(sqlx::query_scalar!(
18 r#"
19 SELECT session_id as "session_id!: SessionId"
20 FROM user_sessions
21 WHERE fingerprint_hash = $1
22 AND started_at > CURRENT_TIMESTAMP - make_interval(days => $2)
23 "#,
24 fingerprint,
25 window_days,
26 )
27 .fetch_all(&*self.write_pool)
28 .await?)
29 }
30 pub async fn count_active_fingerprint(&self, fingerprint_hash: &str) -> Result<i32> {
31 let row = sqlx::query_scalar!(
32 r#"
33 SELECT COUNT(*)::INT as "count!"
34 FROM user_sessions
35 WHERE fingerprint_hash = $1
36 AND ended_at IS NULL
37 AND last_activity_at > CURRENT_TIMESTAMP - INTERVAL '7 days'
38 "#,
39 fingerprint_hash,
40 )
41 .fetch_one(&*self.write_pool)
42 .await?;
43
44 Ok(row)
45 }
46 pub async fn find_reusable_fingerprint(
47 &self,
48 fingerprint_hash: &str,
49 ) -> Result<Option<SessionId>> {
50 let row = sqlx::query_scalar!(
51 r#"
52 SELECT session_id as "session_id!: SessionId"
53 FROM user_sessions
54 WHERE fingerprint_hash = $1
55 AND ended_at IS NULL
56 AND last_activity_at > CURRENT_TIMESTAMP - INTERVAL '7 days'
57 ORDER BY last_activity_at ASC
58 LIMIT 1
59 "#,
60 fingerprint_hash,
61 )
62 .fetch_optional(&*self.write_pool)
63 .await?;
64
65 Ok(row)
66 }
67}