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