Class: Gruf::Error

Inherits:
Object
  • Object
show all
Includes:
Loggable
Defined in:
lib/gruf/error.rb

Overview

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.

Constant Summary collapse

TYPES =
{
  ok: GRPC::Ok,
  cancelled: GRPC::Cancelled,
  unknown: GRPC::Unknown,
  invalid_argument: GRPC::InvalidArgument,
  bad_request: GRPC::InvalidArgument,
  deadline_exceeded: GRPC::DeadlineExceeded,
  not_found: GRPC::NotFound,
  already_exists: GRPC::AlreadyExists,
  unauthorized: GRPC::PermissionDenied,
  permission_denied: GRPC::PermissionDenied,
  unauthenticated: GRPC::Unauthenticated,
  resource_exhausted: GRPC::ResourceExhausted,
  failed_precondition: GRPC::FailedPrecondition,
  aborted: GRPC::Aborted,
  out_of_range: GRPC::OutOfRange,
  unimplemented: GRPC::Unimplemented,
  internal: GRPC::Internal,
  unavailable: GRPC::Unavailable,
  data_loss: GRPC::DataLoss
}.freeze
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.

7.5 * 1_024
METADATA_SIZE_EXCEEDED_CODE =
'metadata_size_exceeded'
METADATA_SIZE_EXCEEDED_MSG =
'Metadata too long, risks exceeding http2 trailing metadata limit.'

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Loggable

#logger

Constructor Details

#initialize(args = {}) ⇒ Error

Initialize the error, setting default values



91
92
93
94
95
96
97
# File 'lib/gruf/error.rb', line 91

def initialize(args = {})
  @field_errors = []
   = {}
  args.each do |k, v|
    send("#{k}=", v) if respond_to?(k)
  end
end

Instance Attribute Details

#app_codeSymbol



68
69
70
# File 'lib/gruf/error.rb', line 68

def app_code
  @app_code
end

#codeSymbol



64
65
66
# File 'lib/gruf/error.rb', line 64

def code
  @code
end

#debug_infoErrors::DebugInfo



78
79
80
# File 'lib/gruf/error.rb', line 78

def debug_info
  @debug_info
end

#field_errorsArray



74
75
76
# File 'lib/gruf/error.rb', line 74

def field_errors
  @field_errors
end

#grpc_errorGRPC::BadStatus

Return the appropriately mapped GRPC::BadStatus error object for this error



209
210
211
212
# File 'lib/gruf/error.rb', line 209

def grpc_error
  md =  || {}
  @grpc_error = grpc_class.new(message, **md)
end

#messageString



71
72
73
# File 'lib/gruf/error.rb', line 71

def message
  @message
end

#metadataObject

Returns the value of attribute metadata.



84
85
86
# File 'lib/gruf/error.rb', line 84

def 
  
end

Instance Method Details

#add_field_error(field_name, error_code, message = '') ⇒ Object

Add a field error to this error package



106
107
108
# File 'lib/gruf/error.rb', line 106

def add_field_error(field_name, error_code, message = '')
  @field_errors << Errors::Field.new(field_name, error_code, message)
end

#attach_to_call(active_call) ⇒ Error

Update the trailing metadata on the given gRPC call, including the error payload if configured to do so.



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/gruf/error.rb', line 159

def attach_to_call(active_call)
  [Gruf..to_sym] = serialize if Gruf.
  return self if .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 .inspect.size > 
    code = 
    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..update()
  self
end

#fail!(active_call) ⇒ GRPC::BadStatus

Fail the current gRPC call with the given error, properly attaching it to the call and raising the appropriate gRPC BadStatus code.



185
186
187
# File 'lib/gruf/error.rb', line 185

def fail!(active_call)
  raise attach_to_call(active_call).grpc_error
end

#has_field_errors?Boolean

Return true if there are any present field errors



115
116
117
# File 'lib/gruf/error.rb', line 115

def has_field_errors?
  @field_errors.any?
end

#serializeString

Serialize the error for transport



145
146
147
148
# File 'lib/gruf/error.rb', line 145

def serialize
  serializer = serializer_class.new(self)
  serializer.serialize.to_s
end

#set_debug_info(detail, stack_trace = []) ⇒ Object

Set the debugging information for the error message

service



126
127
128
# File 'lib/gruf/error.rb', line 126

def set_debug_info(detail, stack_trace = [])
  @debug_info = Errors::DebugInfo.new(detail, stack_trace)
end

#to_hHash

Return the error represented in Hash form



194
195
196
197
198
199
200
201
202
# File 'lib/gruf/error.rb', line 194

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