diff --git a/lib/import/otrs/requester.rb b/lib/import/otrs/requester.rb index 7c1791022..c3dbbf049 100644 --- a/lib/import/otrs/requester.rb +++ b/lib/import/otrs/requester.rb @@ -1,11 +1,16 @@ module Import module OTRS + + # @!attribute [rw] retry_sleep + # @return [Number] the sleep time between the request retries module Requester extend Import::Helper # rubocop:disable Style/ModuleFunction extend self + attr_accessor :retry_sleep + # Loads entries of the given object. # # @param object [String] the name of OTRS object @@ -68,8 +73,17 @@ module Import private def request_result(params) + tries ||= 1 response = request_json(params) response['Result'] + rescue + # stop after 3 tries + raise if tries == 3 + + # try again + tries += 1 + sleep tries * (retry_sleep || 15) + retry end def request_json(params) diff --git a/spec/lib/import/otrs/requester_spec.rb b/spec/lib/import/otrs/requester_spec.rb index f7b77cc4a..630a58a43 100644 --- a/spec/lib/import/otrs/requester_spec.rb +++ b/spec/lib/import/otrs/requester_spec.rb @@ -1,39 +1,54 @@ require 'rails_helper' RSpec.describe Import::OTRS::Requester do - it 'responds to load' do - expect(described_class).to respond_to('load') + + context '.list' do + it 'responds to list' do + expect(described_class).to respond_to(:list) + end end - it 'responds to list' do - expect(described_class).to respond_to('list') - end + context '.load' do - it 'responds to connection_test' do - expect(described_class).to respond_to('connection_test') - end - - context 'caching request results' do - - let(:response) { - response = double() - response_body = double() - expect(response_body).to receive(:to_s).at_least(:once).and_return('{"Result": {}}') - expect(response).to receive('success?').at_least(:once).and_return(true) - expect(response).to receive('body').at_least(:once).and_return(response_body) - response - } - - it 'is active if no args are given' do - expect(UserAgent).to receive(:post).and_return(response) - described_class.load('Ticket') - described_class.load('Ticket') + it 'responds to load' do + expect(described_class).to respond_to(:load) end - it 'is not active if args are given' do - expect(UserAgent).to receive(:post).twice.and_return(response) - described_class.load('Ticket', offset: 10) - described_class.load('Ticket', offset: 20) + context 'caching request results' do + + let(:response) { + response = double() + response_body = double() + expect(response_body).to receive(:to_s).at_least(:once).and_return('{"Result": {}}') + expect(response).to receive('success?').at_least(:once).and_return(true) + expect(response).to receive('body').at_least(:once).and_return(response_body) + response + } + + it 'is active if no args are given' do + expect(UserAgent).to receive(:post).and_return(response) + described_class.load('Ticket') + described_class.load('Ticket') + end + + it 'is not active if args are given' do + expect(UserAgent).to receive(:post).twice.and_return(response) + described_class.load('Ticket', offset: 10) + described_class.load('Ticket', offset: 20) + end end end + + context '.connection_test' do + it 'responds to connection_test' do + expect(described_class).to respond_to(:connection_test) + end + end + + it 'retries request 3 times on errors' do + expect(UserAgent).to receive(:post).and_raise(Errno::ECONNRESET).exactly(3).times + # disable sleep time to speed up tests + described_class.retry_sleep = 0 + expect { described_class.list }.to raise_error(Errno::ECONNRESET) + end end