diff --git a/lib/splitclient-rb/cache/repositories/segments_repository.rb b/lib/splitclient-rb/cache/repositories/segments_repository.rb index a45ee167..1f97464a 100644 --- a/lib/splitclient-rb/cache/repositories/segments_repository.rb +++ b/lib/splitclient-rb/cache/repositories/segments_repository.rb @@ -39,6 +39,10 @@ def used_segment_names @adapter.get_set(namespace_key('.segments.registered')) end + def remove_registered_segment(name) + @adapter.delete_from_set(namespace_key('.segments.registered'), name) + end + def set_change_number(name, last_change) @adapter.set_string(namespace_key(".segment.#{name}.till"), last_change) end diff --git a/lib/splitclient-rb/engine/api/segments.rb b/lib/splitclient-rb/engine/api/segments.rb index 7f4a2f8d..a4d8ec81 100644 --- a/lib/splitclient-rb/engine/api/segments.rb +++ b/lib/splitclient-rb/engine/api/segments.rb @@ -19,6 +19,12 @@ def fetch_segments_by_names(names, fetch_options = { cache_control_headers: fals loop do segment = fetch_segment_changes(name, since, fetch_options) + + if segment.nil? + @segments_repository.remove_registered_segment(name) + break + end + @segments_repository.add_to_segment(segment) @config.split_logger.log_if_debug("Segment #{name} fetched before: #{since}, \ @@ -64,6 +70,9 @@ def fetch_segment_changes(name, since, fetch_options = { cache_control_headers: @config.logger.error('Factory Instantiation: You passed a browser type api_key, ' \ 'please grab an api key from the Split console that is of type sdk') @config.valid_mode = false + elsif response.status == 404 + @config.logger.warn("Segment '#{name}' not found (404). The segment may have been removed from the Split environment.") + nil else @telemetry_runtime_producer.record_sync_error(Telemetry::Domain::Constants::SEGMENT_SYNC, response.status) diff --git a/spec/engine/api/segments_spec.rb b/spec/engine/api/segments_spec.rb index 755a2890..69fc50b0 100644 --- a/spec/engine/api/segments_spec.rb +++ b/spec/engine/api/segments_spec.rb @@ -88,14 +88,24 @@ expect(log.string).to include ':added=>["max", "dan"]' end - it 'throws exception if request to fetch segments from API returns unexpected status code' do + it 'returns nil and logs warning when segment is not found (404)' do stub_request(:get, 'https://sdk.split.io/api/segmentChanges/employees?since=-1') .to_return(status: 404) - expect { segments_api.send(:fetch_segment_changes, 'employees', -1) }.to raise_error( - 'Split SDK failed to connect to backend to fetch segments' - ) - expect(log.string).to include 'Unexpected status code while fetching segments' + result = segments_api.send(:fetch_segment_changes, 'employees', -1) + expect(result).to be_nil + expect(log.string).to include "Segment 'employees' not found (404)" + end + + it 'removes segment from registered set on 404 during fetch_segments_by_names' do + stub_request(:get, 'https://sdk.split.io/api/segmentChanges/employees?since=-1') + .to_return(status: 404) + + segments_repository.instance_variable_get(:@adapter) + .add_to_set('SPLITIO.segments.registered', 'employees') + + expect { segments_api.fetch_segments_by_names(['employees']) }.not_to raise_error + expect(segments_repository.used_segment_names).not_to include('employees') end it 'throws exception if request to get splits from API fails' do