Module: Stoplight

Defined in:
lib/stoplight.rb,
lib/stoplight/admin.rb,
lib/stoplight/color.rb,
lib/stoplight/error.rb,
lib/stoplight/state.rb,
lib/stoplight/types.rb,
lib/stoplight/version.rb,
lib/stoplight/notifier.rb,
lib/stoplight/undefined.rb,
lib/stoplight/data_store.rb,
lib/stoplight/domain/light.rb,
lib/stoplight/admin/helpers.rb,
lib/stoplight/domain/config.rb,
lib/stoplight/wiring/system.rb,
lib/stoplight/domain/failure.rb,
lib/stoplight/wiring/default.rb,
lib/stoplight/domain/light_info.rb,
lib/stoplight/admin/actions/lock.rb,
lib/stoplight/admin/dependencies.rb,
lib/stoplight/admin/lights_stats.rb,
lib/stoplight/wiring/storage_set.rb,
lib/stoplight/admin/actions/stats.rb,
lib/stoplight/common/deprecations.rb,
lib/stoplight/admin/actions/action.rb,
lib/stoplight/admin/actions/remove.rb,
lib/stoplight/admin/actions/unlock.rb,
lib/stoplight/wiring/light_builder.rb,
lib/stoplight/wiring/light_factory.rb,
lib/stoplight/wiring/redis/backend.rb,
lib/stoplight/domain/state_snapshot.rb,
lib/stoplight/wiring/default_config.rb,
lib/stoplight/wiring/memory/backend.rb,
lib/stoplight/admin/actions/lock_red.rb,
lib/stoplight/domain/tracker/request.rb,
lib/stoplight/admin/lights_repository.rb,
lib/stoplight/domain/metrics_snapshot.rb,
lib/stoplight/domain/traffic_recovery.rb,
lib/stoplight/wiring/notifier_factory.rb,
lib/stoplight/admin/actions/lock_green.rb,
lib/stoplight/wiring/configuration_dsl.rb,
lib/stoplight/wiring/data_store_backend.rb,
lib/stoplight/infrastructure/notifier/io.rb,
lib/stoplight/wiring/storage_set_builder.rb,
lib/stoplight/domain/compatibility_result.rb,
lib/stoplight/infrastructure/system_clock.rb,
lib/stoplight/wiring/system/light_builder.rb,
lib/stoplight/wiring/system/light_factory.rb,
lib/stoplight/admin/actions/lock_all_green.rb,
lib/stoplight/domain/error_tracking_policy.rb,
lib/stoplight/wiring/default_configuration.rb,
lib/stoplight/admin/lights_repository/light.rb,
lib/stoplight/domain/tracker/recovery_probe.rb,
lib/stoplight/infrastructure/notifier/logger.rb,
lib/stoplight/infrastructure/notifier/generic.rb,
lib/stoplight/infrastructure/redis/data_store.rb,
lib/stoplight/infrastructure/memory/data_store.rb,
lib/stoplight/domain/traffic_control/error_rate.rb,
lib/stoplight/infrastructure/notifier/fail_safe.rb,
lib/stoplight/domain/storage/recovery_lock_token.rb,
lib/stoplight/domain/strategies/red_run_strategy.rb,
lib/stoplight/infrastructure/redis/storage/state.rb,
lib/stoplight/infrastructure/fail_safe/data_store.rb,
lib/stoplight/infrastructure/memory/storage/state.rb,
lib/generators/stoplight/install/install_generator.rb,
lib/stoplight/domain/strategies/green_run_strategy.rb,
lib/stoplight/infrastructure/redis/storage/metrics.rb,
lib/stoplight/domain/strategies/yellow_run_strategy.rb,
lib/stoplight/wiring/config_compatibility_validator.rb,
lib/stoplight/infrastructure/fail_safe/storage/state.rb,
lib/stoplight/infrastructure/memory/data_store/state.rb,
lib/stoplight/infrastructure/redis/storage/key_space.rb,
lib/stoplight/infrastructure/redis/storage/scripting.rb,
lib/stoplight/infrastructure/fail_safe/storage/metrics.rb,
lib/stoplight/infrastructure/memory/data_store/metrics.rb,
lib/stoplight/wiring/light_factory/traffic_control_dsl.rb,
lib/stoplight/domain/traffic_control/consecutive_errors.rb,
lib/stoplight/infrastructure/redis/data_store/scripting.rb,
lib/stoplight/wiring/light_factory/traffic_recovery_dsl.rb,
lib/stoplight/infrastructure/redis/storage/recovery_lock.rb,
lib/stoplight/infrastructure/storage/compatibility_state.rb,
lib/stoplight/infrastructure/memory/storage/recovery_lock.rb,
lib/stoplight/infrastructure/redis/storage/window_metrics.rb,
lib/stoplight/domain/light/configuration_builder_interface.rb,
lib/stoplight/infrastructure/memory/storage/window_metrics.rb,
lib/stoplight/infrastructure/storage/compatibility_metrics.rb,
lib/stoplight/domain/traffic_recovery/consecutive_successes.rb,
lib/stoplight/infrastructure/redis/storage/recovery_metrics.rb,
lib/stoplight/infrastructure/fail_safe/storage/recovery_lock.rb,
lib/stoplight/infrastructure/memory/storage/recovery_metrics.rb,
lib/stoplight/infrastructure/redis/storage/unbounded_metrics.rb,
lib/stoplight/infrastructure/memory/data_store/sliding_window.rb,
lib/stoplight/infrastructure/memory/storage/unbounded_metrics.rb,
lib/stoplight/infrastructure/storage/compatibility_recovery_lock.rb,
lib/stoplight/infrastructure/redis/data_store/recovery_lock_store.rb,
lib/stoplight/infrastructure/redis/data_store/recovery_lock_token.rb,
lib/stoplight/infrastructure/fail_safe/storage/recovery_lock_token.rb,
lib/stoplight/infrastructure/memory/data_store/recovery_lock_store.rb,
lib/stoplight/infrastructure/memory/data_store/recovery_lock_token.rb,
lib/stoplight/infrastructure/storage/compatibility_recovery_metrics.rb

