class Mongo::Error::Parser
Class for parsing the various forms that errors can come in from MongoDB command responses.
@since 2.0.0
Attributes
@return [ Integer ] code The error code parsed from the document. @since 2.6.0
@return [ String ] code_name
The error code name parsed from the document. @since 2.6.0
@return [ BSON::Document ] document The returned document.
@return [ Array<String> ] labels The set of labels associated with the error. @since 2.7.0
@return [ String ] message The error message parsed from the document.
@return [ Array<Protocol::Message> ] replies The message replies.
@api private
Public Class Methods
Create the new parser with the returned document.
In legacy mode, the code and codeName fields of the document are not examined because the status (ok: 1) is not part of the document and there is no way to distinguish successful from failed responses using the document itself, and a successful response may legitimately have {code: 123, codeName: 'foo'} as the contents of a user-inserted document. The legacy server versions do not fill out code nor codeName thus not reading them does not lose information.
@example Create the new parser.
Parser.new({ 'errmsg' => 'failed' })
@param [ BSON::Document ] document The returned document. @param [ Array<Protocol::Message> ] replies The message replies. @param [ Hash ] options The options.
@option options [ true | false ] :legacy Whether document and replies
are from a legacy (pre-3.2) response
@since 2.0.0
# File lib/mongo/error/parser.rb, line 94 def initialize(document, replies = nil, options = nil) @document = document || {} @replies = replies @options = if options options.dup else {} end.freeze parse! end
Public Instance Methods
@return [ true | false ] Whether the document includes a write
concern error. A failure may have a top level error and a write concern error or either one of the two.
@since 2.10.0 @api experimental
# File lib/mongo/error/parser.rb, line 111 def write_concern_error? !!write_concern_error_document end
@return [ Integer | nil ] The error code for the write concern error,
if a write concern error is present and has a code.
@since 2.10.0 @api experimental
# File lib/mongo/error/parser.rb, line 120 def write_concern_error_code write_concern_error_document && write_concern_error_document['code'] end
@return [ String | nil ] The code name for the write concern error,
if a write concern error is present and has a code name.
@since 2.10.0 @api experimental
# File lib/mongo/error/parser.rb, line 129 def write_concern_error_code_name write_concern_error_document && write_concern_error_document['codeName'] end
Private Instance Methods
# File lib/mongo/error/parser.rb, line 175 def append(message, error) if message.length > 1 message.concat(", #{error}") else message.concat(error) end end
# File lib/mongo/error/parser.rb, line 139 def parse! @message = "" parse_single(@message, ERR) parse_single(@message, ERROR) parse_single(@message, ERRMSG) parse_multiple(@message, 'writeErrors') if write_concern_error_document parse_single(@message, ERRMSG, write_concern_error_document) end parse_flag(@message) parse_code parse_labels parse_wtimeout end
# File lib/mongo/error/parser.rb, line 183 def parse_code if document['ok'] == 1 || @options[:legacy] @code = @code_name = nil else @code = document['code'] @code_name = document['codeName'] end # Since there is only room for one code, do not replace # codes of the top level response with write concern error codes. # In practice this should never be an issue as a write concern # can only fail after the operation succeeds on the primary. if @code.nil? && @code_name.nil? if subdoc = write_concern_error_document @code = subdoc['code'] @code_name = subdoc['codeName'] end end if @code.nil? && @code_name.nil? # If we have writeErrors, and all of their codes are the same, # use that code. Otherwise don't set the code if write_errors = document['writeErrors'] codes = write_errors.map { |e| e['code'] }.compact if codes.uniq.length == 1 @code = codes.first # code name may not be returned by the server @code_name = write_errors.map { |e| e['codeName'] }.compact.first end end end end
# File lib/mongo/error/parser.rb, line 168 def parse_flag(message) if replies && replies.first && (replies.first.respond_to?(:cursor_not_found?)) && replies.first.cursor_not_found? append(message, CURSOR_NOT_FOUND) end end
# File lib/mongo/error/parser.rb, line 216 def parse_labels @labels = document['errorLabels'] || [] end
# File lib/mongo/error/parser.rb, line 160 def parse_multiple(message, key) if errors = document[key] errors.each do |error| parse_single(message, ERRMSG, error) end end end
# File lib/mongo/error/parser.rb, line 154 def parse_single(message, key, doc = document) if error = doc[key] append(message ,"#{error} (#{doc[CODE]})") end end
# File lib/mongo/error/parser.rb, line 220 def parse_wtimeout @wtimeout = write_concern_error_document && write_concern_error_document['errInfo'] && write_concern_error_document['errInfo']['wtimeout'] end
# File lib/mongo/error/parser.rb, line 135 def write_concern_error_document document['writeConcernError'] end