Class: ActiveRecord::ConnectionAdapters::RactorConnectionHandler::Proxy::ErrorResponse
| Relationships & Source Files | |
| Inherits: | Object |
| Defined in: | activerecord/lib/active_record/connection_adapters/ractor_connection_handler/proxy.rb |
Overview
Shareable stand-in for a main-side exception
Class Method Summary
- .new(error) ⇒ ErrorResponse constructor
Instance Method Summary
- #exception(connection_pool: nil)
- #remote_error
-
#attach_cause(error, cause)
private
raiseis the only way to set a cause. - #capture_ivars(error) private
-
#reconstructible?(error) ⇒ Boolean
private
Arbitrary exceptions may carry unshareable or hidden state.
Constructor Details
.new(error) ⇒ ErrorResponse
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/proxy.rb', line 23
def initialize(error) @error_class = error.class @message = error..to_s @backtrace = error.backtrace @cause = ErrorResponse.new(error.cause) if error.cause @ivars = capture_ivars(error) if reconstructible?(error) ActiveSupport::Ractors.make_shareable(self, copy: false) end
Instance Method Details
#attach_cause(error, cause) (private)
raise is the only way to set a cause.
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/proxy.rb', line 75
def attach_cause(error, cause) raise error, cause: cause rescue error.class error end
#capture_ivars(error) (private)
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/proxy.rb', line 63
def capture_ivars(error) error.instance_variables.each_with_object({}) do |name, ivars| next if name == :@connection_pool value = error.instance_variable_get(name) ivars[name] = value.is_a?(Proc) ? ActiveSupport::Ractors.shareable_proc(&value) : ActiveSupport::Ractors.make_shareable(value) end end
#exception(connection_pool: nil)
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/proxy.rb', line 32
def exception(connection_pool: nil) remote = remote_error error = if @ivars rebuilt = @error_class.allocate.exception(@message) @ivars.each { |name, value| rebuilt.instance_variable_set(name, value) } rebuilt.instance_variable_set(:@connection_pool, connection_pool) if rebuilt.is_a?(AdapterError) attach_cause(rebuilt, remote) else remote end error.set_backtrace(@backtrace + caller) if @backtrace error end
#reconstructible?(error) ⇒ Boolean (private)
Arbitrary exceptions may carry unshareable or hidden state. Active Record errors have known state we can copy; otherwise only stateless non-system errors are safe to rebuild.
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/proxy.rb', line 57
def reconstructible?(error) return true if error.is_a?(ActiveRecordError) error.instance_variables.empty? && !error.is_a?(SystemCallError) end
#remote_error
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/proxy.rb', line 47
def remote_error error = RemoteError.new(@error_class, @message) error.set_backtrace(@backtrace) if @backtrace @cause ? attach_cause(error, @cause.remote_error) : error end