Overview

steep:ignore:end

Defined Under Namespace

Modules: Color, Common, DataStore, Domain, Error, Generators, Infrastructure, Notifier, State, Types, Wiring Classes: Admin, Undefined

Constant Summary collapse

T =

rubocop:disable Style/Documentation

Types
VERSION =
Gem::Version.new("5.7.0")

Class Method Summary collapse

Class Method Details

.__stoplight__default_configurationObject



239
240
241
242
# File 'lib/stoplight.rb', line 239

def __stoplight__default_configuration
  ensure_configured
  T.must(@default_config)
end

.__stoplight__default_light_factoryStoplight::Domain::LightFactory

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Retrieves the current default dependencies.

Returns:

  • (Stoplight::Domain::LightFactory)


234
235
236
237
# File 'lib/stoplight.rb', line 234

def __stoplight__default_light_factory
  ensure_configured
  T.must(@default_light_factory)
end

.__stoplight__reset!void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Note:

This method is intended for test suite setup/teardown. Do not use in production code, as it orphans any existing light or system references, leading to split-brain scenarios where different lights with the same name use different data stores.

Note:

This method does not clean up state in external data stores (e.g., Redis keys). It only resets in-process configuration.

This method returns an undefined value.

Resets Stoplight to an unconfigured state.

Clears all registered systems, default configuration, and the default light factory. After calling this method, the next call to Stoplight() or configure will initialize fresh state.

Examples:

RSpec test setup

RSpec.configure do |config|
  config.before do
    Stoplight.__stoplight__reset!
  end
end


223
224
225
226
227
228
# File 'lib/stoplight.rb', line 223

def __stoplight__reset!
  @systems = Concurrent::Map.new
  @default_config = nil
  @default_light_factory = nil
  @configured = nil
end

.__stoplight__system(name, cool_off_time: T.undefined, threshold: T.undefined, recovery_threshold: T.undefined, window_size: T.undefined, tracked_errors: T.undefined, skipped_errors: T.undefined, data_store: T.undefined, error_notifier: T.undefined, notifiers: T.undefined, traffic_control: T.undefined, traffic_recovery: T.undefined) ⇒ Stoplight::Wiring::System

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Note:

Systems are not cached for reuse. Assign the returned system to a constant for repeated access. Calling this method twice with the same name raises an error.

Creates a new named system with the given configuration.

Systems are composition roots that own infrastructure (data store, notifiers) and enforce configuration consistency for all lights created within them.

Examples:

Creating a system for payment services

Payments = Stoplight.__stoplight__system(:payments, threshold: 3, cool_off_time: 30)
Payments.light("stripe").run { process_payment }

Isolated system with dedicated data store

Analytics = Stoplight.__stoplight__system(:analytics, data_store: analytics_redis)

Parameters:

  • name (String)

    Unique identifier for the system

  • settings (Hash)

    Configuration options that override global defaults. @see Stoplight() documentation

Returns:

Raises:

  • (ArgumentError)

    If a system with the given name already exists.



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/stoplight.rb', line 157

