systemprompt_analytics/repository/session_signals/
geo.rs1use super::SessionSignalsRepository;
7use crate::{AnalyticsError, GeoIpReader, Result};
8use systemprompt_identifiers::SessionId;
9
10impl SessionSignalsRepository {
11 pub async fn backfill_session_geo(
12 &self,
13 reader: Option<&GeoIpReader>,
14 batch_size: i64,
15 ) -> Result<u64> {
16 if batch_size <= 0 {
17 return Err(AnalyticsError::invalid_argument(
18 "batch size must be positive",
19 ));
20 }
21 let mut updated = 0;
22 let mut after: Option<SessionId> = None;
23 loop {
24 let rows = self
25 .owner
26 .sessions_missing_geo(after.as_ref(), batch_size)
27 .await
28 .map_err(AnalyticsError::from)?;
29 let Some(last) = rows.last() else {
30 break;
31 };
32 after = Some(last.0.clone());
33 for (session_id, ip) in rows {
34 if let Some((country, region, city)) =
35 crate::services::extractor::geoip::lookup_geoip(&ip, reader)
36 {
37 updated += self
38 .owner
39 .set_session_geo(
40 &session_id,
41 country.as_deref(),
42 region.as_deref(),
43 city.as_deref(),
44 )
45 .await
46 .map_err(AnalyticsError::from)?;
47 }
48 }
49 }
50 Ok(updated)
51 }
52}