Skip to content

Commit 98466f1

Browse files
authored
Merge pull request #53 from FeatureProbe/support_debug_event
✨ feat: support debug event
2 parents a9344fd + 74639a1 commit 98466f1

File tree

7 files changed

+130
-38
lines changed

7 files changed

+130
-38
lines changed

Cargo.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
edition = "2021"
33
name = "feature-probe-server-sdk"
4-
version = "2.1.1"
4+
version = "2.2.0"
55
license = "Apache-2.0"
66
authors = ["maintain@featureprobe.com"]
77
description = "FeatureProbe Server Side SDK for Rust"
@@ -40,7 +40,7 @@ thiserror = "1.0"
4040
tracing = "0.1"
4141
url = "2"
4242

43-
feature-probe-event = { version = "1.1.3", features = [
43+
feature-probe-event = { version = "1.2.0", features = [
4444
"use_tokio",
4545
], default-features = false}
4646

resources/fixtures/repo.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"version": 1,
3+
"debugUntilTime": 1681289908000,
34
"segments": {
45
"some_segment1-fjoaefjaam": {
56
"key": "some_segment1",

src/evaluate.rs

Lines changed: 69 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -123,14 +123,16 @@ pub struct EvalParams<'a> {
123123
variations: &'a [Value],
124124
segment_repo: &'a HashMap<String, Segment>,
125125
toggle_repo: &'a HashMap<String, Toggle>,
126+
debug_until_time: Option<u64>,
126127
}
127128

128-
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Default)]
129+
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Default, Clone)]
129130
#[serde(rename_all = "camelCase")]
130131
pub struct EvalDetail<T> {
131132
pub value: Option<T>,
132133
pub rule_index: Option<usize>,
133134
pub track_access_events: Option<bool>,
135+
pub debug_until_time: Option<u64>,
134136
pub last_modified: Option<u64>,
135137
pub variation_index: Option<usize>,
136138
pub version: Option<u64>,
@@ -168,6 +170,7 @@ impl Toggle {
168170
toggle_repo: &HashMap<String, Toggle>,
169171
is_detail: bool,
170172
deep: u8,
173+
debug_until_time: Option<u64>,
171174
) -> EvalDetail<Value> {
172175
let eval_param = EvalParams {
173176
user,
@@ -176,6 +179,7 @@ impl Toggle {
176179
key: &self.key,
177180
is_detail,
178181
variations: &self.variations,
182+
debug_until_time,
179183
};
180184

181185
match self.do_eval(&eval_param, deep) {
@@ -191,20 +195,41 @@ impl Toggle {
191195
) -> Result<EvalDetail<Value>, PrerequisiteError> {
192196
if !self.enabled {
193197
let v = self.disabled_serve.select_variation(eval_param).ok();
194-
return Ok(self.serve_variation(v, "disabled".to_owned(), None));
198+
return Ok(self.serve_variation(
199+
v,
200+
"disabled".to_owned(),
201+
None,
202+
eval_param.debug_until_time,
203+
));
195204
}
196205

197-
self.check_prerequisites(eval_param, max_deep)?;
206+
match self.check_prerequisites(eval_param, max_deep) {
207+
Ok(is_match) if !is_match => {
208+
return Ok(self.default_variation(eval_param, None));
209+
}
210+
Ok(_is_match) => {}
211+
Err(e) => return Err(e),
212+
}
198213

199214
for (i, rule) in self.rules.iter().enumerate() {
200215
match rule.serve_variation(eval_param) {
201216
Ok(v) => {
202217
if v.is_some() {
203-
return Ok(self.serve_variation(v, format!("rule {i}"), Some(i)));
218+
return Ok(self.serve_variation(
219+
v,
220+
format!("rule {i}"),
221+
Some(i),
222+
eval_param.debug_until_time,
223+
));
204224
}
205225
}
206226
Err(e) => {
207-
return Ok(self.serve_variation(None, format!("{e:?}"), Some(i)));
227+
return Ok(self.serve_variation(
228+
None,
229+
format!("{e:?}"),
230+
Some(i),
231+
eval_param.debug_until_time,
232+
));
208233
}
209234
}
210235
}
@@ -216,7 +241,7 @@ impl Toggle {
216241
&self,
217242
eval_param: &EvalParams,
218243
deep: u8,
219-
) -> Result<(), PrerequisiteError> {
244+
) -> Result<bool, PrerequisiteError> {
220245
if deep == 0 {
221246
return Err(PrerequisiteError::DeepOverflow);
222247
}
@@ -235,32 +260,35 @@ impl Toggle {
235260
user: eval_param.user,
236261
segment_repo: eval_param.segment_repo,
237262
toggle_repo: eval_param.toggle_repo,
263+
debug_until_time: eval_param.debug_until_time,
238264
},
239265
deep - 1,
240266
)?,
241267
};
242268

243269
match eval.value {
244270
Some(v) if v == pre.value => continue,
245-
_ => return Err(PrerequisiteError::NotMatch(pre.key.to_string())),
271+
_ => return Ok(false),
246272
}
247273
}
274+
return Ok(true);
248275
}
249-
250-
Ok(())
276+
Ok(true)
251277
}
252278

253279
fn serve_variation(
254280
&self,
255281
v: Option<Variation>,
256282
reason: String,
257283
rule_index: Option<usize>,
284+
debug_until_time: Option<u64>,
258285
) -> EvalDetail<Value> {
259286
EvalDetail {
260287
variation_index: v.as_ref().map(|v| v.index),
261288
value: v.map(|v| v.value),
262289
version: Some(self.version),
263290
track_access_events: self.track_access_events,
291+
debug_until_time,
264292
last_modified: self.last_modified,
265293
rule_index,
266294
reason,
@@ -273,10 +301,18 @@ impl Toggle {
273301
reason: Option<String>,
274302
) -> EvalDetail<Value> {
275303
match self.default_serve.select_variation(eval_param) {
276-
Ok(v) => {
277-
self.serve_variation(Some(v), concat_reason("default".to_owned(), reason), None)
278-
}
279-
Err(e) => self.serve_variation(None, concat_reason(format!("{e:?}"), reason), None),
304+
Ok(v) => self.serve_variation(
305+
Some(v),
306+
concat_reason("default".to_owned(), reason),
307+
None,
308+
eval_param.debug_until_time,
309+
),
310+
Err(e) => self.serve_variation(
311+
None,
312+
concat_reason(format!("{e:?}"), reason),
313+
None,
314+
eval_param.debug_until_time,
315+
),
280316
}
281317
}
282318

@@ -524,12 +560,14 @@ impl Segment {
524560
}
525561

526562
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
563+
#[serde(rename_all = "camelCase")]
527564
pub struct Repository {
528565
pub segments: HashMap<String, Segment>,
529566
pub toggles: HashMap<String, Toggle>,
530567
pub events: Option<Value>,
531568
// TODO: remove option next release
532569
pub version: Option<u128>,
570+
pub debug_until_time: Option<u64>,
533571
}
534572

535573
impl Default for Repository {
@@ -539,6 +577,7 @@ impl Default for Repository {
539577
toggles: Default::default(),
540578
events: Default::default(),
541579
version: Some(0),
580+
debug_until_time: None,
542581
}
543582
}
544583
}
@@ -612,7 +651,7 @@ mod tests {
612651

613652
let user = FPUser::new().with("city", "4");
614653
let toggle = repo.toggles.get("json_toggle").unwrap();
615-
let r = toggle.eval(&user, &repo.segments, &repo.toggles, false, MAX_DEEP);
654+
let r = toggle.eval(&user, &repo.segments, &repo.toggles, false, MAX_DEEP, None);
616655
let r = r.value.unwrap();
617656
let r = r.as_object().unwrap();
618657
assert!(r.get("variation_1").is_some());
@@ -629,7 +668,7 @@ mod tests {
629668

630669
let user = FPUser::new().with("city", "100");
631670
let toggle = repo.toggles.get("not_in_segment").unwrap();
632-
let r = toggle.eval(&user, &repo.segments, &repo.toggles, false, MAX_DEEP);
671+
let r = toggle.eval(&user, &repo.segments, &repo.toggles, false, MAX_DEEP, None);
633672
let r = r.value.unwrap();
634673
let r = r.as_object().unwrap();
635674
assert!(r.get("not_in").is_some());
@@ -646,19 +685,19 @@ mod tests {
646685

647686
let user = FPUser::new().with("city", "1").with("os", "linux");
648687
let toggle = repo.toggles.get("multi_condition_toggle").unwrap();
649-
let r = toggle.eval(&user, &repo.segments, &repo.toggles, false, MAX_DEEP);
688+
let r = toggle.eval(&user, &repo.segments, &repo.toggles, false, MAX_DEEP, None);
650689
let r = r.value.unwrap();
651690
let r = r.as_object().unwrap();
652691
assert!(r.get("variation_0").is_some());
653692

654693
let user = FPUser::new().with("os", "linux");
655694
let toggle = repo.toggles.get("multi_condition_toggle").unwrap();
656-
let r = toggle.eval(&user, &repo.segments, &repo.toggles, false, MAX_DEEP);
695+
let r = toggle.eval(&user, &repo.segments, &repo.toggles, false, MAX_DEEP, None);
657696
assert!(r.reason.starts_with("default"));
658697

659698
let user = FPUser::new().with("city", "1");
660699
let toggle = repo.toggles.get("multi_condition_toggle").unwrap();
661-
let r = toggle.eval(&user, &repo.segments, &repo.toggles, false, MAX_DEEP);
700+
let r = toggle.eval(&user, &repo.segments, &repo.toggles, false, MAX_DEEP, None);
662701
assert!(r.reason.starts_with("default"));
663702
}
664703

@@ -678,7 +717,7 @@ mod tests {
678717
let mut variation_1 = 0;
679718
let mut variation_2 = 0;
680719
for user in &users {
681-
let r = toggle.eval(&user, &repo.segments, &repo.toggles, false, MAX_DEEP);
720+
let r = toggle.eval(&user, &repo.segments, &repo.toggles, false, MAX_DEEP, None);
682721
let r = r.value.unwrap();
683722
let r = r.as_object().unwrap();
684723
if r.get("variation_0").is_some() {
@@ -709,7 +748,7 @@ mod tests {
709748

710749
let user = FPUser::new().with("city", "100");
711750
let toggle = repo.toggles.get("disabled_toggle").unwrap();
712-
let r = toggle.eval(&user, &repo.segments, &repo.toggles, false, MAX_DEEP);
751+
let r = toggle.eval(&user, &repo.segments, &repo.toggles, false, MAX_DEEP, None);
713752
assert!(r
714753
.value
715754
.unwrap()
@@ -731,7 +770,7 @@ mod tests {
731770
let user = FPUser::new().with("city", "4");
732771

733772
let toggle = repo.toggles.get("prerequisite_toggle").unwrap();
734-
let r = toggle.eval(&user, &repo.segments, &repo.toggles, false, MAX_DEEP);
773+
let r = toggle.eval(&user, &repo.segments, &repo.toggles, false, MAX_DEEP, None);
735774

736775
assert!(r.value.unwrap().as_object().unwrap().get("2").is_some());
737776
}
@@ -748,7 +787,7 @@ mod tests {
748787
let user = FPUser::new().with("city", "4");
749788

750789
let toggle = repo.toggles.get("prerequisite_toggle_not_exist").unwrap();
751-
let r = toggle.eval(&user, &repo.segments, &repo.toggles, false, MAX_DEEP);
790+
let r = toggle.eval(&user, &repo.segments, &repo.toggles, false, MAX_DEEP, None);
752791

753792
assert!(r.value.unwrap().as_object().unwrap().get("1").is_some());
754793
assert!(r.reason.contains("not exist"));
@@ -766,10 +805,10 @@ mod tests {
766805
let user = FPUser::new().with("city", "4");
767806

768807
let toggle = repo.toggles.get("prerequisite_toggle_not_match").unwrap();
769-
let r = toggle.eval(&user, &repo.segments, &repo.toggles, false, MAX_DEEP);
808+
let r = toggle.eval(&user, &repo.segments, &repo.toggles, false, MAX_DEEP, None);
770809

771810
assert!(r.value.unwrap().as_object().unwrap().get("1").is_some());
772-
assert!(r.reason.contains("not match"));
811+
assert!(r.reason.contains("default."));
773812
}
774813

775814
#[test]
@@ -784,7 +823,7 @@ mod tests {
784823
let user = FPUser::new().with("city", "4");
785824

786825
let toggle = repo.toggles.get("prerequisite_toggle").unwrap();
787-
let r = toggle.eval(&user, &repo.segments, &repo.toggles, false, 1);
826+
let r = toggle.eval(&user, &repo.segments, &repo.toggles, false, 1, None);
788827

789828
assert!(r.value.unwrap().as_object().unwrap().get("1").is_some());
790829
assert!(r.reason.contains("deep overflow"));
@@ -828,6 +867,7 @@ mod distribution_tests {
828867
variations: &[],
829868
segment_repo: &Default::default(),
830869
toggle_repo: &Default::default(),
870+
debug_until_time: None,
831871
};
832872
let result = distribution.find_index(&params);
833873

@@ -854,6 +894,7 @@ mod distribution_tests {
854894
variations: &[],
855895
segment_repo: &Default::default(),
856896
toggle_repo: &Default::default(),
897+
debug_until_time: None,
857898
};
858899
let result = distribution.find_index(&params);
859900

@@ -866,6 +907,7 @@ mod distribution_tests {
866907
variations: &[],
867908
segment_repo: &Default::default(),
868909
toggle_repo: &Default::default(),
910+
debug_until_time: None,
869911
};
870912
let result = distribution.find_index(&params_no_detail);
871913
assert!(result.is_err());
@@ -895,6 +937,7 @@ mod distribution_tests {
895937
],
896938
segment_repo: &Default::default(),
897939
toggle_repo: &Default::default(),
940+
debug_until_time: None,
898941
};
899942

900943
let result = serve.select_variation(&params).expect_err("e");
@@ -1245,7 +1288,7 @@ mod condition_tests {
12451288

12461289
let user = FPUser::new().with("city", "1");
12471290
let toggle = repo.toggles.get("json_toggle").unwrap();
1248-
let r = toggle.eval(&user, &repo.segments, &repo.toggles, false, MAX_DEEP);
1291+
let r = toggle.eval(&user, &repo.segments, &repo.toggles, false, MAX_DEEP, None);
12491292
let r = r.value.unwrap();
12501293
let r = r.as_object().unwrap();
12511294
assert!(r.get("variation_0").is_some());

0 commit comments

Comments
 (0)