Skip to main content

statsig_rust/event_logging/event_queue/
queued_event.rs

1use super::{
2    queued_config_expo::QueuedConfigExposureEvent,
3    queued_experiment_expo::QueuedExperimentExposureEvent, queued_expo::QueuedExposureEvent,
4    queued_gate_expo::QueuedGateExposureEvent,
5    queued_layer_param_expo::QueuedLayerParamExposureEvent,
6    queued_secondary_expo::QueuedSecondaryExposureAsPrimaryEvent,
7};
8use crate::{
9    evaluation::evaluation_types::ExtraExposureInfo,
10    event_logging::{
11        exposure_sampling::{EvtSamplingDecision, ExposureSamplingKey},
12        statsig_event_internal::StatsigEventInternal,
13    },
14    user::StatsigUserLoggable,
15    SecondaryExposure,
16};
17
18pub trait EnqueueOperation {
19    fn as_exposure(&self) -> Option<&impl QueuedExposure<'_>>;
20    fn into_queued_event(self, sampling_decision: EvtSamplingDecision) -> QueuedEvent;
21}
22
23pub trait QueuedExposure<'a> {
24    fn create_exposure_sampling_key(&self) -> ExposureSamplingKey;
25    fn get_rule_id_ref(&'a self) -> &'a str;
26    fn get_extra_exposure_info_ref(&'a self) -> Option<&'a ExtraExposureInfo>;
27}
28
29pub enum QueuedEvent {
30    Exposure(QueuedExposureEvent),
31    Passthrough(StatsigEventInternal),
32
33    // Deprecated - Remove when rolled into QueuedExposureEvent
34    GateExposure(QueuedGateExposureEvent),
35    ConfigExposure(QueuedConfigExposureEvent),
36    ExperimentExposure(QueuedExperimentExposureEvent),
37    LayerParamExposure(QueuedLayerParamExposureEvent),
38    SecondaryExposureAsPrimary(QueuedSecondaryExposureAsPrimaryEvent),
39}
40
41impl QueuedEvent {
42    pub fn into_statsig_event_internal(self) -> StatsigEventInternal {
43        match self {
44            QueuedEvent::Exposure(event) => event.into_statsig_event_internal(),
45            QueuedEvent::Passthrough(event) => event,
46
47            QueuedEvent::GateExposure(event) => event.into_statsig_event_internal(),
48            QueuedEvent::ConfigExposure(event) => event.into_statsig_event_internal(),
49            QueuedEvent::ExperimentExposure(event) => event.into_statsig_event_internal(),
50            QueuedEvent::LayerParamExposure(event) => event.into_statsig_event_internal(),
51            QueuedEvent::SecondaryExposureAsPrimary(event) => event.into_statsig_event_internal(),
52        }
53    }
54
55    pub fn exposure_time(&self) -> Option<u64> {
56        match self {
57            QueuedEvent::Exposure(event) => Some(event.data.exposure_time),
58            QueuedEvent::GateExposure(event) => Some(event.exposure_time),
59            QueuedEvent::ConfigExposure(event) => Some(event.exposure_time),
60            QueuedEvent::ExperimentExposure(event) => Some(event.exposure_time),
61            QueuedEvent::LayerParamExposure(event) => Some(event.exposure_time),
62            QueuedEvent::SecondaryExposureAsPrimary(event) => Some(event.exposure_time),
63            QueuedEvent::Passthrough(_) => None,
64        }
65    }
66
67    pub fn user_for_secondary_exposures(&self) -> Option<StatsigUserLoggable> {
68        match self {
69            QueuedEvent::Exposure(event) => Some(event.user.clone()),
70            QueuedEvent::GateExposure(event) => Some(event.user.clone()),
71            QueuedEvent::ConfigExposure(event) => Some(event.user.clone()),
72            QueuedEvent::ExperimentExposure(event) => Some(event.user.clone()),
73            QueuedEvent::LayerParamExposure(event) => Some(event.user.clone()),
74            QueuedEvent::SecondaryExposureAsPrimary(event) => Some(event.user.clone()),
75            QueuedEvent::Passthrough(_) => None,
76        }
77    }
78
79    pub fn take_secondary_exposures_for_primary_logging(&mut self) -> Vec<SecondaryExposure> {
80        match self {
81            QueuedEvent::Exposure(event) => event.take_secondary_exposures_for_primary_logging(),
82            QueuedEvent::GateExposure(event) => {
83                take_non_empty_secondary_exposures(&mut event.secondary_exposures)
84            }
85            QueuedEvent::ConfigExposure(event) => {
86                take_non_empty_secondary_exposures(&mut event.secondary_exposures)
87            }
88            QueuedEvent::ExperimentExposure(event) => {
89                take_non_empty_secondary_exposures(&mut event.secondary_exposures)
90            }
91            QueuedEvent::LayerParamExposure(event) => {
92                take_non_empty_secondary_exposures(&mut event.secondary_exposures)
93            }
94            QueuedEvent::Passthrough(_) | QueuedEvent::SecondaryExposureAsPrimary(_) => Vec::new(),
95        }
96    }
97}
98
99pub(crate) fn take_non_empty_secondary_exposures(
100    secondary_exposures: &mut Option<Vec<SecondaryExposure>>,
101) -> Vec<SecondaryExposure> {
102    match secondary_exposures.take() {
103        Some(exposures) if !exposures.is_empty() => {
104            *secondary_exposures = Some(Vec::new());
105            exposures
106        }
107        original => {
108            *secondary_exposures = original;
109            Vec::new()
110        }
111    }
112}