@@ -28,12 +28,20 @@ pub struct MultivariateFeatureStateValue {
2828 pub mv_fs_value_uuid : String ,
2929}
3030
31+ #[ derive( Serialize , Deserialize , Clone , Debug ) ]
32+ pub struct FeatureSegment {
33+ pub priority : u32 ,
34+ }
35+
3136#[ derive( Serialize , Deserialize , Clone , Debug ) ]
3237pub struct FeatureState {
3338 pub feature : Feature ,
3439 pub enabled : bool ,
3540 pub django_id : Option < u32 > ,
3641
42+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
43+ pub feature_segment : Option < FeatureSegment > ,
44+
3745 #[ serde( default = "utils::get_uuid" ) ]
3846 pub featurestate_uuid : String ,
3947 pub multivariate_feature_state_values : Vec < MultivariateFeatureStateValue > ,
@@ -51,6 +59,25 @@ impl FeatureState {
5159 } ;
5260 return value;
5361 }
62+
63+ // Returns `true` if `self` is higher segment priority than `other`
64+ // (i.e. has lower value for feature_segment.priority)
65+ // NOTE:
66+ // A segment will be considered higher priority only if:
67+ // 1. `other` does not have a feature segment(i.e: it is an environment feature state or it's a
68+ // feature state with feature segment but from an old document that does not have `feature_segment.priority`)
69+ // but `self` does.
70+
71+ // 2. `other` have a feature segment but with lower priority
72+ pub fn is_higher_segment_priority ( & self , other : & FeatureState ) -> bool {
73+ match & other. feature_segment {
74+ None if self . feature_segment . is_some ( ) => true ,
75+ Some ( feature_segment) if self . feature_segment . is_some ( ) => {
76+ self . feature_segment . as_ref ( ) . unwrap ( ) . priority < feature_segment. priority
77+ }
78+ _ => false ,
79+ }
80+ }
5481 fn get_multivariate_value ( & self , identity_id : & str ) -> FlagsmithValue {
5582 let object_id = match self . django_id {
5683 Some ( django_id) => django_id. to_string ( ) ,
@@ -144,6 +171,64 @@ mod tests {
144171 assert_eq ! ( given_json, feature_state_json)
145172 }
146173
174+ #[ test]
175+ fn feature_state_is_higher_segment_priority ( ) {
176+ // Given
177+ let feature_state_json = serde_json:: json!(
178+ {
179+ "multivariate_feature_state_values" : [ ] ,
180+ "feature_state_value" : 1 ,
181+ "featurestate_uuid" : "a6ff815f-63ed-4e72-99dc-9124c442ce4d" ,
182+ "django_id" : 1 ,
183+ "feature" : {
184+ "name" : "feature1" ,
185+ "type" : null,
186+ "id" : 1
187+ } ,
188+ "enabled" : false
189+ }
190+ ) ;
191+ let mut feature_state_1: FeatureState =
192+ serde_json:: from_value ( feature_state_json. clone ( ) ) . unwrap ( ) ;
193+ let mut feature_state_2: FeatureState =
194+ serde_json:: from_value ( feature_state_json. clone ( ) ) . unwrap ( ) ;
195+
196+ // Firstly, since both fs do not have feature segment this should be false
197+ assert_eq ! (
198+ feature_state_1. is_higher_segment_priority( & feature_state_2) ,
199+ false
200+ ) ;
201+ assert_eq ! (
202+ feature_state_2. is_higher_segment_priority( & feature_state_1) ,
203+ false
204+ ) ;
205+
206+ // Now add feature_segment to feature_state_2
207+ feature_state_2. feature_segment = Some ( FeatureSegment { priority : 1 } ) ;
208+
209+ // Since `feature_state_2` have a feature segment this should be false as well
210+ assert_eq ! (
211+ feature_state_1. is_higher_segment_priority( & feature_state_2) ,
212+ false
213+ ) ;
214+ // And, this true
215+ assert_eq ! (
216+ feature_state_2. is_higher_segment_priority( & feature_state_1) ,
217+ true
218+ ) ;
219+
220+ // Next, let's add a feature segment with higher priority to `feature_state_1`
221+ feature_state_1. feature_segment = Some ( FeatureSegment { priority : 0 } ) ;
222+ assert_eq ! (
223+ feature_state_1. is_higher_segment_priority( & feature_state_2) ,
224+ true
225+ ) ;
226+ assert_eq ! (
227+ feature_state_2. is_higher_segment_priority( & feature_state_1) ,
228+ false
229+ ) ;
230+ }
231+
147232 #[ rstest]
148233 #[ case( "2" , "foo" . to_string( ) ) ] // Generated hash percentage 26
149234 #[ case( "8" , "bar" . to_string( ) ) ] // Generated hash percentage 38
0 commit comments