Skip to main content

statsig_rust/event_logging/event_queue/
batch.rs

1use crate::event_logging::statsig_event_internal::StatsigEventInternal;
2use crate::log_event_payload::{LogEventPayload, LogEventRequest};
3use crate::statsig_metadata::StatsigMetadataWithLogEventExtras;
4use serde_json::json;
5
6pub struct EventBatch {
7    pub attempts: u8,
8    pub events: Vec<StatsigEventInternal>,
9    first_event_time_ms: Option<u64>,
10}
11
12impl EventBatch {
13    pub fn new(events: Vec<StatsigEventInternal>) -> Self {
14        let first_event_time_ms = events.first().map(|event| event.time);
15        Self {
16            events,
17            attempts: 0,
18            first_event_time_ms,
19        }
20    }
21
22    pub fn get_max_event_queue_time_ms(&self, now_ms: u64) -> u64 {
23        self.first_event_time_ms
24            .map(|first_event_time_ms| now_ms.saturating_sub(first_event_time_ms))
25            .unwrap_or_default()
26    }
27
28    pub fn get_log_event_request(
29        &self,
30        statsig_metadata: StatsigMetadataWithLogEventExtras,
31    ) -> LogEventRequest {
32        let payload = LogEventPayload {
33            events: json!(self.events),
34            statsig_metadata: json!(statsig_metadata),
35        };
36
37        LogEventRequest {
38            payload,
39            event_count: self.events.len() as u64,
40            retries: self.attempts as u32,
41        }
42    }
43}
44
45#[cfg(test)]
46mod tests {
47    use super::*;
48    use crate::{event_logging::statsig_event::StatsigEvent, user::StatsigUserLoggable};
49
50    fn make_event(time: u64) -> StatsigEventInternal {
51        StatsigEventInternal::new(
52            time,
53            StatsigUserLoggable::null(),
54            StatsigEvent {
55                event_name: "test_event".to_string(),
56                value: None,
57                metadata: None,
58                statsig_metadata: None,
59            },
60            None,
61        )
62    }
63
64    #[test]
65    fn max_event_queue_time_uses_cached_first_event_time() {
66        let batch = EventBatch::new(vec![make_event(100), make_event(200)]);
67
68        assert_eq!(batch.get_max_event_queue_time_ms(350), 250);
69    }
70
71    #[test]
72    fn max_event_queue_time_saturates_at_zero() {
73        let batch = EventBatch::new(vec![make_event(200)]);
74
75        assert_eq!(batch.get_max_event_queue_time_ms(100), 0);
76    }
77
78    #[test]
79    fn max_event_queue_time_defaults_for_empty_batch() {
80        let batch = EventBatch::new(Vec::new());
81
82        assert_eq!(batch.get_max_event_queue_time_ms(100), 0);
83    }
84}