Improve Zendesk import when DNS resolution fails etc.

This commit is contained in:
Ryan Lue 2018-12-14 02:59:19 +01:00
parent fb612f34d1
commit 30beecd3e7
14 changed files with 142 additions and 79 deletions

View file

@ -26,7 +26,7 @@ module Import
def attribute_config(object, name, attribute)
{
object: object,
object: object.to_s,
name: name,
display: attribute.title,
data_type: data_type(attribute),

View file

@ -40,7 +40,18 @@ class Sequencer
def resource_iteration(&block)
resource_collection.public_send(resource_iteration_method, &block)
rescue ZendeskAPI::Error::NetworkError => e
return if e.response.status.to_s == '403' && resource_klass.in?(%w[UserField OrganizationField])
case e.response.status.to_s
when '403'
return if resource_klass.in?(%w[UserField OrganizationField])
when /^5\d\d$/
raise if (fail_count ||= 1) > 10
logger.error e
logger.info "Sleeping 10 seconds after ZendeskAPI::Error::NetworkError and retry (##{fail_count}/10)."
sleep 10
(fail_count += 1) && retry
end
raise
end

View file

@ -0,0 +1,46 @@
require 'rails_helper'
RSpec.shared_examples Import::Zendesk::ObjectAttribute::Base do
let(:attribute) do
double(
title: 'Example attribute',
description: 'Example attribute description',
removable: false,
active: true,
position: 12,
visible_in_portal: true,
required_in_portal: true,
required: true,
type: 'input',
custom_field_options: [],
regexp_for_validation: '',
)
end
describe 'exception handling' do
let(:error_text) { Faker::Lorem.sentence }
it 'extends ObjectManager Attribute exception message' do
expect(ObjectManager::Attribute).to receive(:add).and_raise(RuntimeError, error_text)
expect do
described_class.new('Ticket', 'example_field', attribute)
end.to raise_error(RuntimeError, /'example_field': #{error_text}$/)
end
end
describe 'argument handling' do
it 'takes an ObjectLookup name as the first argument' do
expect(ObjectManager::Attribute)
.to receive(:add).with(hash_including(object: 'Ticket'))
described_class.new('Ticket', 'example_field', attribute)
end
it 'accepts a constant ObjectLookup name' do
expect(ObjectManager::Attribute)
.to receive(:add).with(hash_including(object: 'Ticket'))
described_class.new(Ticket, 'example_field', attribute)
end
end
end

View file

@ -1,34 +0,0 @@
require 'rails_helper'
RSpec.describe Import::Zendesk::ObjectAttribute::Base do
it 'extends ObjectManager Attribute exception text' do
attribute = double(
title: 'Example attribute',
description: 'Example attribute description',
removable: false,
active: true,
position: 12,
visible_in_portal: true,
required_in_portal: true,
required: true,
type: 'input',
)
error_text = 'some error'
expect(ObjectManager::Attribute).to receive(:add).and_raise(RuntimeError, error_text)
exception = nil
begin
described_class.new('Ticket', 'example_field', attribute)
rescue => e
exception = e
end
expect(exception).not_to be nil
expect(exception).to be_a(RuntimeError)
expect(exception.message).to include(error_text)
expect(exception.message).not_to eq(error_text)
end
end

View file

@ -1,6 +1,8 @@
require 'rails_helper'
require 'lib/import/zendesk/object_attribute/base_examples'
RSpec.describe Import::Zendesk::ObjectAttribute::Checkbox do
it_behaves_like Import::Zendesk::ObjectAttribute::Base
it 'imports boolean object attribute from checkbox object field' do

View file

@ -1,9 +1,11 @@
require 'rails_helper'
require 'lib/import/zendesk/object_attribute/base_examples'
# required due to some of rails autoloading issues
require 'import/zendesk/object_attribute/date'
RSpec.describe Import::Zendesk::ObjectAttribute::Date do
it_behaves_like Import::Zendesk::ObjectAttribute::Base
it 'imports date object attribute from date object field' do

View file

@ -1,6 +1,8 @@
require 'rails_helper'
require 'lib/import/zendesk/object_attribute/base_examples'
RSpec.describe Import::Zendesk::ObjectAttribute::Decimal do
it_behaves_like Import::Zendesk::ObjectAttribute::Base
it 'imports input object attribute from decimal object field' do

View file

@ -1,6 +1,8 @@
require 'rails_helper'
require 'lib/import/zendesk/object_attribute/base_examples'
RSpec.describe Import::Zendesk::ObjectAttribute::Dropdown do
it_behaves_like Import::Zendesk::ObjectAttribute::Base
it 'imports select object attribute from dropdown object field' do

View file

@ -1,9 +1,11 @@
require 'rails_helper'
require 'lib/import/zendesk/object_attribute/base_examples'
# required due to some of rails autoloading issues
require 'import/zendesk/object_attribute/integer'
RSpec.describe Import::Zendesk::ObjectAttribute::Integer do
it_behaves_like Import::Zendesk::ObjectAttribute::Base
it 'imports integer object attribute from integer object field' do

View file

@ -1,9 +1,11 @@
require 'rails_helper'
require 'lib/import/zendesk/object_attribute/base_examples'
# required due to some of rails autoloading issues
require 'import/zendesk/object_attribute/regexp'
RSpec.describe Import::Zendesk::ObjectAttribute::Regexp do
it_behaves_like Import::Zendesk::ObjectAttribute::Base
it 'imports input object attribute from regexp object field' do

View file

@ -1,6 +1,8 @@
require 'rails_helper'
require 'lib/import/zendesk/object_attribute/base_examples'
RSpec.describe Import::Zendesk::ObjectAttribute::Tagger do
it_behaves_like Import::Zendesk::ObjectAttribute::Base
it 'imports select object attribute from tagger object field' do

View file

@ -1,6 +1,8 @@
require 'rails_helper'
require 'lib/import/zendesk/object_attribute/base_examples'
RSpec.describe Import::Zendesk::ObjectAttribute::Text do
it_behaves_like Import::Zendesk::ObjectAttribute::Base
it 'imports input object attribute from text object field' do

View file

@ -1,6 +1,8 @@
require 'rails_helper'
require 'lib/import/zendesk/object_attribute/base_examples'
RSpec.describe Import::Zendesk::ObjectAttribute::Textarea do
it_behaves_like Import::Zendesk::ObjectAttribute::Base
it 'imports input object attribute from textarea object field' do

View file

@ -1,4 +1,5 @@
RSpec.shared_examples 'Sequencer::Unit::Import::Zendesk::SubSequence::Base' do
describe 'error handling' do
before do
allow(params[:client]).to receive(collection_name).and_return(client_collection)
allow(client_collection).to receive(:all!).and_raise(api_error)
@ -19,7 +20,11 @@ RSpec.shared_examples 'Sequencer::Unit::Import::Zendesk::SubSequence::Base' do
let(:collection_name) { described_class.name.demodulize.snakecase.to_sym }
let(:client_collection) { double('ZendeskAPI::Collection') }
let(:api_error) { ZendeskAPI::Error::NetworkError.new('Mock err msg', response_obj) }
let(:response_obj) { double('Faraday::Response') }
let(:response_obj) do
# stubbed methods required for ZendeskAPI::Error::ClientError#to_s
double('Faraday::Response', method: :get, url: 'https://example.com', status: 500)
end
# https://github.com/zammad/zammad/issues/2262
context 'for lowest-tier Zendesk subscriptions ("Essential")' do
@ -33,11 +38,14 @@ RSpec.shared_examples 'Sequencer::Unit::Import::Zendesk::SubSequence::Base' do
end
context 'when API returns other errors' do
before { allow(response_obj).to receive(:status).and_return(500) }
# https://github.com/zammad/zammad/issues/2262
it 'does not rescue the resulting exception' do
expect { process(params) }.to raise_error(api_error)
expect do
process(params) do |unit|
allow(unit).to receive(:sleep) # stub out this method to speed up retry cycle
end
end
.to raise_error(api_error)
end
end
end
@ -58,4 +66,18 @@ RSpec.shared_examples 'Sequencer::Unit::Import::Zendesk::SubSequence::Base' do
include_examples 'Zendesk import data (available on all tiers)'
end
end
context 'when DNS resolution fails (getaddrinfo: nodename nor servname provided, or not known)' do
it 'retries ten times, in 10s intervals' do
expect(client_collection)
.to receive(:all!).exactly(11).times
expect do
process(params) do |unit|
expect(unit).to receive(:sleep).with(10).exactly(10).times
end
end.to raise_error(api_error)
end
end
end
end