require 'active_support/core_ext/object'
require 'real_page/utils/array_fetcher'
require 'real_page/utils/snowflake_event_tracker'
module RealPage
module Validator
# Ensure there are no errors in the wrapped contents of the body.
#
# This validator works on responses that have the following format:
#
#
#
#
#
#
# false
# 1
#
#
# Critical
# 1
# something went wrong
#
#
#
#
#
#
#
#
class RequestErrors
# Ensure the concatenated error message does not exceed Snowflake error column max
# character length. The error column data type is VARCHAR(16777216)
# 16777216 bytes / 4 bytes per character = 4194304 characters
MAX_ERROR_LENGTH = 4194304
private_constant :MAX_ERROR_LENGTH
# @param response [Hash] the XML response parsed into a
# Hash
def initialize(response, request_params, request_name)
@response = response
@request_params = request_params
@request_name = request_name
end
# @raise [RealPage::Error::RequestFault] if the response has an error
# node in the contents
def validate!
return unless error?
send_request_error_to_snowflake
raise RealPage::Error::BadRequest.new(errors)
end
private
attr_reader :response, :request_params, :request_name
def contents
body = response['s:Envelope']['s:Body']
response_key = body.keys.detect { |key| key !~ /^xmlns/ }
contents_response = body[response_key]
result_key = contents_response.keys.detect { |key| key !~ /^xmlns/ }
contents_result = contents_response[result_key]
contents_result.values.first
end
def error?
contents['success'] == 'false'
end
def errors
errors = contents['errors']
errors_array = Utils::ArrayFetcher.new(hash: errors, key: 'error').fetch
errors_array.map do |error|
Struct.new(:message, :severity, :internal_message).new(
error['errormessage'],
error['severity'],
error['internalerrormessage']
)
end
end
def send_request_error_to_snowflake
Utils::SnowflakeEventTracker.track_pms_resident_event(
import_resident_id: request_params[:import_id] || '',
api_name: request_name,
resident_type: 'PRIMARY',
request_params: request_params,
phones_count: 0,
error: error_messages
)
end
def error_messages
errors.map(&:message).join(' ').slice(0, MAX_ERROR_LENGTH)
end
end
end
end