Skip to content

Commit

Permalink
Refactor tests and WorkflowErrorsReporter class
Browse files Browse the repository at this point in the history
  • Loading branch information
SaravShah committed Jan 12, 2018
1 parent c8cee3c commit 391ffe0
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 57 deletions.
6 changes: 2 additions & 4 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ Lint/RescueWithoutErrorClass:
Metrics/AbcSize:
Exclude:
- 'app/services/preserved_object_handler.rb' # methods still readable; shameless green
- 'app/services/preserved_object_handler_results.rb' # method still readable
- 'lib/audit/moab_to_catalog.rb' # .xxx_for_all_storage_roots is decidedly readable

Metrics/BlockLength:
Expand All @@ -74,6 +75,7 @@ Metrics/BlockNesting:
Metrics/ClassLength:
Exclude:
- 'app/services/preserved_object_handler.rb'
- 'app/services/preserved_object_handler_results.rb'

Metrics/CyclomaticComplexity:
Exclude:
Expand All @@ -89,15 +91,11 @@ Metrics/LineLength:
- 'app/services/workflow_errors_reporter.rb' # line 7 is 143
- 'spec/lib/audit/moab_to_catalog_spec.rb' # 1 line 126
- 'spec/models/status_spec.rb' # Line length of 132 for better readability
- spec/services/preserved_object_handler_spec.rb
- 'spec/services/preserved_object_handler_check_exist_spec.rb' # 17 lines, but who's counting, officer?
- 'spec/services/preserved_object_handler_confirm_version_spec.rb'
- 'spec/services/preserved_object_handler_create_spec.rb'
- 'spec/services/preserved_object_handler_update_version_spec.rb'
- 'spec/services/shared_examples_preserved_object_handler.rb'
- 'spec/models/status_spec.rb' # Line length of 132 for better readability
- 'spec/services/preserved_object_handler_check_exist_spec.rb' # 17 lines, but who's counting, officer?
- 'spec/services/workflow_errors_reporter_spec.rb' # lines for body and error_msg kept long for readability

Metrics/MethodLength:
Max: 25
Expand Down
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ gem 'newrelic_rpm'
gem 'honeybadger'
# Use faraday for ReST calls
gem 'faraday'
# Use retries for handling exceptions and retries
# For more robust handling of network glitches
gem 'retries'

# Stanford gems
Expand Down
34 changes: 30 additions & 4 deletions app/services/preserved_object_handler_results.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ class PreservedObjectHandlerResults
PC_PO_VERSION_MISMATCH => "PreservedCopy online moab version %{pc_version} does not match PreservedObject current_version %{po_version}"
}.freeze

WORKFLOW_REPORT_CODES = [
ARG_VERSION_LESS_THAN_DB_OBJECT,
DB_UPDATE_FAILED,
OBJECT_ALREADY_EXISTS,
OBJECT_DOES_NOT_EXIST,
UNEXPECTED_VERSION,
PC_PO_VERSION_MISMATCH
].freeze

