Class: TIMEx::Result

Inherits:
Object
  • Object
show all
Defined in:
lib/timex/result.rb

Overview

Discriminated outcome from work executed under a deadline when errors are captured instead of raised (+on_timeout: :result+, non-raising strategies, etc.).

Instances are frozen at construction and support pattern matching via #deconstruct / #deconstruct_keys.

See Also:

Constant Summary collapse

OK =
:ok
TIMEOUT =
:timeout
ERROR =
:error

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(outcome:, value: nil, strategy: nil, elapsed_ms: nil, error: nil, deadline_ms: nil) ⇒ void

Note:

Freezes self before returning.

Parameters:

  • outcome (Symbol)

    one of OK, TIMEOUT, or ERROR

  • value (Object, nil) (defaults to: nil)

    success payload when outcome == OK

  • strategy (Symbol, nil) (defaults to: nil)

    component name when known

  • elapsed_ms (Numeric, nil) (defaults to: nil)

    elapsed time in ms when known

  • error (Exception, nil) (defaults to: nil)

    underlying exception for timeout/error paths

  • deadline_ms (Numeric, nil) (defaults to: nil)

    original budget in ms for timeout paths



28
29
30
31
32
33
34
35
36
# File 'lib/timex/result.rb', line 28

def initialize(outcome:, value: nil, strategy: nil, elapsed_ms: nil, error: nil, deadline_ms: nil) # rubocop:disable Metrics/ParameterLists
  @outcome = outcome
  @value = value
  @strategy = strategy
  @elapsed_ms = elapsed_ms
  @error = error
  @deadline_ms = deadline_ms
  freeze
end

Instance Attribute Details

#deadline_msObject (readonly)

Returns the value of attribute deadline_ms.



17
18
19
# File 'lib/timex/result.rb', line 17

def deadline_ms
  @deadline_ms
end

#elapsed_msObject (readonly)

Returns the value of attribute elapsed_ms.



17
18
19
# File 'lib/timex/result.rb', line 17

def elapsed_ms
  @elapsed_ms
end

#errorObject (readonly)

Returns the value of attribute error.



17
18
19
# File 'lib/timex/result.rb', line 17

def error
  @error
end

#outcomeObject (readonly)

Returns the value of attribute outcome.



17
18
19
# File 'lib/timex/result.rb', line 17

def outcome
  @outcome
end

#strategyObject (readonly)

Returns the value of attribute strategy.



17
18
19
# File 'lib/timex/result.rb', line 17

def strategy
  @strategy
end

#valueObject (readonly)

Returns the value of attribute value.



17
18
19
# File 'lib/timex/result.rb', line 17

def value
  @value
end

Class Method Details

.error(error, strategy: nil, elapsed_ms: nil) ⇒ Result

Returns frozen error result.

Parameters:

  • error (Exception)
  • strategy (Symbol, nil) (defaults to: nil)
  • elapsed_ms (Numeric, nil) (defaults to: nil)

Returns:

  • (Result)

    frozen error result

Raises:

  • (ArgumentError)

    when error is not an Exception



75
76
77
78
79
# File 'lib/timex/result.rb', line 75

def self.error(error, strategy: nil, elapsed_ms: nil)
  raise ArgumentError, "error must be an Exception, got #{error.class}" unless error.is_a?(Exception)

  new(outcome: ERROR, error:, strategy:, elapsed_ms:)
end

.ok(value, strategy: nil, elapsed_ms: nil) ⇒ Result

Returns frozen OK result.

Parameters:

  • value (Object)

    success value

  • strategy (Symbol, nil) (defaults to: nil)
  • elapsed_ms (Numeric, nil) (defaults to: nil)

Returns:

  • (Result)

    frozen OK result



42
43
44
# File 'lib/timex/result.rb', line 42

def self.ok(value, strategy: nil, elapsed_ms: nil)
  new(outcome: OK, value:, strategy:, elapsed_ms:)
end

.timeout(strategy:, expired: nil, elapsed_ms: nil, deadline_ms: nil) ⇒ Result

Builds a timeout result, always carrying an Expired in #error so #value! can re-raise with uniform metadata.

Parameters:

  • strategy (Symbol, nil)
  • expired (Expired, nil) (defaults to: nil)

    existing Expired (preferred)

  • elapsed_ms (Numeric, nil) (defaults to: nil)

    used with deadline_ms to synthesize Expired when expired omitted

  • deadline_ms (Numeric, nil) (defaults to: nil)

    used with elapsed_ms to synthesize Expired when expired omitted

Returns:

  • (Result)

    frozen timeout result



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/timex/result.rb', line 54

def self.timeout(strategy:, expired: nil, elapsed_ms: nil, deadline_ms: nil)
  expired ||= Expired.new(
    "deadline expired",
    strategy:,
    deadline_ms:,
    elapsed_ms:
  )
  new(
    outcome: TIMEOUT,
    strategy:,
    error: expired,
    elapsed_ms: elapsed_ms || expired.elapsed_ms,
    deadline_ms: deadline_ms || expired.deadline_ms
  )
end

Instance Method Details

#deconstructArray(Symbol, Object, Exception, nil)

Returns array shape for pattern matching.

Returns:

  • (Array(Symbol, Object, Exception, nil))

    array shape for pattern matching



119
120
121
# File 'lib/timex/result.rb', line 119

def deconstruct
  [@outcome, @value, @error]
end

#deconstruct_keys(_keys) ⇒ Hash{Symbol => Object}

Returns hash shape for pattern matching.

Parameters:

  • _keys (Array<Symbol>, nil)

    ignored; present for Ruby pattern-matching protocol

Returns:

  • (Hash{Symbol => Object})

    hash shape for pattern matching



125
126
127
128
129
130
131
132
133
134
# File 'lib/timex/result.rb', line 125

def deconstruct_keys(_keys)
  {
    outcome: @outcome,
    value: @value,
    error: @error,
    strategy: @strategy,
    elapsed_ms: @elapsed_ms,
    deadline_ms: @deadline_ms
  }
end

#error?Boolean

Returns:

  • (Boolean)


88
# File 'lib/timex/result.rb', line 88

def error?   = @outcome == ERROR

#ok?Boolean

Returns:

  • (Boolean)


82
# File 'lib/timex/result.rb', line 82

def ok?      = @outcome == OK

#timeout?Boolean

Returns:

  • (Boolean)


85
# File 'lib/timex/result.rb', line 85

def timeout? = @outcome == TIMEOUT

#value!Object Also known as: unwrap

Returns the success value or raises the captured exception.

Returns:

  • (Object)

    @value when #ok?

Raises:



95
96
97
98
99
100
# File 'lib/timex/result.rb', line 95

def value!
  return @value if ok?
  raise @error if @error

  raise Error, "result has no value"
end

#value_or(default = nil) {|result| ... } ⇒ Object Also known as: unwrap_or

Returns @value when the result is OK, otherwise the default (or the block's return value if a block is given).

Parameters:

  • default (Object) (defaults to: nil)

    fallback when not OK and no block given

Yield Parameters:

  • result (Result)

    self for inspecting error, strategy, etc.

Returns:

  • (Object)


109
110
111
112
113
114
115
# File 'lib/timex/result.rb', line 109

def value_or(default = nil)
  if ok?
    @value
  else
    (block_given? ? yield(self) : default)
  end
end