@@ -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,42 @@ 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_pass) => {
208+ if !is_pass {
209+ return Ok ( self . default_variation ( eval_param, None ) ) ;
210+ }
211+ }
212+ Err ( e) => return Err ( e) ,
213+ }
198214
199215 for ( i, rule) in self . rules . iter ( ) . enumerate ( ) {
200216 match rule. serve_variation ( eval_param) {
201217 Ok ( v) => {
202218 if v. is_some ( ) {
203- return Ok ( self . serve_variation ( v, format ! ( "rule {i}" ) , Some ( i) ) ) ;
219+ return Ok ( self . serve_variation (
220+ v,
221+ format ! ( "rule {i}" ) ,
222+ Some ( i) ,
223+ eval_param. debug_until_time ,
224+ ) ) ;
204225 }
205226 }
206227 Err ( e) => {
207- return Ok ( self . serve_variation ( None , format ! ( "{e:?}" ) , Some ( i) ) ) ;
228+ return Ok ( self . serve_variation (
229+ None ,
230+ format ! ( "{e:?}" ) ,
231+ Some ( i) ,
232+ eval_param. debug_until_time ,
233+ ) ) ;
208234 }
209235 }
210236 }
@@ -216,7 +242,7 @@ impl Toggle {
216242 & self ,
217243 eval_param : & EvalParams ,
218244 deep : u8 ,
219- ) -> Result < ( ) , PrerequisiteError > {
245+ ) -> Result < bool , PrerequisiteError > {
220246 if deep == 0 {
221247 return Err ( PrerequisiteError :: DeepOverflow ) ;
222248 }
@@ -235,32 +261,35 @@ impl Toggle {
235261 user : eval_param. user ,
236262 segment_repo : eval_param. segment_repo ,
237263 toggle_repo : eval_param. toggle_repo ,
264+ debug_until_time : eval_param. debug_until_time ,
238265 } ,
239266 deep - 1 ,
240267 ) ?,
241268 } ;
242269
243270 match eval. value {
244271 Some ( v) if v == pre. value => continue ,
245- _ => return Err ( PrerequisiteError :: NotMatch ( pre . key . to_string ( ) ) ) ,
272+ _ => return Ok ( false ) ,
246273 }
247274 }
275+ return Ok ( true ) ;
248276 }
249-
250- Ok ( ( ) )
277+ Ok ( true )
251278 }
252279
253280 fn serve_variation (
254281 & self ,
255282 v : Option < Variation > ,
256283 reason : String ,
257284 rule_index : Option < usize > ,
285+ debug_until_time : Option < u64 > ,
258286 ) -> EvalDetail < Value > {
259287 EvalDetail {
260288 variation_index : v. as_ref ( ) . map ( |v| v. index ) ,
261289 value : v. map ( |v| v. value ) ,
262290 version : Some ( self . version ) ,
263291 track_access_events : self . track_access_events ,
292+ debug_until_time,
264293 last_modified : self . last_modified ,
265294 rule_index,
266295 reason,
@@ -273,10 +302,18 @@ impl Toggle {
273302 reason : Option < String > ,
274303 ) -> EvalDetail < Value > {
275304 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 ) ,
305+ Ok ( v) => self . serve_variation (
306+ Some ( v) ,
307+ concat_reason ( "default" . to_owned ( ) , reason) ,
308+ None ,
309+ eval_param. debug_until_time ,
310+ ) ,
311+ Err ( e) => self . serve_variation (
312+ None ,
313+ concat_reason ( format ! ( "{e:?}" ) , reason) ,
314+ None ,
315+ eval_param. debug_until_time ,
316+ ) ,
280317 }
281318 }
282319
@@ -524,12 +561,14 @@ impl Segment {
524561}
525562
526563#[ derive( Serialize , Deserialize , Debug , PartialEq , Clone ) ]
564+ #[ serde( rename_all = "camelCase" ) ]
527565pub struct Repository {
528566 pub segments : HashMap < String , Segment > ,
529567 pub toggles : HashMap < String , Toggle > ,
530568 pub events : Option < Value > ,
531569 // TODO: remove option next release
532570 pub version : Option < u128 > ,
571+ pub debug_until_time : Option < u64 > ,
533572}
534573
535574impl Default for Repository {
@@ -539,6 +578,7 @@ impl Default for Repository {
539578 toggles : Default :: default ( ) ,
540579 events : Default :: default ( ) ,
541580 version : Some ( 0 ) ,
581+ debug_until_time : None ,
542582 }
543583 }
544584}
@@ -612,7 +652,7 @@ mod tests {
612652
613653 let user = FPUser :: new ( ) . with ( "city" , "4" ) ;
614654 let toggle = repo. toggles . get ( "json_toggle" ) . unwrap ( ) ;
615- let r = toggle. eval ( & user, & repo. segments , & repo. toggles , false , MAX_DEEP ) ;
655+ let r = toggle. eval ( & user, & repo. segments , & repo. toggles , false , MAX_DEEP , None ) ;
616656 let r = r. value . unwrap ( ) ;
617657 let r = r. as_object ( ) . unwrap ( ) ;
618658 assert ! ( r. get( "variation_1" ) . is_some( ) ) ;
@@ -629,7 +669,7 @@ mod tests {
629669
630670 let user = FPUser :: new ( ) . with ( "city" , "100" ) ;
631671 let toggle = repo. toggles . get ( "not_in_segment" ) . unwrap ( ) ;
632- let r = toggle. eval ( & user, & repo. segments , & repo. toggles , false , MAX_DEEP ) ;
672+ let r = toggle. eval ( & user, & repo. segments , & repo. toggles , false , MAX_DEEP , None ) ;
633673 let r = r. value . unwrap ( ) ;
634674 let r = r. as_object ( ) . unwrap ( ) ;
635675 assert ! ( r. get( "not_in" ) . is_some( ) ) ;
@@ -646,19 +686,19 @@ mod tests {
646686
647687 let user = FPUser :: new ( ) . with ( "city" , "1" ) . with ( "os" , "linux" ) ;
648688 let toggle = repo. toggles . get ( "multi_condition_toggle" ) . unwrap ( ) ;
649- let r = toggle. eval ( & user, & repo. segments , & repo. toggles , false , MAX_DEEP ) ;
689+ let r = toggle. eval ( & user, & repo. segments , & repo. toggles , false , MAX_DEEP , None ) ;
650690 let r = r. value . unwrap ( ) ;
651691 let r = r. as_object ( ) . unwrap ( ) ;
652692 assert ! ( r. get( "variation_0" ) . is_some( ) ) ;
653693
654694 let user = FPUser :: new ( ) . with ( "os" , "linux" ) ;
655695 let toggle = repo. toggles . get ( "multi_condition_toggle" ) . unwrap ( ) ;
656- let r = toggle. eval ( & user, & repo. segments , & repo. toggles , false , MAX_DEEP ) ;
696+ let r = toggle. eval ( & user, & repo. segments , & repo. toggles , false , MAX_DEEP , None ) ;
657697 assert ! ( r. reason. starts_with( "default" ) ) ;
658698
659699 let user = FPUser :: new ( ) . with ( "city" , "1" ) ;
660700 let toggle = repo. toggles . get ( "multi_condition_toggle" ) . unwrap ( ) ;
661- let r = toggle. eval ( & user, & repo. segments , & repo. toggles , false , MAX_DEEP ) ;
701+ let r = toggle. eval ( & user, & repo. segments , & repo. toggles , false , MAX_DEEP , None ) ;
662702 assert ! ( r. reason. starts_with( "default" ) ) ;
663703 }
664704
@@ -678,7 +718,7 @@ mod tests {
678718 let mut variation_1 = 0 ;
679719 let mut variation_2 = 0 ;
680720 for user in & users {
681- let r = toggle. eval ( & user, & repo. segments , & repo. toggles , false , MAX_DEEP ) ;
721+ let r = toggle. eval ( & user, & repo. segments , & repo. toggles , false , MAX_DEEP , None ) ;
682722 let r = r. value . unwrap ( ) ;
683723 let r = r. as_object ( ) . unwrap ( ) ;
684724 if r. get ( "variation_0" ) . is_some ( ) {
@@ -709,7 +749,7 @@ mod tests {
709749
710750 let user = FPUser :: new ( ) . with ( "city" , "100" ) ;
711751 let toggle = repo. toggles . get ( "disabled_toggle" ) . unwrap ( ) ;
712- let r = toggle. eval ( & user, & repo. segments , & repo. toggles , false , MAX_DEEP ) ;
752+ let r = toggle. eval ( & user, & repo. segments , & repo. toggles , false , MAX_DEEP , None ) ;
713753 assert ! ( r
714754 . value
715755 . unwrap( )
@@ -731,7 +771,7 @@ mod tests {
731771 let user = FPUser :: new ( ) . with ( "city" , "4" ) ;
732772
733773 let toggle = repo. toggles . get ( "prerequisite_toggle" ) . unwrap ( ) ;
734- let r = toggle. eval ( & user, & repo. segments , & repo. toggles , false , MAX_DEEP ) ;
774+ let r = toggle. eval ( & user, & repo. segments , & repo. toggles , false , MAX_DEEP , None ) ;
735775
736776 assert ! ( r. value. unwrap( ) . as_object( ) . unwrap( ) . get( "2" ) . is_some( ) ) ;
737777 }
@@ -748,7 +788,7 @@ mod tests {
748788 let user = FPUser :: new ( ) . with ( "city" , "4" ) ;
749789
750790 let toggle = repo. toggles . get ( "prerequisite_toggle_not_exist" ) . unwrap ( ) ;
751- let r = toggle. eval ( & user, & repo. segments , & repo. toggles , false , MAX_DEEP ) ;
791+ let r = toggle. eval ( & user, & repo. segments , & repo. toggles , false , MAX_DEEP , None ) ;
752792
753793 assert ! ( r. value. unwrap( ) . as_object( ) . unwrap( ) . get( "1" ) . is_some( ) ) ;
754794 assert ! ( r. reason. contains( "not exist" ) ) ;
@@ -766,10 +806,10 @@ mod tests {
766806 let user = FPUser :: new ( ) . with ( "city" , "4" ) ;
767807
768808 let toggle = repo. toggles . get ( "prerequisite_toggle_not_match" ) . unwrap ( ) ;
769- let r = toggle. eval ( & user, & repo. segments , & repo. toggles , false , MAX_DEEP ) ;
809+ let r = toggle. eval ( & user, & repo. segments , & repo. toggles , false , MAX_DEEP , None ) ;
770810
771811 assert ! ( r. value. unwrap( ) . as_object( ) . unwrap( ) . get( "1" ) . is_some( ) ) ;
772- assert ! ( r. reason. contains( "not match " ) ) ;
812+ assert ! ( r. reason. contains( "default. " ) ) ;
773813 }
774814
775815 #[ test]
@@ -784,7 +824,7 @@ mod tests {
784824 let user = FPUser :: new ( ) . with ( "city" , "4" ) ;
785825
786826 let toggle = repo. toggles . get ( "prerequisite_toggle" ) . unwrap ( ) ;
787- let r = toggle. eval ( & user, & repo. segments , & repo. toggles , false , 1 ) ;
827+ let r = toggle. eval ( & user, & repo. segments , & repo. toggles , false , 1 , None ) ;
788828
789829 assert ! ( r. value. unwrap( ) . as_object( ) . unwrap( ) . get( "1" ) . is_some( ) ) ;
790830 assert ! ( r. reason. contains( "deep overflow" ) ) ;
@@ -828,6 +868,7 @@ mod distribution_tests {
828868 variations : & [ ] ,
829869 segment_repo : & Default :: default ( ) ,
830870 toggle_repo : & Default :: default ( ) ,
871+ debug_until_time : None ,
831872 } ;
832873 let result = distribution. find_index ( & params) ;
833874
@@ -854,6 +895,7 @@ mod distribution_tests {
854895 variations : & [ ] ,
855896 segment_repo : & Default :: default ( ) ,
856897 toggle_repo : & Default :: default ( ) ,
898+ debug_until_time : None ,
857899 } ;
858900 let result = distribution. find_index ( & params) ;
859901
@@ -866,6 +908,7 @@ mod distribution_tests {
866908 variations : & [ ] ,
867909 segment_repo : & Default :: default ( ) ,
868910 toggle_repo : & Default :: default ( ) ,
911+ debug_until_time : None ,
869912 } ;
870913 let result = distribution. find_index ( & params_no_detail) ;
871914 assert ! ( result. is_err( ) ) ;
@@ -895,6 +938,7 @@ mod distribution_tests {
895938 ] ,
896939 segment_repo : & Default :: default ( ) ,
897940 toggle_repo : & Default :: default ( ) ,
941+ debug_until_time : None ,
898942 } ;
899943
900944 let result = serve. select_variation ( & params) . expect_err ( "e" ) ;
@@ -1245,7 +1289,7 @@ mod condition_tests {
12451289
12461290 let user = FPUser :: new ( ) . with ( "city" , "1" ) ;
12471291 let toggle = repo. toggles . get ( "json_toggle" ) . unwrap ( ) ;
1248- let r = toggle. eval ( & user, & repo. segments , & repo. toggles , false , MAX_DEEP ) ;
1292+ let r = toggle. eval ( & user, & repo. segments , & repo. toggles , false , MAX_DEEP , None ) ;
12491293 let r = r. value . unwrap ( ) ;
12501294 let r = r. as_object ( ) . unwrap ( ) ;
12511295 assert ! ( r. get( "variation_0" ) . is_some( ) ) ;
0 commit comments