class Gruf::Error
Represents a error that can be transformed into a gRPC error and have metadata attached to the trailing headers. This layer acts as an middle layer that can have metadata injection, tracing support, and other functionality not present in the gRPC core.
Constants
- MAX_METADATA_SIZE
Default limit on trailing metadata is 8KB. We need to be careful not to overflow this limit, or the response message will never be sent. Instead, resource_exhausted will be thrown.
- METADATA_SIZE_EXCEEDED_CODE
- METADATA_SIZE_EXCEEDED_MSG
- TYPES
@return [Hash<GRPC::BadStatus>] A hash mapping of gRPC BadStatus codes to error symbols
Attributes
@return [Symbol] An arbitrary application code that can be used for logical processing of the error by the client
@return [Symbol] The given internal gRPC code for the error
@return [Errors::DebugInfo] A object containing debugging information, such as a stack trace and exception name, that can be used to debug an given error response. This is sent by the server over the trailing metadata.
@return [Array] An array of field errors that can be returned by the server
@return [GRPC::BadStatus] The gRPC BadStatus error object that was generated
@return [String] The error message returned by the server
@return [Hash] The trailing metadata that was attached to the error
Public Class Methods
Initialize the error, setting default values
@param [Hash] args (Optional) An optional hash of arguments that will set fields on the error object
# File lib/gruf/error.rb, line 83 def initialize(args = {}) @field_errors = [] @metadata = {} args.each do |k, v| send("#{k}=", v) if respond_to?(k) end end
Public Instance Methods
Add a field error to this error package
@param [Symbol] field_name The field name for the error @param [Symbol] error_code The application error code for the error; e.g. :job_not_found @param [String] message The application error message for the error; e.g. “Job not found with ID 123”
# File lib/gruf/error.rb, line 98 def add_field_error(field_name, error_code, message = '') @field_errors << Errors::Field.new(field_name, error_code, message) end
Update the trailing metadata on the given gRPC call, including the error payload if configured to do so.
@param [GRPC::ActiveCall] active_call The marshalled gRPC call @return [Error] Return the error itself after updating metadata on the given gRPC call.
In the case of a metadata overflow error, we replace the current error with a new one that won't cause a low-level http2 error.
# File lib/gruf/error.rb, line 151 def attach_to_call(active_call) metadata[Gruf.error_metadata_key.to_sym] = serialize if Gruf.append_server_errors_to_trailing_metadata return self if metadata.empty? || !active_call || !active_call.respond_to?(:output_metadata) # Check if we've overflown the maximum size of output metadata. If so, # log a warning and replace the metadata with something smaller to avoid # resource exhausted errors. if metadata.inspect.size > MAX_METADATA_SIZE code = METADATA_SIZE_EXCEEDED_CODE msg = METADATA_SIZE_EXCEEDED_MSG logger.warn "#{code}: #{msg} Original error: #{to_h.inspect}" err = Gruf::Error.new(code: :internal, app_code: code, message: msg) return err.attach_to_call(active_call) end active_call.output_metadata.update(metadata) self end
Fail the current gRPC call with the given error, properly attaching it to the call and raising the appropriate gRPC BadStatus code.
@param [GRPC::ActiveCall] active_call The marshalled gRPC call @return [GRPC::BadStatus] The gRPC BadStatus code this error is mapped to
# File lib/gruf/error.rb, line 177 def fail!(active_call) raise attach_to_call(active_call).grpc_error end
Return the appropriately mapped GRPC::BadStatus error object for this error
@return [GRPC::BadStatus]
# File lib/gruf/error.rb, line 201 def grpc_error md = @metadata || {} @grpc_error = grpc_class.new(message, **md) end
Return true if there are any present field errors
@return [Boolean] True if the service has any field errors
# File lib/gruf/error.rb, line 107 def has_field_errors? @field_errors.any? end
Ensure all metadata values are strings as HTTP/2 requires string values for transport
@param [Hash] metadata The existing metadata hash @return [Hash] The newly set metadata
# File lib/gruf/error.rb, line 128 def metadata=(metadata) @metadata = metadata.transform_values(&:to_s) end
Serialize the error for transport
@return [String] The serialized error message
# File lib/gruf/error.rb, line 137 def serialize serializer = serializer_class.new(self) serializer.serialize.to_s end
Set the debugging information for the error message
@param [String] detail The detailed message generated by the exception @param [Array<String>] stack_trace An array of strings that represents the exception backtrace generated by the service
# File lib/gruf/error.rb, line 118 def set_debug_info(detail, stack_trace = []) @debug_info = Errors::DebugInfo.new(detail, stack_trace) end
Return the error represented in Hash form
@return [Hash] The error as a hash
# File lib/gruf/error.rb, line 186 def to_h { code: code, app_code: app_code, message: message, field_errors: field_errors.map(&:to_h), debug_info: debug_info.to_h } end
Private Instance Methods
Return the appropriate gRPC class for the given error code
@return [Class] The gRPC error class
# File lib/gruf/error.rb, line 226 def grpc_class TYPES[code] end
Return the error serializer being used for gruf
@return [Gruf::Serializers::Errors::Base]
# File lib/gruf/error.rb, line 213 def serializer_class if Gruf.error_serializer Gruf.error_serializer.is_a?(Class) ? Gruf.error_serializer : Gruf.error_serializer.to_s.constantize else Gruf::Serializers::Errors::Json end end