Exception: Axn::Failure

Inherits:
StandardError
  • Object
show all
Defined in:
lib/axn/exceptions.rb

Overview

Raised when fail! is called

Constant Summary collapse

DEFAULT_MESSAGE =
"Execution was halted"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(message = nil, standalone: false, action: nil) ⇒ Failure

Returns a new instance of Failure.



111
112
113
114
115
116
117
# File 'lib/axn/exceptions.rb', line 111

def initialize(message = nil, standalone: false, action: nil)
  @raw_reason = message
  @presentation = nil
  @standalone = standalone
  @__originating_action = action
  super(message)
end

Instance Attribute Details

#__originating_actionObject (readonly)

The action whose fail! raised this. We hold the action OBJECT (compared by identity in Result#_fail_standalone?), not its object_id — consistent with ExceptionClassification's identity keying, which deliberately avoids the freed-then-reused-object_id collision hazard. standalone: is scoped to that action: an ancestor that catches a bubbled child Failure still applies its OWN base (the child's opt-out is local). NOTE: this pins the action (and its context/inputs) for the Failure's lifetime — only relevant if a bare result.exception is retained beyond its result; results are normally short-lived.



109
110
111
# File 'lib/axn/exceptions.rb', line 109

def __originating_action
  @__originating_action
end

#raw_reasonObject (readonly)

The action whose fail! raised this. We hold the action OBJECT (compared by identity in Result#_fail_standalone?), not its object_id — consistent with ExceptionClassification's identity keying, which deliberately avoids the freed-then-reused-object_id collision hazard. standalone: is scoped to that action: an ancestor that catches a bubbled child Failure still applies its OWN base (the child's opt-out is local). NOTE: this pins the action (and its context/inputs) for the Failure's lifetime — only relevant if a bare result.exception is retained beyond its result; results are normally short-lived.



109
110
111
# File 'lib/axn/exceptions.rb', line 109

def raw_reason
  @raw_reason
end

Instance Method Details

#__present_as(string) ⇒ Object

Set the resolved, presentation-layer string shown by #message. Leaves raw_reason untouched so the framework can keep re-resolving from the raw reason without double-prefixing.

Normalized on assignment, undispatched, and read back plain — because what resolution produces is ultimately the caller's own object when they passed one (fail!(obj) with no declared base error resolves to obj itself). presence here dispatched that object's blank? from inside the settling path, which aborted _settle_exception! mid-way: the on_error callbacks and the failure classification below it never ran, and the executor's guard warned about a reporting failure instead.



127
# File 'lib/axn/exceptions.rb', line 127

def __present_as(string) = @presentation = Axn::Internal::NativeMethods.absent_value?(string) ? nil : string

#default_message?Boolean

Keyed off the RAW reason, not #message: once __present_as stamps the resolved presentation, #message no longer reflects whether the caller supplied a reason. Post-run consumers read this on a finalized, stamped result (e.g. ContextFacadeInspector#status → "[failed]" vs "[failed with…]").

The comparison runs on axn's OWN frozen String as receiver rather than on the reason, so no == the caller's object defines decides this either. String#eql? is value equality for a String (subclass included) and false for anything else, which is what a reason equal to the default message needs.

Returns:

  • (Boolean)


155
156
157
158
# File 'lib/axn/exceptions.rb', line 155

def default_message?
  reason = supplied_reason
  Axn::Internal::Identity.nil_value?(reason) || DEFAULT_MESSAGE.eql?(reason)
end

#inspectObject



160
# File 'lib/axn/exceptions.rb', line 160

def inspect = "#<#{self.class.name} '#{message}'>"

#messageObject



146
# File 'lib/axn/exceptions.rb', line 146

def message = @presentation || supplied_reason || DEFAULT_MESSAGE

#standalone?Boolean

Returns:

  • (Boolean)


129
# File 'lib/axn/exceptions.rb', line 129

def standalone? = @standalone

#supplied_reasonObject

The reason the caller handed fail!, or nil when they handed none — the undispatched form of raw_reason.presence.

fail! takes an ARBITRARY object, and this is read while a failure is already being reported: from #message, from #inspect, and from Result#_user_provided_error_message, which is what result.error and result.message resolve through. So presence meant dispatching the caller's blank?/empty? from inside axn's own reporting, where an override that raises replaces the failure being reported with its own exception — and outside StandardError it escapes the rescue meant to settle it. fail! with an object whose blank? raises took down result.error, result.message and result.inspect alike, with the failure itself intact underneath.

The spellings that mean "no reason" are decided from the value's class and its own bytes instead (NativeMethods.absent_value?), which is the same undispatched answer a declared name gets.



144
# File 'lib/axn/exceptions.rb', line 144

def supplied_reason = Axn::Internal::NativeMethods.absent_value?(@raw_reason) ? nil : @raw_reason