def __stoplight__system(
  name,
  cool_off_time: T.undefined,
  threshold: T.undefined,
  recovery_threshold: T.undefined,
  window_size: T.undefined,
  tracked_errors: T.undefined,
  skipped_errors: T.undefined,
  data_store: T.undefined,
  error_notifier: T.undefined,
  notifiers: T.undefined,
  traffic_control: T.undefined,
  traffic_recovery: T.undefined
)
  ensure_configured

  systems.compute(name.to_s) do |existing_system|
    if existing_system
      raise ArgumentError, "system `#{name}` is already in use"
    else
      Wiring::System.new(
        config: Wiring::ConfigurationDsl.new(
          name: name.to_s,
          cool_off_time:,
          threshold:,
          recovery_threshold:,
          window_size:,
          tracked_errors:,
          skipped_errors:,
          traffic_control:,
          traffic_recovery:,
          data_store:,
          error_notifier:,
          notifiers:
        ).configure!(default_config)
      )
    end
  end
end

.configure(trust_me_im_an_engineer: false) {|config| ... } ⇒ void

Note:

It is not recommended to call this method multiple times because after reconfiguring Stoplight it will not be possible to change the configuration of existing circuit breakers. If you do so, the method produces a warning:

"Stoplight reconfigured. Existing circuit breakers will not see the new configuration. New
  configuration: ...f

If you really know what you are doing, you can pass the trust_me_im_an_engineer parameter as true to suppress this warning, which could be useful in test environments.

This method returns an undefined value.

Configures the Stoplight library.

This method allows you to set up the library’s configuration using a block. It raises an error if called more than once.

Examples:

Stoplight.configure do |config|
  config.window_size = 14
  config.data_store = Stoplight::DataStore::Redis.new(redis_client)
  config.notifiers = [Stoplight::Notifier::IO.new($stdout)]
  config.cool_off_time = 120
  config.threshold = 5
  config.tracked_errors = [StandardError]
  config.skipped_errors = [RuntimeError]
end

Parameters:

  • trust_me_im_an_engineer (Boolean) (defaults to: false)

Yields:

  • (config)

    Provides a configuration object to the block.

Yield Parameters:



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

def configure(trust_me_im_an_engineer: false)
  warn_if_reconfiguring(trust_me_im_an_engineer) do
    configuration = Wiring::DefaultConfiguration.new
    yield configuration if block_given?

    default_config = configuration.to_config!
    @default_config = default_config
    @default_light_factory = Wiring::LightFactory.new(config: default_config)
  end
end

.light(name, cool_off_time: T.undefined, threshold: T.undefined, recovery_threshold: T.undefined, window_size: T.undefined, tracked_errors: T.undefined, skipped_errors: T.undefined, data_store: T.undefined, error_notifier: T.undefined, notifiers: T.undefined, traffic_control: T.undefined, traffic_recovery: T.undefined) ⇒ Stoplight::Light

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Create a Light with the user default configuration.

Returns:

  • (Stoplight::Light)


103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/stoplight.rb', line 103

def light(
  name,
  cool_off_time: T.undefined,
  threshold: T.undefined,
  recovery_threshold: T.undefined,
  window_size: T.undefined,
  tracked_errors: T.undefined,
  skipped_errors: T.undefined,
  data_store: T.undefined,
  error_notifier: T.undefined,
  notifiers: T.undefined,
  traffic_control: T.undefined,
  traffic_recovery: T.undefined
)
  __stoplight__default_light_factory.build_with(
    name:,
    cool_off_time:,
    threshold:,
    recovery_threshold:,
    window_size:,
    tracked_errors:,
    skipped_errors:,
    data_store:,
    error_notifier:,
    notifiers:,
    traffic_control:,
    traffic_recovery:
  )
end

.system_light(name, cool_off_time: T.undefined, threshold: T.undefined, recovery_threshold: T.undefined, window_size: T.undefined, tracked_errors: T.undefined, skipped_errors: T.undefined, data_store: T.undefined, error_notifier: T.undefined, notifiers: T.undefined, traffic_control: T.undefined, traffic_recovery: T.undefined) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/stoplight.rb', line 69

def system_light(
  name,
  cool_off_time: T.undefined,
  threshold: T.undefined,
  recovery_threshold: T.undefined,
  window_size: T.undefined,
  tracked_errors: T.undefined,
  skipped_errors: T.undefined,
  data_store: T.undefined,
  error_notifier: T.undefined,
  notifiers: T.undefined,
  traffic_control: T.undefined,
  traffic_recovery: T.undefined
)
  Wiring::LightFactory.new(config: Wiring::DefaultConfig).build_with(
    name: "__stoplight__#{name}",
    cool_off_time:,
    threshold:,
    recovery_threshold:,
    window_size:,
    tracked_errors:,
    skipped_errors:,
    data_store:,
    error_notifier:,
    notifiers:,
    traffic_control:,
    traffic_recovery:
  )
end