@@ -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" ) ]
130131pub 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" ) ]
527564pub 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
535573impl 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