nimbus/stateful/
targeting.rs
1use crate::{
6 enrollment::ExperimentEnrollment,
7 error::{warn, BehaviorError},
8 json::JsonObject,
9 stateful::behavior::{EventQueryType, EventStore},
10 NimbusError, NimbusTargetingHelper, Result, TargetingAttributes,
11};
12use std::collections::HashMap;
13use std::sync::{Arc, Mutex};
14
15impl NimbusTargetingHelper {
16 pub(crate) fn with_targeting_attributes(
17 targeting_attributes: &TargetingAttributes,
18 event_store: Arc<Mutex<EventStore>>,
19 ) -> Self {
20 Self {
21 context: serde_json::to_value(targeting_attributes.clone()).unwrap(),
22 event_store,
23 targeting_attributes: Some(targeting_attributes.clone()),
24 }
25 }
26
27 pub(crate) fn update_enrollment(&mut self, enrollment: &ExperimentEnrollment) -> bool {
28 if let Some(ref mut targeting_attributes) = self.targeting_attributes {
29 targeting_attributes.update_enrollment(enrollment);
30
31 self.context = serde_json::to_value(targeting_attributes.clone()).unwrap();
32 true
33 } else {
34 false
35 }
36 }
37}
38
39pub trait RecordedContext: Send + Sync {
40 fn to_json(&self) -> JsonObject;
44
45 fn get_event_queries(&self) -> HashMap<String, String>;
50
51 fn set_event_query_values(&self, event_query_values: HashMap<String, f64>);
55
56 fn record(&self);
60}
61
62impl dyn RecordedContext {
63 pub fn execute_queries(
64 &self,
65 nimbus_targeting_helper: &NimbusTargetingHelper,
66 ) -> Result<HashMap<String, f64>> {
67 let results: HashMap<String, f64> =
68 HashMap::from_iter(self.get_event_queries().iter().filter_map(|(key, query)| {
69 match nimbus_targeting_helper.evaluate_jexl_raw_value(query) {
70 Ok(result) => match result.as_f64() {
71 Some(v) => Some((key.clone(), v)),
72 None => {
73 warn!(
74 "Value '{}' for query '{}' was not a string",
75 result.to_string(),
76 query
77 );
78 None
79 }
80 },
81 Err(err) => {
82 let error_string = format!(
83 "error during jexl evaluation for query '{}' — {}",
84 query, err
85 );
86 warn!("{}", error_string);
87 None
88 }
89 }
90 }));
91 self.set_event_query_values(results.clone());
92 Ok(results)
93 }
94
95 pub fn validate_queries(&self) -> Result<()> {
96 for query in self.get_event_queries().values() {
97 match EventQueryType::validate_query(query) {
98 Ok(true) => continue,
99 Ok(false) => {
100 return Err(NimbusError::BehaviorError(
101 BehaviorError::EventQueryParseError(query.clone()),
102 ));
103 }
104 Err(err) => return Err(err),
105 }
106 }
107 Ok(())
108 }
109}
110
111pub fn validate_event_queries(recorded_context: Arc<dyn RecordedContext>) -> Result<()> {
112 recorded_context.validate_queries()
113}