diff --git a/lib/optimizely/event/batch_event_processor.rb b/lib/optimizely/event/batch_event_processor.rb index 428c4abf..6229ad3b 100644 --- a/lib/optimizely/event/batch_event_processor.rb +++ b/lib/optimizely/event/batch_event_processor.rb @@ -182,7 +182,9 @@ def flush_queue! while retry_count < max_retries begin - @event_dispatcher.dispatch_event(log_event) + result = @event_dispatcher.dispatch_event(log_event) + raise result if result.is_a?(StandardError) + @notification_center&.send_notifications( NotificationCenter::NOTIFICATION_TYPES[:LOG_EVENT], log_event diff --git a/lib/optimizely/event_dispatcher.rb b/lib/optimizely/event_dispatcher.rb index 874a43db..015df97a 100644 --- a/lib/optimizely/event_dispatcher.rb +++ b/lib/optimizely/event_dispatcher.rb @@ -50,7 +50,9 @@ def dispatch_event(event) when 500...600 @logger.log(Logger::ERROR, error_msg) - @error_handler.handle_error(HTTPCallError.new("HTTP Server Error: #{response.code}")) + error = HTTPCallError.new("HTTP Server Error: #{response.code}") + @error_handler.handle_error(error) + error else @logger.log(Logger::DEBUG, "event successfully sent with response code #{response.code}") end diff --git a/spec/event/batch_event_processor_spec.rb b/spec/event/batch_event_processor_spec.rb index 604784d6..64b821bc 100644 --- a/spec/event/batch_event_processor_spec.rb +++ b/spec/event/batch_event_processor_spec.rb @@ -381,6 +381,44 @@ end context 'retry logic with exponential backoff' do + [500, 400].each do |status| + it "should #{status == 500 ? 'retry' : 'not retry'} HTTP #{status} with the default dispatcher" do + user_event = Optimizely::UserEventFactory.create_conversion_event(project_config, event, 'test_user', nil, nil) + log_event = Optimizely::EventFactory.create_log_event(user_event, spy_logger) + request = stub_request(:post, log_event.url).with(body: log_event.params.to_json) + .to_return(status: status).then.to_return(status: 200) + @event_processor = Optimizely::BatchEventProcessor.new(notification_center: @notification_center) + allow(@event_processor).to receive(:sleep) + @event_processor.current_batch << user_event + + @event_processor.send(:flush_queue!) + + expect(request).to have_been_requested.times(status == 500 ? 2 : 1) + expect(@event_processor.current_batch).to be_empty + expect(@notification_center).to have_received(:send_notifications).with( + Optimizely::NotificationCenter::NOTIFICATION_TYPES[:LOG_EVENT], log_event + ).once + end + end + + it 'should retry a timeout with the default dispatcher' do + user_event = Optimizely::UserEventFactory.create_conversion_event(project_config, event, 'test_user', nil, nil) + log_event = Optimizely::EventFactory.create_log_event(user_event, spy_logger) + request = stub_request(:post, log_event.url).with(body: log_event.params.to_json) + .to_timeout.then.to_return(status: 200) + @event_processor = Optimizely::BatchEventProcessor.new(notification_center: @notification_center) + allow(@event_processor).to receive(:sleep) + @event_processor.current_batch << user_event + + @event_processor.send(:flush_queue!) + + expect(request).to have_been_requested.twice + expect(@event_processor.current_batch).to be_empty + expect(@notification_center).to have_received(:send_notifications).with( + Optimizely::NotificationCenter::NOTIFICATION_TYPES[:LOG_EVENT], log_event + ).once + end + it 'should retry on dispatch errors with exponential backoff' do @event_processor = Optimizely::BatchEventProcessor.new( event_dispatcher: @event_dispatcher,