@@ -5,35 +5,79 @@ module Api
55 # Retrieves split definitions from the Split Backend
66 class Splits < Client
77
8+ PROXY_CHECK_INTERVAL_SECONDS = 24 * 60 * 60
9+ SPEC_1_1 = "1.1"
10+
811 def initialize ( api_key , config , telemetry_runtime_producer )
912 super ( config )
1013 @api_key = api_key
1114 @telemetry_runtime_producer = telemetry_runtime_producer
1215 @flag_sets_filter = @config . flag_sets_filter
16+ @spec_version = SplitIoClient ::Spec ::FeatureFlags ::SPEC_VERSION
17+ @last_proxy_check_timestamp = 0
18+ @clear_storage = false
19+ @old_spec_since = nil
1320 end
1421
1522 def since ( since , since_rbs , fetch_options = { cache_control_headers : false , till : nil , sets : nil } )
1623 start = Time . now
24+
25+ if check_last_proxy_check_timestamp
26+ @spec_version = SplitIoClient ::Spec ::FeatureFlags ::SPEC_VERSION
27+ @config . logger . debug ( "Switching to new Feature flag spec #{ @spec_version } and fetching." )
28+ @old_spec_since = since
29+ since = -1
30+ since_rbs = -1
31+ fetch_options = { cache_control_headers : false , till : nil , sets : nil }
32+ end
33+
34+ if @spec_version == Splits ::SPEC_1_1
35+ since = @old_spec_since unless @old_spec_since . nil?
36+ params = { s : @spec_version , since : since }
37+ @old_spec_since = nil
38+ else
39+ params = { s : @spec_version , since : since , rbSince : since_rbs }
40+ end
1741
18- params = { s : SplitIoClient ::Spec ::FeatureFlags ::SPEC_VERSION , since : since , rbSince : since_rbs }
1942 params [ :sets ] = @flag_sets_filter . join ( "," ) unless @flag_sets_filter . empty?
2043 params [ :till ] = fetch_options [ :till ] unless fetch_options [ :till ] . nil?
2144 @config . logger . debug ( "Fetching from splitChanges with #{ params } : " )
2245 response = get_api ( "#{ @config . base_uri } /splitChanges" , @api_key , params , fetch_options [ :cache_control_headers ] )
46+
2347 if response . status == 414
2448 @config . logger . error ( "Error fetching feature flags; the amount of flag sets provided are too big, causing uri length error." )
2549 raise ApiException . new response . body , 414
2650 end
51+
52+ if response . status == 400 and sdk_url_overriden? and @spec_version == SplitIoClient ::Spec ::FeatureFlags ::SPEC_VERSION
53+ @config . logger . warn ( "Detected proxy response error, changing spec version from #{ @spec_version } to #{ Splits ::SPEC_1_1 } and re-fetching." )
54+ @spec_version = Splits ::SPEC_1_1
55+ @last_proxy_check_timestamp = Time . now
56+ return since ( since , 0 , fetch_options = { cache_control_headers : fetch_options [ :cache_control_headers ] , till : fetch_options [ :till ] ,
57+ sets : fetch_options [ :sets ] } )
58+ end
59+
2760 if response . success?
28- result = objects_with_segment_names ( response . body )
61+ result = JSON . parse ( response . body , symbolize_names : true )
62+ if @spec_version == Splits ::SPEC_1_1
63+ result = convert_to_newSPEC ( result )
64+ end
65+
66+ result [ :rbs ] [ :d ] = check_rbs_data ( result [ :rbs ] [ :d ] )
67+ result = objects_with_segment_names ( result )
2968
69+ if @spec_version == SplitIoClient ::Spec ::FeatureFlags ::SPEC_VERSION
70+ @clear_storage = @last_proxy_check_timestamp != 0
71+ @last_proxy_check_timestamp = 0
72+ end
73+
3074 unless result [ :ff ] [ :d ] . empty?
3175 @config . split_logger . log_if_debug ( "#{ result [ :ff ] [ :d ] . length } feature flags retrieved. since=#{ since } " )
3276 end
3377 @config . split_logger . log_if_transport ( "Feature flag changes response: #{ result [ :ff ] . to_s } " )
3478
3579 unless result [ :rbs ] [ :d ] . empty?
36- @config . split_logger . log_if_debug ( "#{ result [ :ff ] [ :d ] . length } rule based segments retrieved. since=#{ since_rbs } " )
80+ @config . split_logger . log_if_debug ( "#{ result [ :rbs ] [ :d ] . length } rule based segments retrieved. since=#{ since_rbs } " )
3781 end
3882 @config . split_logger . log_if_transport ( "rule based segments changes response: #{ result [ :rbs ] . to_s } " )
3983
@@ -52,21 +96,42 @@ def since(since, since_rbs, fetch_options = { cache_control_headers: false, till
5296 end
5397 end
5498
99+ def clear_storage
100+ @clear_storage
101+ end
102+
55103 private
56104
57- def objects_with_segment_names ( objects_json )
58- parsed_objects = JSON . parse ( objects_json , symbolize_names : true )
105+ def check_rbs_data ( rbs_data )
106+ rbs_data . each do |rb_segment |
107+ rb_segment [ :excluded ] = { :keys => [ ] , :segments => [ ] } if rb_segment [ :excluded ] . nil?
108+ rb_segment [ :excluded ] [ :keys ] = [ ] if rb_segment [ :excluded ] [ :keys ] . nil?
109+ rb_segment [ :excluded ] [ :segments ] = [ ] if rb_segment [ :excluded ] [ :segments ] . nil?
110+ end
111+ rbs_data
112+ end
113+
114+ def objects_with_segment_names ( parsed_objects )
115+ parsed_objects [ :segment_names ] = Set . new
59116 parsed_objects [ :segment_names ] =
60117 parsed_objects [ :ff ] [ :d ] . each_with_object ( Set . new ) do |split , splits |
61118 splits << Helpers ::Util . segment_names_by_object ( split , "IN_SEGMENT" )
62119 end . flatten
63- if not parsed_objects [ :ff ] [ :rbs ] . nil?
64- parsed_objects [ :segment_names ] . merge parsed_objects [ :ff ] [ :rbs ] . each_with_object ( Set . new ) do |rule_based_segment , rule_based_segments |
65- rule_based_segments << Helpers ::Util . segment_names_by_object ( rule_based_segment , "IN_SEGMENT" )
66- end . flatten
120+
121+ parsed_objects [ :rbs ] [ :d ] . each do |rule_based_segment |
122+ parsed_objects [ :segment_names ] . merge Helpers ::Util . segment_names_in_rb_segment ( rule_based_segment , "IN_SEGMENT" )
67123 end
124+
68125 parsed_objects
69126 end
127+
128+ def check_last_proxy_check_timestamp
129+ @spec_version == Splits ::SPEC_1_1 and ( ( Time . now - @last_proxy_check_timestamp ) >= Splits ::PROXY_CHECK_INTERVAL_SECONDS )
130+ end
131+
132+ def convert_to_newSPEC ( body )
133+ { :ff => { :d => body [ :splits ] , :s => body [ :since ] , :t => body [ :till ] } , :rbs => { :d => [ ] , :s => -1 , :t => -1 } }
134+ end
70135 end
71136 end
72137end
0 commit comments