systemprompt_users/sessions/
store.rs1use crate::repository::SessionRepository;
7use async_trait::async_trait;
8use chrono::{DateTime, Utc};
9use systemprompt_identifiers::{SessionId, UserId};
10use systemprompt_traits::session_store::{
11 ActiveSessionLookup, CreateSessionParams, SessionBehavioralData, SessionRecord, SessionSnapshot,
12};
13use systemprompt_traits::{AnalyticsProviderError, AnalyticsResult};
14#[async_trait]
15impl systemprompt_traits::SessionStore for SessionRepository {
16 async fn fingerprint_session_ids(
17 &self,
18 fingerprint: &str,
19 window_days: i64,
20 ) -> AnalyticsResult<Vec<SessionId>> {
21 Self::fingerprint_session_ids(self, fingerprint, window_days)
22 .await
23 .map_err(|e| AnalyticsProviderError::Internal(e.into()))
24 }
25 async fn find_by_id(&self, session_id: &SessionId) -> AnalyticsResult<Option<SessionSnapshot>> {
26 Self::find_by_id(self, session_id)
27 .await
28 .map_err(|e| AnalyticsProviderError::Internal(e.into()))
29 }
30 async fn find_active_by_id(
31 &self,
32 session_id: &SessionId,
33 ) -> AnalyticsResult<Option<ActiveSessionLookup>> {
34 Self::find_active_by_id(self, session_id)
35 .await
36 .map_err(|e| AnalyticsProviderError::Internal(e.into()))
37 }
38 async fn revoke_all_for_user(&self, user_id: &UserId) -> AnalyticsResult<u64> {
39 Self::revoke_all_for_user(self, user_id)
40 .await
41 .map_err(|e| AnalyticsProviderError::Internal(e.into()))
42 }
43 async fn find_by_fingerprint(
44 &self,
45 fingerprint_hash: &str,
46 user_id: &UserId,
47 ) -> AnalyticsResult<Option<SessionSnapshot>> {
48 Self::find_by_fingerprint(self, fingerprint_hash, user_id)
49 .await
50 .map_err(|e| AnalyticsProviderError::Internal(e.into()))
51 }
52 async fn list_active_by_user(&self, user_id: &UserId) -> AnalyticsResult<Vec<SessionSnapshot>> {
53 Self::list_active_by_user(self, user_id)
54 .await
55 .map_err(|e| AnalyticsProviderError::Internal(e.into()))
56 }
57 async fn increment_request_count(&self, session_id: &SessionId) -> AnalyticsResult<()> {
58 Self::increment_request_count(self, session_id)
59 .await
60 .map_err(|e| AnalyticsProviderError::Internal(e.into()))
61 }
62 async fn end_session(&self, session_id: &SessionId) -> AnalyticsResult<()> {
63 Self::end_session(self, session_id)
64 .await
65 .map_err(|e| AnalyticsProviderError::Internal(e.into()))
66 }
67 async fn mark_as_scanner(&self, session_id: &SessionId) -> AnalyticsResult<()> {
68 Self::mark_as_scanner(self, session_id)
69 .await
70 .map_err(|e| AnalyticsProviderError::Internal(e.into()))
71 }
72 async fn mark_converted(&self, session_id: &SessionId) -> AnalyticsResult<()> {
73 Self::mark_converted(self, session_id)
74 .await
75 .map_err(|e| AnalyticsProviderError::Internal(e.into()))
76 }
77 async fn mark_ghost_sessions_as_bots(&self) -> AnalyticsResult<u64> {
78 Self::mark_ghost_sessions_as_bots(self)
79 .await
80 .map_err(|e| AnalyticsProviderError::Internal(e.into()))
81 }
82 async fn mark_no_js_sessions_as_bots(&self, engaged: &[SessionId]) -> AnalyticsResult<u64> {
83 Self::mark_no_js_sessions_as_bots(self, engaged)
84 .await
85 .map_err(|e| AnalyticsProviderError::Internal(e.into()))
86 }
87 async fn check_and_mark_behavioral_bot(
88 &self,
89 session_id: &SessionId,
90 request_count_threshold: i32,
91 ) -> AnalyticsResult<bool> {
92 Self::check_and_mark_behavioral_bot(self, session_id, request_count_threshold)
93 .await
94 .map_err(|e| AnalyticsProviderError::Internal(e.into()))
95 }
96 async fn cleanup_inactive(&self, inactive_hours: i32) -> AnalyticsResult<u64> {
97 Self::cleanup_inactive(self, inactive_hours)
98 .await
99 .map_err(|e| AnalyticsProviderError::Internal(e.into()))
100 }
101 async fn count_inactive(&self, inactive_hours: i32) -> AnalyticsResult<i64> {
102 Self::count_inactive(self, inactive_hours)
103 .await
104 .map_err(|e| AnalyticsProviderError::Internal(e.into()))
105 }
106 async fn count_sessions_missing_geo(&self) -> AnalyticsResult<i64> {
107 Self::count_sessions_missing_geo(self)
108 .await
109 .map_err(|e| AnalyticsProviderError::Internal(e.into()))
110 }
111 async fn insert_session(&self, params: &CreateSessionParams<'_>) -> AnalyticsResult<()> {
112 Self::create_session(self, params)
113 .await
114 .map_err(|e| AnalyticsProviderError::Internal(e.into()))
115 }
116 async fn find_recent_by_fingerprint(
117 &self,
118 fingerprint_hash: &str,
119 max_age_seconds: i64,
120 ) -> AnalyticsResult<Option<SessionRecord>> {
121 Self::find_recent_anonymous_by_fingerprint(self, fingerprint_hash, max_age_seconds)
122 .await
123 .map_err(|e| AnalyticsProviderError::Internal(e.into()))
124 }
125 async fn increment_ai_usage(
126 &self,
127 session_id: &SessionId,
128 tokens: i32,
129 cost_microdollars: i64,
130 ) -> AnalyticsResult<()> {
131 Self::increment_ai_usage(self, session_id, tokens, cost_microdollars)
132 .await
133 .map_err(|e| AnalyticsProviderError::Internal(e.into()))
134 }
135 async fn update_behavioral_detection(
136 &self,
137 session_id: &SessionId,
138 score: i32,
139 is_behavioral_bot: bool,
140 reason: Option<&str>,
141 ) -> AnalyticsResult<()> {
142 Self::update_behavioral_detection(self, session_id, score, is_behavioral_bot, reason)
143 .await
144 .map_err(|e| AnalyticsProviderError::Internal(e.into()))
145 }
146 async fn count_sessions_by_fingerprint(
147 &self,
148 fingerprint_hash: &str,
149 window_hours: i64,
150 ) -> AnalyticsResult<i64> {
151 Self::count_sessions_by_fingerprint(self, fingerprint_hash, window_hours)
152 .await
153 .map_err(|e| AnalyticsProviderError::Internal(e.into()))
154 }
155 async fn get_session_for_behavioral_analysis(
156 &self,
157 session_id: &SessionId,
158 ) -> AnalyticsResult<Option<SessionBehavioralData>> {
159 Self::get_session_for_behavioral_analysis(self, session_id)
160 .await
161 .map_err(|e| AnalyticsProviderError::Internal(e.into()))
162 }
163 async fn count_unique_ips_by_fingerprint(
164 &self,
165 fingerprint_hash: &str,
166 window_days: i64,
167 ) -> AnalyticsResult<i64> {
168 Self::count_unique_ips_by_fingerprint(self, fingerprint_hash, window_days)
169 .await
170 .map_err(|e| AnalyticsProviderError::Internal(e.into()))
171 }
172 async fn get_session_starts_by_fingerprint(
173 &self,
174 fingerprint_hash: &str,
175 window_days: i64,
176 ) -> AnalyticsResult<Vec<DateTime<Utc>>> {
177 Self::get_session_starts_by_fingerprint(self, fingerprint_hash, window_days)
178 .await
179 .map_err(|e| AnalyticsProviderError::Internal(e.into()))
180 }
181 async fn get_session_velocity(
182 &self,
183 session_id: &SessionId,
184 ) -> AnalyticsResult<(Option<i64>, Option<i64>)> {
185 Self::get_session_velocity(self, session_id)
186 .await
187 .map_err(|e| AnalyticsProviderError::Internal(e.into()))
188 }
189 async fn count_active_fingerprint_sessions(&self, fingerprint: &str) -> AnalyticsResult<i32> {
190 self.count_active_fingerprint(fingerprint)
191 .await
192 .map_err(|e| AnalyticsProviderError::Internal(e.into()))
193 }
194 async fn find_reusable_fingerprint_session(
195 &self,
196 fingerprint: &str,
197 ) -> AnalyticsResult<Option<SessionId>> {
198 self.find_reusable_fingerprint(fingerprint)
199 .await
200 .map_err(|e| AnalyticsProviderError::Internal(e.into()))
201 }
202 async fn sessions_missing_geo(
203 &self,
204 after: Option<&SessionId>,
205 limit: i64,
206 ) -> AnalyticsResult<Vec<(SessionId, String)>> {
207 self.missing_geo(after, limit)
208 .await
209 .map_err(|e| AnalyticsProviderError::Internal(e.into()))
210 }
211 async fn set_session_geo(
212 &self,
213 session_id: &SessionId,
214 country: Option<&str>,
215 region: Option<&str>,
216 city: Option<&str>,
217 ) -> AnalyticsResult<u64> {
218 self.set_geo(session_id, country, region, city)
219 .await
220 .map_err(|e| AnalyticsProviderError::Internal(e.into()))
221 }
222}