DB_UPDATED_CODES = [
UPDATED_DB_OBJECT,
UPDATED_DB_OBJECT_TIMESTAMP_ONLY,
Expand Down Expand Up @@ -86,19 +95,36 @@ def result_hash(code, msg_args=nil)
{ code => result_code_msg(code, msg_args) }
end

# result_array = [result1, result2]
# result1 = {response_code => msg}
# result2 = {response_code => msg}
# output results to Rails.logger and send errors to WorkflowErrorsReporter
# @return result_array
def report_results
WorkflowErrorsReporter.update_workflow(druid, result_array)
candidate_workflow_results = []
result_array.each do |r|
severity = self.class.logger_severity_level(r.keys.first)
msg = r.values.first
Rails.logger.log(severity, msg)
if r.key?(PreservedObjectHandlerResults::INVALID_MOAB)
WorkflowErrorsReporter.update_workflow(druid, 'moab-valid', r.values.first)
elsif WORKFLOW_REPORT_CODES.include?(r.keys.first)
candidate_workflow_results << r
end
end
stack_trace = caller(1..1).first[/.+?(?=:in)/]
report_errors_to_workflows(candidate_workflow_results, stack_trace)
result_array
end

def report_errors_to_workflows(candidate_workflow_results, stack_trace)
value_array = []
candidate_workflow_results.each do |x|
x.each_value do |val|
value_array << val
end
end
value_array << stack_trace
WorkflowErrorsReporter.update_workflow(druid, 'preservation-audit-process', value_array.join(" || "))
end

private

def result_code_msg(code, addl=nil)
Expand Down
48 changes: 26 additions & 22 deletions app/services/workflow_errors_reporter.rb
Original file line number Diff line number Diff line change
@@ -1,45 +1,49 @@
require 'faraday'
require 'retries'
# This class will send a put ReST call to the preservationWF via faraday. This also parses
# out a shorter error message, that only includes the moab validation error.
# send errors to preservationWF workflow for an object via ReST calls.
class WorkflowErrorsReporter

def self.update_workflow(druid, error_message)
error_message.select { |error| request(druid, 'moab-valid', moab_error(error)) if error.key?(PreservedObjectHandlerResults::INVALID_MOAB) }
def self.update_workflow(druid, process_name, error_message)
response = http_workflow_request(druid, process_name, error_message)

# had to add this if response becuase test for making sure if Setting.workflow_service_url
# was empty returned the correct Rails.logger.warn

if response
if response.status == 204
Rails.logger.debug("put request went through")
else
# didn't add a status == 400 because either way it is getting handled in the
# rescue, if i add the ==400 then there is double logging.
Rails.logger.warn("put request did not go through")
end
end
rescue Faraday::Error, StandardError => e
Rails.logger.warn(e)
end

def self.request(druid, process_name, error_message)
private_class_method def self.http_workflow_request(druid, process_name, error_message)
return unless conn
handler = proc do |exception, attempt_number, total_delay|
Rails.logger.warn("Handler saw a #{exception.class}; retry attempt #{attempt_number}; #{total_delay} seconds have passed.")
Rails.logger.debug("Handler saw a #{exception.class}; retry attempt #{attempt_number}; #{total_delay} seconds have passed.")
end
with_retries(max_tries: 3, handler: handler, rescue: workflow_service_exceptions_to_catch) do
@connection.put do |request|
with_retries(max_tries: 3, handler: handler, rescue: Faraday::Error) do
conn.put do |request|
request.headers['content-type'] = "application/xml"
request.url "/workflow/dor/objects/druid:#{druid}/workflows/preservationWF/#{process_name}"
request.body = "<process name='#{process_name}' status='error' errorMessage='#{error_message}'/>"
request.body = "<process name='#{process_name} status='error' errorMessage='#{error_message}'/>"
end
end
rescue *workflow_service_exceptions_to_catch => e
raise Faraday::Error, e
end

private_class_method def self.conn
if Settings.workflow_services.url.present?
@connection ||= Faraday.new(url: Settings.workflow_services.url) do |c|
if Settings.workflow_services_url.present?
@@connection ||= Faraday.new(url: Settings.workflow_services_url) do |c|
c.use Faraday::Response::RaiseError
c.use Faraday::Adapter::NetHttp
end
else
Rails.logger.warn('no workflow hookup - assume you are in test or dev environment')
end
@connection
end
private_class_method def self.workflow_service_exceptions_to_catch
[Faraday::Error]
end

private_class_method def self.moab_error(error)
/^.*\)(.*)$/.match(error[PreservedObjectHandlerResults::INVALID_MOAB]).captures.first
end

end
3 changes: 1 addition & 2 deletions config/settings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,4 @@ preservation_policies:
provlog:
enable: false

workflow_services:
url: ''
workflow_services_url: ''
2 changes: 1 addition & 1 deletion config/settings/development.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ moab:
# name: '/location/on/disk' # e.g.
fixture_sr1: 'spec/fixtures/storage_root01'
fixture_sr2: 'spec/fixtures/storage_root02'
workflow_services_url: 'https://sul-lyberservices-test.stanford.edu/workflow/'
58 changes: 35 additions & 23 deletions spec/services/workflow_errors_reporter_spec.rb
Original file line number Diff line number Diff line change
@@ -1,42 +1,54 @@
require 'rails_helper'

