Class: Stoplight::Domain::Light

Inherits:
Object
  • Object
show all
Includes:
Common::Deprecations, ConfigurationBuilderInterface
Defined in:
lib/stoplight/domain/light.rb,
lib/stoplight/domain/light/configuration_builder_interface.rb

Defined Under Namespace

Modules: ConfigurationBuilderInterface

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from ConfigurationBuilderInterface

#with_cool_off_time, #with_data_store, #with_error_notifier, #with_notifiers, #with_skipped_errors, #with_threshold, #with_tracked_errors, #with_window_size

Methods included from Common::Deprecations

#deprecate

Constructor Details

#initialize(name, green_run_strategy:, yellow_run_strategy:, red_run_strategy:, factory:, state_store:) ⇒ Light

Returns a new instance of Light.



19
20
21
22
23
24
25
26
# File 'lib/stoplight/domain/light.rb', line 19

def initialize(name, green_run_strategy:, yellow_run_strategy:, red_run_strategy:, factory:, state_store:)
  @name = name
  @green_run_strategy = green_run_strategy
  @yellow_run_strategy = yellow_run_strategy
  @red_run_strategy = red_run_strategy
  @factory = factory
  @state_store = state_store
end

Instance Attribute Details

#factoryObject (readonly)



16
17
18
# File 'lib/stoplight/domain/light.rb', line 16

def factory
  @factory
end

#green_run_strategyObject (readonly)



13
14
15
# File 'lib/stoplight/domain/light.rb', line 13

def green_run_strategy
  @green_run_strategy
end

#nameObject (readonly)



11
12
13
# File 'lib/stoplight/domain/light.rb', line 11

def name
  @name
end

#red_run_strategyObject (readonly)



15
16
17
# File 'lib/stoplight/domain/light.rb', line 15

def red_run_strategy
  @red_run_strategy
end

#state_storeObject (readonly)



17
18
19
# File 'lib/stoplight/domain/light.rb', line 17

def state_store
  @state_store
end

#yellow_run_strategyObject (readonly)



14
15
16
# File 'lib/stoplight/domain/light.rb', line 14

def yellow_run_strategy
  @yellow_run_strategy
end

Instance Method Details

#==(other) ⇒ Object

Two lights considered equal if they have the same configuration.



102
103
104
# File 'lib/stoplight/domain/light.rb', line 102

def ==(other)
  other.is_a?(self.class) && factory == other.factory
end

#colorObject

Returns current color:

* +Stoplight::Color::GREEN+ -- circuit breaker is closed
* +Stoplight::Color::RED+ -- circuit breaker is open
* +Stoplight::Color::YELLOW+ -- circuit breaker is half-open

Examples:

light = Stoplight('example')
light.color #=> Color::GREEN


44
# File 'lib/stoplight/domain/light.rb', line 44

def color = state_snapshot.color

#lock(color) ⇒ Object

Locks light in either State::LOCKED_RED or State::LOCKED_GREEN

Examples:

light = Stoplight('example-locked')
light.lock(Stoplight::Color::RED)

Parameters:

  • color

    should be either Color::RED or Color::GREEN

Returns:

  • locked light



75
76
77
78
79
80
81
82
83
84
85
# File 'lib/stoplight/domain/light.rb', line 75

def lock(color)
  state = case color
  when Color::RED then State::LOCKED_RED
  when Color::GREEN then State::LOCKED_GREEN
  else raise Error::IncorrectColor
  end

  state_store.set_state(state)

  self
end

#run(fallback = nil, &code) ⇒ Object

Runs the given block of code with this circuit breaker

Examples:

light = Stoplight('example')
light.run { 2/0 }

Running with fallback

light = Stoplight('example')
light.run(->(error) { 0 }) { 1 / 0 } #=> 0

Parameters:

  • fallback (defaults to: nil)

    fallback code to run if the circuit breaker is open

Raises:



58
59
60
61
62
63
64
65
# File 'lib/stoplight/domain/light.rb', line 58

def run(fallback = nil, &code)
  raise ArgumentError, "nothing to run. Please, pass a block into `Light#run`" unless block_given?

  state_snapshot.then do |state_snapshot|
    strategy = state_strategy_factory(state_snapshot.color)
    strategy.execute(fallback, state_snapshot:, &code)
  end
end

#stateObject

Returns the current state of the light:

* +Stoplight::State::LOCKED_GREEN+ -- light is locked green and allows all traffic
* +Stoplight::State::LOCKED_RED+ -- light is locked red and blocks all traffic
* +Stoplight::State::UNLOCKED+ -- light is not locked and follow the configured rules


33
# File 'lib/stoplight/domain/light.rb', line 33

def state = state_snapshot.locked_state

#unlockObject

Unlocks light and sets its state to State::UNLOCKED

Examples:

light = Stoplight('example-locked')
light.lock(Stoplight::Color::RED)
light.unlock

Returns:

  • returns unlocked light (circuit breaker)



95
96
97
98
99
# File 'lib/stoplight/domain/light.rb', line 95

def unlock
  state_store.set_state(State::UNLOCKED)

  self
end

#with(**settings) ⇒ Stoplight::Light

Deprecated.

Reconfigures the light with updated settings and returns a new instance.

This method allows you to modify the configuration of a Stoplight::Light object by providing a hash of settings. The original light remains unchanged, and a new light instance with the updated configuration is returned.

steep:ignore:start

Examples:

Reconfiguring a light with custom settings

light = Stoplight('payment-api')

# Create a light for invoices with a higher threshold
invoices_light = light.with(tracked_errors: [TimeoutError], threshold: 10)

# Create a light for payments with a lower threshold
payment_light = light.with(threshold: 5)

# Run the lights with their respective configurations
invoices_light.run(->(error) { [] }) { call_invoices_api }
payment_light.run(->(error) { nil }) { call_payment_api }

Parameters:

  • settings (Hash)

    A hash of configuration options to update.

Options Hash (**settings):

  • :name (String)

    The name of the light.

  • :cool_off_time (Numeric)

    The cool-off time in seconds before the light attempts recovery.

  • :threshold (Numeric)

    The failure threshold to trigger the red state.

  • :window_size (Numeric)

    The time window in seconds for counting failures.

  • :data_store (Stoplight::DataStore::Base)

    The data store to use for persisting light state.

  • :notifiers (Array<Stoplight::Domain::AbstractStateTransitionNotifier>)

    A list of notifiers to handle light events.

  • :error_notifier (Proc)

    A custom error notifier to handle exceptions.

  • :tracked_errors (Array<StandardError>)

    A list of errors to track for failure counting.

  • :skipped_errors (Array<StandardError>)

    A list of errors to skip from failure counting.

Returns:

  • (Stoplight::Light)

    A new Stoplight::Light instance with the updated configuration.

See Also:

  • +Stoplight()+


139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/stoplight/domain/light.rb', line 139

def with(**settings)
  deprecate(<<~MSG)
    Light#with is deprecated and will be removed in v6.0.0.

    Circuit breakers should be configured once at creation, not cloned with
    modifications.

    Instead of:
      light = Stoplight('api-call', threshold: 5)
      modified = light.with(threshold: 10)

    Configure correctly from the start:
      Stoplight('api-call', threshold: 10)
  MSG
  with_without_warning(**settings)
end