@@ -18,66 +18,67 @@ use crate::Feature;
18
18
use std:: collections:: HashMap ;
19
19
20
20
use super :: feature_proxy:: random_value;
21
- use crate :: segment_evaluation:: find_applicable_segment_rule_for_entity ;
21
+ use crate :: segment_evaluation:: SegmentRules ;
22
22
23
23
use crate :: errors:: Result ;
24
24
25
25
/// Provides a snapshot of a [`Feature`].
26
26
#[ derive( Debug ) ]
27
27
pub struct FeatureSnapshot {
28
- feature : crate :: models:: Feature ,
29
- segments : HashMap < String , crate :: models:: Segment > ,
28
+ enabled : bool ,
29
+ enabled_value : Value ,
30
+ disabled_value : Value ,
31
+ rollout_percentage : u32 ,
32
+ name : String ,
33
+ feature_id : String ,
34
+ segment_rules : SegmentRules ,
30
35
}
31
36
32
37
impl FeatureSnapshot {
33
38
pub ( crate ) fn new (
34
39
feature : crate :: models:: Feature ,
35
40
segments : HashMap < String , crate :: models:: Segment > ,
36
41
) -> Self {
37
- Self { feature, segments }
42
+ let segment_rules = SegmentRules :: new ( segments, feature. segment_rules , feature. kind ) ;
43
+ Self {
44
+ enabled : feature. enabled , // TODO: Based on this enabled value we can create two different implementations, as the disabled one is much more simpler.
45
+ enabled_value : ( feature. kind , feature. enabled_value )
46
+ . try_into ( )
47
+ . expect ( "TODO: Handle this error" ) ,
48
+ disabled_value : ( feature. kind , feature. disabled_value )
49
+ . try_into ( )
50
+ . expect ( "TODO: Handle this error" ) ,
51
+ rollout_percentage : feature. rollout_percentage ,
52
+ segment_rules,
53
+ name : feature. name ,
54
+ feature_id : feature. feature_id ,
55
+ }
38
56
}
39
57
40
- fn evaluate_feature_for_entity (
41
- & self ,
42
- entity : & impl Entity ,
43
- ) -> Result < crate :: models:: ConfigValue > {
44
- if !self . feature . enabled {
45
- return Ok ( self . feature . disabled_value . clone ( ) ) ;
58
+ fn evaluate_feature_for_entity ( & self , entity : & impl Entity ) -> Result < Value > {
59
+ if !self . enabled {
60
+ return Ok ( self . disabled_value . clone ( ) ) ;
46
61
}
47
62
48
- if self . feature . segment_rules . is_empty ( ) || entity. get_attributes ( ) . is_empty ( ) {
63
+ if self . segment_rules . is_empty ( ) || entity. get_attributes ( ) . is_empty ( ) {
49
64
// No match possible. Do not consider segment rules:
50
65
return self . use_rollout_percentage_to_get_value_from_feature_directly ( entity) ;
51
66
}
52
67
53
- match find_applicable_segment_rule_for_entity (
54
- & self . segments ,
55
- & self . feature . segment_rules ,
56
- entity,
57
- ) ? {
68
+ match self
69
+ . segment_rules
70
+ . find_applicable_segment_rule_for_entity ( entity) ?
71
+ {
58
72
Some ( segment_rule) => {
59
73
// Get rollout percentage
60
- let rollout_percentage = match & segment_rule. rollout_percentage {
61
- Some ( value) => {
62
- if value. is_default ( ) {
63
- self . feature . rollout_percentage
64
- } else {
65
- u32:: try_from ( value. as_u64 ( ) . expect ( "Rollout value is not u64." ) )
66
- . expect ( "Invalid rollout value. Could not convert to u32." )
67
- }
68
- }
69
- None => panic ! ( "Rollout value is missing." ) ,
70
- } ;
74
+ let rollout_percentage =
75
+ segment_rule. rollout_percentage ( self . rollout_percentage ) ?;
71
76
72
77
// Should rollout?
73
- if Self :: should_rollout ( rollout_percentage, entity, & self . feature . feature_id ) {
74
- if segment_rule. value . is_default ( ) {
75
- Ok ( self . feature . enabled_value . clone ( ) )
76
- } else {
77
- Ok ( segment_rule. value . clone ( ) )
78
- }
78
+ if Self :: should_rollout ( rollout_percentage, entity, & self . feature_id ) {
79
+ segment_rule. value ( & self . enabled_value )
79
80
} else {
80
- Ok ( self . feature . disabled_value . clone ( ) )
81
+ Ok ( self . disabled_value . clone ( ) )
81
82
}
82
83
}
83
84
None => self . use_rollout_percentage_to_get_value_from_feature_directly ( entity) ,
@@ -92,28 +93,27 @@ impl FeatureSnapshot {
92
93
fn use_rollout_percentage_to_get_value_from_feature_directly (
93
94
& self ,
94
95
entity : & impl Entity ,
95
- ) -> Result < crate :: models :: ConfigValue > {
96
- let rollout_percentage = self . feature . rollout_percentage ;
97
- if Self :: should_rollout ( rollout_percentage, entity, & self . feature . feature_id ) {
98
- Ok ( self . feature . enabled_value . clone ( ) )
96
+ ) -> Result < Value > {
97
+ let rollout_percentage = self . rollout_percentage ;
98
+ if Self :: should_rollout ( rollout_percentage, entity, & self . feature_id ) {
99
+ Ok ( self . enabled_value . clone ( ) )
99
100
} else {
100
- Ok ( self . feature . disabled_value . clone ( ) )
101
+ Ok ( self . disabled_value . clone ( ) )
101
102
}
102
103
}
103
104
}
104
105
105
106
impl Feature for FeatureSnapshot {
106
107
fn get_name ( & self ) -> Result < String > {
107
- Ok ( self . feature . name . clone ( ) )
108
+ Ok ( self . name . clone ( ) )
108
109
}
109
110
110
111
fn is_enabled ( & self ) -> Result < bool > {
111
- Ok ( self . feature . enabled )
112
+ Ok ( self . enabled )
112
113
}
113
114
114
115
fn get_value ( & self , entity : & impl Entity ) -> Result < Value > {
115
- let model_value = self . evaluate_feature_for_entity ( entity) ?;
116
- ( self . feature . kind , model_value) . try_into ( )
116
+ self . evaluate_feature_for_entity ( entity)
117
117
}
118
118
119
119
fn get_value_into < T : TryFrom < Value , Error = crate :: Error > > (
@@ -186,7 +186,7 @@ pub mod tests {
186
186
attributes : entity_attributes. clone ( ) ,
187
187
} ;
188
188
assert_eq ! (
189
- random_value( format!( "{}:{}" , entity. id, feature. feature . feature_id) . as_str( ) ) ,
189
+ random_value( format!( "{}:{}" , entity. id, feature. feature_id) . as_str( ) ) ,
190
190
68
191
191
) ;
192
192
let value = feature. get_value ( & entity) . unwrap ( ) ;
@@ -198,7 +198,7 @@ pub mod tests {
198
198
attributes : entity_attributes,
199
199
} ;
200
200
assert_eq ! (
201
- random_value( format!( "{}:{}" , entity. id, feature. feature . feature_id) . as_str( ) ) ,
201
+ random_value( format!( "{}:{}" , entity. id, feature. feature_id) . as_str( ) ) ,
202
202
29
203
203
) ;
204
204
let value = feature. get_value ( & entity) . unwrap ( ) ;
0 commit comments