RSpec.describe WorkflowErrorsReporter do
describe '.update_workflow(druid, error_message)' do
let(:body) { "<process name='moab-valid' status='error' errorMessage=' Invalid moab, validation errors: [\"Should contain only sequential version directories. Current directories: [\\\"v0001\\\", \\\"v0002\\\", \\\"v0009\\\"]\"]'/>" }
let(:error_msg) do
[{ 10 => "PreservedObjectHandler(jj925bx9565, 9, 6570668, <Endpoint:...>) PreservedObject db object does not exist" },
{ 13 => "PreservedObjectHandler(jj925bx9565, 9, 6570668, <Endpoint:...>) Invalid moab, validation errors: [\"Should contain only sequential version directories. Current directories: [\\\"v0001\\\", \\\"v0002\\\", \\\"v0009\\\"]\"]" }]
end
let(:put) { 'https://sul-lyberservices-test.stanford.edu/workflow/dor/objects/druid:jj925bx9565/workflows/preservationWF/moab-valid' }
let(:headers) { { 'Content-Type' => 'application/xml' } }
let(:result_array) do
{ 13 => "Invalid moab, validation error...ential version directories." }
end
let(:body) { "<process name='moab-valid status='error' errorMessage='{13=>\"Invalid moab, validation error...ential version directories.\"}'/>" }

describe '.update_workflow with 204' do
before do
Settings.workflow_services.url = 'https://sul-lyberservices-test.stanford.edu/workflow/'
stub_request(:put, 'https://sul-lyberservices-test.stanford.edu/workflow/dor/objects/druid:jj925bx9565/workflows/preservationWF/moab-valid')
.with(body: body,
headers: { 'Content-Type' => 'application/xml' })
.to_return(status: 204, body: "", headers: {})
Settings.workflow_services_url = 'https://sul-lyberservices-test.stanford.edu/workflow/'
stub_request(:put, put)
.with(body: body,
headers: headers)
.to_return(status: 204, body: "", headers: {})
end
it 'updates preservationWF with invalid moab errors' do
expect(described_class.update_workflow('jj925bx9565', error_msg)).to eq [error_msg[1]]

it 'returns a 204 response status' do
expect(Rails.logger).to receive(:debug).with("put request went through")
described_class.update_workflow('jj925bx9565', 'moab-valid', result_array)
end
end
describe '.request' do
it 'rescues for Faraday::Error' do
allow(described_class).to receive(:request).and_raise(Faraday::Error)
expect { described_class.request('jj925bx9565', 'moab-valid', 'Foo() error') }.to raise_error(Faraday::Error)

describe '.update_workflow with 400' do
before do
Settings.workflow_services_url = 'https://sul-lyberservices-test.stanford.edu/workflow/'
stub_request(:put, put)
.with(body: body,
headers: headers)
.to_return(status: 400, body: "", headers: {})
end

it 'returns a 400 response status' do
expect(Rails.logger).to receive(:warn).with(Faraday::ClientError)
described_class.update_workflow('jj925bx9565', 'moab-valid', result_array)
end
end

describe '.update_workflow with invalid workflow_services.url' do
before do
stub_request(:put, "https://sul-lyberservices-test.stanford.edu/workflow/dor/objects/druid:jj925bx9565/workflows/preservationWF/moab-valid")
.with(body: "<process name='moab-valid' status='error' errorMessage=' Invalid Moab'/>",
headers: { 'Content-Type' => 'application/xml' })
.to_return(status: 200, body: "", headers: {})
stub_request(:put, put)
.with(body: body,
headers: headers)
.to_return(status: 400, body: "", headers: {})
end
it 'returns Rails warning' do
Settings.workflow_services.url = ''
Settings.workflow_services_url = ''
expect(Rails.logger).to receive(:warn).with('no workflow hookup - assume you are in test or dev environment')
described_class.update_workflow('jj925bx9565', [{ 13 => "Foo() Invalid Moab" }])
described_class.update_workflow('jj925bx9565', 'moab-valid', result_array)
end
end
end

0 comments on commit 391ffe0

Please sign in to comment.