Browse Source

In certain cases the http requests fails (== full import stops, need to start again):

- max database connections (unprocessable html content is delivered, Zammad expected json - full import stops because of not parseable JSON)
- tmp. network issues (e. g. https issue or connection reset - full import stops because of exception)

Try failing http request 3 times (with some sleep between) to ignore OTRS and network related issue.
Thorsten Eckel 8 years ago
parent
commit
f7ba0a2865
2 changed files with 56 additions and 27 deletions
  1. 14 0
      lib/import/otrs/requester.rb
  2. 42 27
      spec/lib/import/otrs/requester_spec.rb

+ 14 - 0
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)

+ 42 - 27
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')
-  end
 
-  it 'responds to list' do
-    expect(described_class).to respond_to('list')
+  context '.list' do
+    it 'responds to list' do
+      expect(described_class).to respond_to(:list)
+    end
   end
 
-  it 'responds to connection_test' do
-    expect(described_class).to respond_to('connection_test')
-  end
+  context '.load' do
 
-  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