stoplight 5.6.0 → 5.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/UPGRADING.md +303 -0
- data/lib/generators/stoplight/install/install_generator.rb +6 -1
- data/lib/stoplight/admin/dependencies.rb +1 -1
- data/lib/stoplight/admin/helpers.rb +26 -5
- data/lib/stoplight/admin/lights_repository/light.rb +22 -6
- data/lib/stoplight/admin/lights_repository.rb +20 -16
- data/lib/stoplight/admin/views/_card.erb +8 -5
- data/lib/stoplight/admin.rb +2 -1
- data/lib/stoplight/color.rb +9 -0
- data/lib/stoplight/common/deprecations.rb +11 -0
- data/lib/stoplight/data_store.rb +28 -0
- data/lib/stoplight/domain/compatibility_result.rb +7 -7
- data/lib/stoplight/domain/config.rb +38 -35
- data/lib/stoplight/domain/error_tracking_policy.rb +27 -0
- data/lib/stoplight/domain/failure.rb +1 -1
- data/lib/stoplight/domain/light/configuration_builder_interface.rb +122 -16
- data/lib/stoplight/domain/light.rb +44 -64
- data/lib/stoplight/domain/light_info.rb +7 -0
- data/lib/stoplight/domain/metrics_snapshot.rb +58 -0
- data/lib/stoplight/domain/state_snapshot.rb +29 -23
- data/lib/stoplight/domain/storage/recovery_lock_token.rb +15 -0
- data/lib/stoplight/domain/strategies/green_run_strategy.rb +18 -26
- data/lib/stoplight/domain/strategies/red_run_strategy.rb +9 -12
- data/lib/stoplight/domain/strategies/yellow_run_strategy.rb +74 -58
- data/lib/stoplight/domain/tracker/recovery_probe.rb +27 -43
- data/lib/stoplight/domain/tracker/request.rb +24 -39
- data/lib/stoplight/domain/traffic_control/consecutive_errors.rb +8 -11
- data/lib/stoplight/domain/traffic_control/error_rate.rb +19 -15
- data/lib/stoplight/domain/traffic_recovery/consecutive_successes.rb +8 -18
- data/lib/stoplight/domain/traffic_recovery.rb +3 -5
- data/lib/stoplight/error.rb +46 -0
- data/lib/stoplight/infrastructure/fail_safe/data_store.rb +152 -0
- data/lib/stoplight/infrastructure/fail_safe/storage/metrics.rb +65 -0
- data/lib/stoplight/infrastructure/fail_safe/storage/recovery_lock.rb +69 -0
- data/lib/stoplight/infrastructure/fail_safe/storage/recovery_lock_token.rb +19 -0
- data/lib/stoplight/infrastructure/fail_safe/storage/state.rb +62 -0
- data/lib/stoplight/infrastructure/{data_store/memory → memory/data_store}/metrics.rb +2 -2
- data/lib/stoplight/infrastructure/memory/data_store/recovery_lock_store.rb +52 -0
- data/lib/stoplight/infrastructure/memory/data_store/recovery_lock_token.rb +17 -0
- data/lib/stoplight/infrastructure/{data_store/memory → memory/data_store}/sliding_window.rb +21 -26
- data/lib/stoplight/infrastructure/{data_store/memory → memory/data_store}/state.rb +3 -3
- data/lib/stoplight/infrastructure/{data_store/memory.rb → memory/data_store.rb} +90 -57
- data/lib/stoplight/infrastructure/memory/storage/recovery_lock.rb +35 -0
- data/lib/stoplight/infrastructure/memory/storage/recovery_metrics.rb +16 -0
- data/lib/stoplight/infrastructure/memory/storage/state.rb +155 -0
- data/lib/stoplight/infrastructure/memory/storage/unbounded_metrics.rb +103 -0
- data/lib/stoplight/infrastructure/memory/storage/window_metrics.rb +101 -0
- data/lib/stoplight/infrastructure/notifier/fail_safe.rb +50 -0
- data/lib/stoplight/infrastructure/notifier/generic.rb +4 -14
- data/lib/stoplight/infrastructure/notifier/io.rb +1 -2
- data/lib/stoplight/infrastructure/notifier/logger.rb +1 -2
- data/lib/stoplight/infrastructure/redis/data_store/lua_scripts/record_recovery_probe_failure.lua +27 -0
- data/lib/stoplight/infrastructure/redis/data_store/lua_scripts/record_recovery_probe_success.lua +23 -0
- data/lib/stoplight/infrastructure/redis/data_store/lua_scripts/release_lock.lua +6 -0
- data/lib/stoplight/infrastructure/redis/data_store/recovery_lock_store.rb +60 -0
- data/lib/stoplight/infrastructure/redis/data_store/recovery_lock_token.rb +28 -0
- data/lib/stoplight/infrastructure/redis/data_store/scripting.rb +73 -0
- data/lib/stoplight/infrastructure/{data_store/redis.rb → redis/data_store.rb} +173 -210
- data/lib/stoplight/infrastructure/redis/storage/key_space.rb +51 -0
- data/lib/stoplight/infrastructure/redis/storage/metrics.rb +40 -0
- data/lib/stoplight/infrastructure/redis/storage/recovery_lock/release_lock.lua +6 -0
- data/lib/stoplight/infrastructure/redis/storage/recovery_lock.rb +64 -0
- data/lib/stoplight/infrastructure/redis/storage/recovery_metrics.rb +20 -0
- data/lib/stoplight/infrastructure/redis/storage/scripting.rb +18 -0
- data/lib/stoplight/infrastructure/redis/storage/state/transition_to_green.lua +10 -0
- data/lib/stoplight/infrastructure/redis/storage/state/transition_to_red.lua +10 -0
- data/lib/stoplight/infrastructure/redis/storage/state/transition_to_yellow.lua +9 -0
- data/lib/stoplight/infrastructure/redis/storage/state.rb +141 -0
- data/lib/stoplight/infrastructure/redis/storage/unbounded_metrics/record_failure.lua +28 -0
- data/lib/stoplight/infrastructure/redis/storage/unbounded_metrics/record_success.lua +26 -0
- data/lib/stoplight/infrastructure/redis/storage/unbounded_metrics.rb +123 -0
- data/lib/stoplight/infrastructure/redis/storage/window_metrics/metrics_snapshot.lua +26 -0
- data/lib/stoplight/infrastructure/redis/storage/window_metrics/record_failure.lua +36 -0
- data/lib/stoplight/infrastructure/redis/storage/window_metrics/record_success.lua +35 -0
- data/lib/stoplight/infrastructure/redis/storage/window_metrics.rb +174 -0
- data/lib/stoplight/infrastructure/storage/compatibility_metrics.rb +41 -0
- data/lib/stoplight/infrastructure/storage/compatibility_recovery_lock.rb +33 -0
- data/lib/stoplight/infrastructure/storage/compatibility_recovery_metrics.rb +47 -0
- data/lib/stoplight/infrastructure/storage/compatibility_state.rb +44 -0
- data/lib/stoplight/infrastructure/system_clock.rb +16 -0
- data/lib/stoplight/notifier.rb +11 -0
- data/lib/stoplight/state.rb +9 -0
- data/lib/stoplight/types.rb +29 -0
- data/lib/stoplight/undefined.rb +16 -0
- data/lib/stoplight/version.rb +1 -1
- data/lib/stoplight/wiring/config_compatibility_validator.rb +54 -0
- data/lib/stoplight/wiring/configuration_dsl.rb +101 -0
- data/lib/stoplight/wiring/data_store_backend.rb +26 -0
- data/lib/stoplight/wiring/default.rb +2 -2
- data/lib/stoplight/wiring/default_config.rb +21 -0
- data/lib/stoplight/wiring/default_configuration.rb +70 -53
- data/lib/stoplight/wiring/light_builder.rb +198 -0
- data/lib/stoplight/wiring/light_factory/traffic_control_dsl.rb +26 -0
- data/lib/stoplight/wiring/light_factory/traffic_recovery_dsl.rb +21 -0
- data/lib/stoplight/wiring/light_factory.rb +74 -135
- data/lib/stoplight/wiring/memory/backend.rb +57 -0
- data/lib/stoplight/wiring/notifier_factory.rb +26 -0
- data/lib/stoplight/wiring/redis/backend.rb +116 -0
- data/lib/stoplight/wiring/storage_set.rb +12 -0
- data/lib/stoplight/wiring/storage_set_builder.rb +51 -0
- data/lib/stoplight/wiring/system/light_builder.rb +47 -0
- data/lib/stoplight/wiring/system/light_factory.rb +64 -0
- data/lib/stoplight/wiring/system.rb +129 -0
- data/lib/stoplight.rb +209 -23
- data/sig/_private/generators/stoplight/install/install_generator.rbs +22 -0
- data/sig/_private/stoplight/common/deprecations.rbs +9 -0
- data/sig/_private/stoplight/data_store.rbs +6 -0
- data/sig/_private/stoplight/domain/compatibility_result.rbs +18 -0
- data/sig/_private/stoplight/domain/config.rbs +65 -0
- data/sig/_private/stoplight/domain/error_tracking_policy.rbs +14 -0
- data/sig/_private/stoplight/domain/failure.rbs +16 -0
- data/sig/_private/stoplight/domain/light.rbs +25 -0
- data/sig/_private/stoplight/domain/light_info.rbs +19 -0
- data/sig/_private/stoplight/domain/metrics_snapshot.rbs +38 -0
- data/sig/_private/stoplight/domain/ports/clock.rbs +18 -0
- data/sig/_private/stoplight/domain/ports/data_store.rbs +76 -0
- data/{lib/stoplight/domain/light_factory.rb → sig/_private/stoplight/domain/ports/light_factory.rbs} +33 -28
- data/sig/_private/stoplight/domain/ports/metrics_store.rbs +29 -0
- data/sig/_private/stoplight/domain/ports/recovery_lock_store.rbs +52 -0
- data/sig/_private/stoplight/domain/ports/recovery_lock_token.rbs +6 -0
- data/sig/_private/stoplight/domain/ports/run_strategy.rbs +14 -0
- data/sig/_private/stoplight/domain/ports/state_store.rbs +79 -0
- data/sig/_private/stoplight/domain/ports/traffic_control.rbs +41 -0
- data/sig/_private/stoplight/domain/ports/traffic_recovery.rbs +47 -0
- data/sig/_private/stoplight/domain/state_snapshot.rbs +32 -0
- data/sig/_private/stoplight/domain/storage/recovery_lock_token.rbs +11 -0
- data/sig/_private/stoplight/domain/strategies/green_run_strategy.rbs +17 -0
- data/sig/_private/stoplight/domain/strategies/red_run_strategy.rbs +17 -0
- data/sig/_private/stoplight/domain/strategies/yellow_run_strategy.rbs +42 -0
- data/sig/_private/stoplight/domain/tracker/base.rbs +8 -0
- data/sig/_private/stoplight/domain/tracker/recovery_probe.rbs +25 -0
- data/sig/_private/stoplight/domain/tracker/request.rbs +26 -0
- data/sig/_private/stoplight/domain/traffic_control/consecutive_errors.rbs +9 -0
- data/sig/_private/stoplight/domain/traffic_control/error_rate.rbs +13 -0
- data/sig/_private/stoplight/domain/traffic_recovery/consecutive_successes.rbs +9 -0
- data/sig/_private/stoplight/domain/traffic_recovery.rbs +9 -0
- data/sig/_private/stoplight/infrastructure/fail_safe/data_store.rbs +26 -0
- data/sig/_private/stoplight/infrastructure/fail_safe/storage/metrics.rbs +25 -0
- data/sig/_private/stoplight/infrastructure/fail_safe/storage/recovery_lock.rbs +29 -0
- data/sig/_private/stoplight/infrastructure/fail_safe/storage/recovery_lock_token.rbs +19 -0
- data/sig/_private/stoplight/infrastructure/fail_safe/storage/state.rbs +25 -0
- data/sig/_private/stoplight/infrastructure/memory/data_store/metrics.rbs +25 -0
- data/sig/_private/stoplight/infrastructure/memory/data_store/recovery_lock_store.rbs +19 -0
- data/sig/_private/stoplight/infrastructure/memory/data_store/recovery_lock_token.rbs +17 -0
- data/sig/_private/stoplight/infrastructure/memory/data_store/sliding_window.rbs +27 -0
- data/sig/_private/stoplight/infrastructure/memory/data_store/state.rbs +17 -0
- data/sig/_private/stoplight/infrastructure/memory/data_store.rbs +30 -0
- data/sig/_private/stoplight/infrastructure/memory/storage/recovery_lock.rbs +15 -0
- data/sig/_private/stoplight/infrastructure/memory/storage/recovery_metrics.rbs +10 -0
- data/sig/_private/stoplight/infrastructure/memory/storage/state.rbs +28 -0
- data/sig/_private/stoplight/infrastructure/memory/storage/unbounded_metrics.rbs +25 -0
- data/sig/_private/stoplight/infrastructure/memory/storage/window_metrics.rbs +26 -0
- data/sig/_private/stoplight/infrastructure/notifier/fail_safe.rbs +17 -0
- data/sig/_private/stoplight/infrastructure/notifier/generic.rbs +18 -0
- data/sig/_private/stoplight/infrastructure/notifier/io.rbs +14 -0
- data/sig/_private/stoplight/infrastructure/notifier/logger.rbs +14 -0
- data/sig/_private/stoplight/infrastructure/redis/data_store/recovery_lock_store.rbs +24 -0
- data/sig/_private/stoplight/infrastructure/redis/data_store/recovery_lock_token.rbs +21 -0
- data/sig/_private/stoplight/infrastructure/redis/data_store/scripting.rbs +34 -0
- data/sig/_private/stoplight/infrastructure/redis/data_store.rbs +67 -0
- data/sig/_private/stoplight/infrastructure/redis/storage/key_space.rbs +19 -0
- data/sig/_private/stoplight/infrastructure/redis/storage/metrics.rbs +17 -0
- data/sig/_private/stoplight/infrastructure/redis/storage/recovery_lock.rbs +26 -0
- data/sig/_private/stoplight/infrastructure/redis/storage/recovery_metrics.rbs +10 -0
- data/sig/_private/stoplight/infrastructure/redis/storage/scripting.rbs +13 -0
- data/sig/_private/stoplight/infrastructure/redis/storage/state.rbs +32 -0
- data/sig/_private/stoplight/infrastructure/redis/storage/unbounded_metrics.rbs +21 -0
- data/sig/_private/stoplight/infrastructure/redis/storage/window_metrics.rbs +34 -0
- data/sig/_private/stoplight/infrastructure/storage/compatibility_metrics.rbs +17 -0
- data/sig/_private/stoplight/infrastructure/storage/compatibility_recovery_lock.rbs +13 -0
- data/sig/_private/stoplight/infrastructure/storage/compatibility_recovery_metrics.rbs +14 -0
- data/sig/_private/stoplight/infrastructure/storage/compatibility_state.rbs +14 -0
- data/sig/_private/stoplight/infrastructure/system_clock.rbs +7 -0
- data/sig/_private/stoplight/system/light_builder.rbs +23 -0
- data/sig/_private/stoplight/system/light_factory.rbs +17 -0
- data/sig/_private/stoplight/types.rbs +6 -0
- data/sig/_private/stoplight/wiring/config_compatibility_validator.rbs +19 -0
- data/sig/_private/stoplight/wiring/configuration_dsl.rbs +43 -0
- data/sig/_private/stoplight/wiring/data_store_backend.rbs +11 -0
- data/sig/_private/stoplight/wiring/default.rbs +26 -0
- data/sig/_private/stoplight/wiring/default_config.rbs +7 -0
- data/sig/_private/stoplight/wiring/default_configuration.rbs +29 -0
- data/sig/_private/stoplight/wiring/light_builder.rbs +48 -0
- data/sig/_private/stoplight/wiring/light_factory/traffic_control_dsl.rbs +7 -0
- data/sig/_private/stoplight/wiring/light_factory/traffic_recovery_dsl.rbs +7 -0
- data/sig/_private/stoplight/wiring/light_factory.rbs +16 -0
- data/sig/_private/stoplight/wiring/memory/backend.rbs +26 -0
- data/sig/_private/stoplight/wiring/notifier_factory.rbs +10 -0
- data/sig/_private/stoplight/wiring/redis/backend.rbs +38 -0
- data/sig/_private/stoplight/wiring/storage_set.rbs +38 -0
- data/sig/_private/stoplight/wiring/storage_set_builder.rbs +15 -0
- data/sig/_private/stoplight/wiring/system.rbs +15 -0
- data/sig/_private/stoplight.rbs +48 -0
- data/sig/stoplight/color.rbs +7 -0
- data/sig/stoplight/data_store.rbs +19 -0
- data/sig/stoplight/error.rbs +20 -0
- data/sig/stoplight/notifier.rbs +11 -0
- data/sig/stoplight/ports/configuration.rbs +19 -0
- data/sig/stoplight/ports/exception_matcher.rbs +8 -0
- data/sig/stoplight/ports/light.rbs +12 -0
- data/sig/stoplight/ports/light_info.rbs +5 -0
- data/sig/stoplight/ports/state_transition_notifier.rbs +15 -0
- data/sig/stoplight/ports/system.rbs +21 -0
- data/sig/stoplight/state.rbs +7 -0
- data/sig/stoplight/undefined.rbs +9 -0
- data/sig/stoplight/version.rbs +3 -0
- data/sig/stoplight.rbs +66 -0
- metadata +199 -36
- data/lib/stoplight/domain/color.rb +0 -11
- data/lib/stoplight/domain/data_store.rb +0 -130
- data/lib/stoplight/domain/error.rb +0 -42
- data/lib/stoplight/domain/metrics.rb +0 -85
- data/lib/stoplight/domain/state.rb +0 -11
- data/lib/stoplight/domain/state_transition_notifier.rb +0 -25
- data/lib/stoplight/domain/strategies/run_strategy.rb +0 -27
- data/lib/stoplight/domain/tracker/base.rb +0 -41
- data/lib/stoplight/domain/traffic_control/base.rb +0 -74
- data/lib/stoplight/domain/traffic_recovery/base.rb +0 -80
- data/lib/stoplight/infrastructure/data_store/redis/lua.rb +0 -25
- data/lib/stoplight/infrastructure/dependency_injection/container.rb +0 -249
- data/lib/stoplight/infrastructure/dependency_injection/unresolved_dependency_error.rb +0 -13
- data/lib/stoplight/wiring/container.rb +0 -80
- data/lib/stoplight/wiring/default_factory_builder.rb +0 -25
- data/lib/stoplight/wiring/fail_safe_data_store.rb +0 -147
- data/lib/stoplight/wiring/fail_safe_notifier.rb +0 -79
- data/lib/stoplight/wiring/light/default_config.rb +0 -18
- data/lib/stoplight/wiring/light/system_config.rb +0 -11
- data/lib/stoplight/wiring/public_api.rb +0 -28
- data/lib/stoplight/wiring/system_container.rb +0 -9
- data/lib/stoplight/wiring/system_light_factory.rb +0 -17
- /data/lib/stoplight/infrastructure/{data_store/redis → redis/data_store/lua_scripts}/get_metrics.lua +0 -0
- /data/lib/stoplight/infrastructure/{data_store/redis → redis/data_store/lua_scripts}/record_failure.lua +0 -0
- /data/lib/stoplight/infrastructure/{data_store/redis → redis/data_store/lua_scripts}/record_success.lua +0 -0
- /data/lib/stoplight/infrastructure/{data_store/redis → redis/data_store/lua_scripts}/transition_to_green.lua +0 -0
- /data/lib/stoplight/infrastructure/{data_store/redis → redis/data_store/lua_scripts}/transition_to_red.lua +0 -0
- /data/lib/stoplight/infrastructure/{data_store/redis → redis/data_store/lua_scripts}/transition_to_yellow.lua +0 -0
data/lib/stoplight.rb
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "concurrent/map"
|
|
3
4
|
require "zeitwerk"
|
|
4
5
|
|
|
6
|
+
# steep:ignore:start
|
|
5
7
|
loader = Zeitwerk::Loader.for_gem
|
|
6
8
|
loader.inflector.inflect("io" => "IO")
|
|
7
9
|
loader.do_not_eager_load(
|
|
@@ -12,19 +14,21 @@ loader.do_not_eager_load(
|
|
|
12
14
|
loader.ignore("#{__dir__}/generators")
|
|
13
15
|
loader.ignore("#{__dir__}/stoplight/rspec.rb", "#{__dir__}/stoplight/rspec")
|
|
14
16
|
loader.setup
|
|
17
|
+
# steep:ignore:end
|
|
15
18
|
|
|
16
19
|
module Stoplight # rubocop:disable Style/Documentation
|
|
17
|
-
|
|
20
|
+
T = Types
|
|
18
21
|
|
|
19
22
|
CONFIG_MUTEX = Mutex.new
|
|
20
23
|
private_constant :CONFIG_MUTEX
|
|
24
|
+
@systems = Concurrent::Map.new
|
|
21
25
|
|
|
22
26
|
class << self
|
|
23
27
|
# Configures the Stoplight library.
|
|
24
28
|
#
|
|
25
29
|
# This method allows you to set up the library's configuration using a block.
|
|
26
30
|
# It raises an error if called more than once.
|
|
27
|
-
#
|
|
31
|
+
# @param trust_me_im_an_engineer [Boolean]
|
|
28
32
|
# @yield [config] Provides a configuration object to the block.
|
|
29
33
|
# @yieldparam config [Stoplight::Wiring::DefaultConfiguration] The configuration object.
|
|
30
34
|
# @return [void]
|
|
@@ -52,32 +56,175 @@ module Stoplight # rubocop:disable Style/Documentation
|
|
|
52
56
|
#
|
|
53
57
|
def configure(trust_me_im_an_engineer: false)
|
|
54
58
|
warn_if_reconfiguring(trust_me_im_an_engineer) do
|
|
55
|
-
|
|
56
|
-
yield
|
|
59
|
+
configuration = Wiring::DefaultConfiguration.new
|
|
60
|
+
yield configuration if block_given?
|
|
57
61
|
|
|
58
|
-
|
|
59
|
-
@
|
|
62
|
+
default_config = configuration.to_config!
|
|
63
|
+
@default_config = default_config
|
|
64
|
+
@default_light_factory = Wiring::LightFactory.new(config: default_config)
|
|
60
65
|
end
|
|
61
66
|
end
|
|
62
67
|
|
|
63
|
-
# Creates a Light for internal use.
|
|
64
|
-
#
|
|
65
|
-
# @param name [String]
|
|
66
|
-
# @param settings [Hash]
|
|
67
|
-
# @return [Stoplight::Light]
|
|
68
68
|
# @api private
|
|
69
|
-
def system_light(
|
|
70
|
-
|
|
69
|
+
def system_light(
|
|
70
|
+
name,
|
|
71
|
+
cool_off_time: T.undefined,
|
|
72
|
+
threshold: T.undefined,
|
|
73
|
+
recovery_threshold: T.undefined,
|
|
74
|
+
window_size: T.undefined,
|
|
75
|
+
tracked_errors: T.undefined,
|
|
76
|
+
skipped_errors: T.undefined,
|
|
77
|
+
data_store: T.undefined,
|
|
78
|
+
error_notifier: T.undefined,
|
|
79
|
+
notifiers: T.undefined,
|
|
80
|
+
traffic_control: T.undefined,
|
|
81
|
+
traffic_recovery: T.undefined
|
|
82
|
+
)
|
|
83
|
+
Wiring::LightFactory.new(config: Wiring::DefaultConfig).build_with(
|
|
84
|
+
name: "__stoplight__#{name}",
|
|
85
|
+
cool_off_time:,
|
|
86
|
+
threshold:,
|
|
87
|
+
recovery_threshold:,
|
|
88
|
+
window_size:,
|
|
89
|
+
tracked_errors:,
|
|
90
|
+
skipped_errors:,
|
|
91
|
+
data_store:,
|
|
92
|
+
error_notifier:,
|
|
93
|
+
notifiers:,
|
|
94
|
+
traffic_control:,
|
|
95
|
+
traffic_recovery:
|
|
96
|
+
)
|
|
71
97
|
end
|
|
72
98
|
|
|
73
99
|
# Create a Light with the user default configuration.
|
|
74
100
|
#
|
|
75
|
-
# @param name [String]
|
|
76
|
-
# @param settings [Hash]
|
|
77
101
|
# @return [Stoplight::Light]
|
|
78
102
|
# @api private
|
|
79
|
-
def light(
|
|
80
|
-
|
|
103
|
+
def light(
|
|
104
|
+
name,
|
|
105
|
+
cool_off_time: T.undefined,
|
|
106
|
+
threshold: T.undefined,
|
|
107
|
+
recovery_threshold: T.undefined,
|
|
108
|
+
window_size: T.undefined,
|
|
109
|
+
tracked_errors: T.undefined,
|
|
110
|
+
skipped_errors: T.undefined,
|
|
111
|
+
data_store: T.undefined,
|
|
112
|
+
error_notifier: T.undefined,
|
|
113
|
+
notifiers: T.undefined,
|
|
114
|
+
traffic_control: T.undefined,
|
|
115
|
+
traffic_recovery: T.undefined
|
|
116
|
+
)
|
|
117
|
+
__stoplight__default_light_factory.build_with(
|
|
118
|
+
name:,
|
|
119
|
+
cool_off_time:,
|
|
120
|
+
threshold:,
|
|
121
|
+
recovery_threshold:,
|
|
122
|
+
window_size:,
|
|
123
|
+
tracked_errors:,
|
|
124
|
+
skipped_errors:,
|
|
125
|
+
data_store:,
|
|
126
|
+
error_notifier:,
|
|
127
|
+
notifiers:,
|
|
128
|
+
traffic_control:,
|
|
129
|
+
traffic_recovery:
|
|
130
|
+
)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# Creates a new named system with the given configuration.
|
|
134
|
+
#
|
|
135
|
+
# Systems are composition roots that own infrastructure (data store, notifiers)
|
|
136
|
+
# and enforce configuration consistency for all lights created within them.
|
|
137
|
+
#
|
|
138
|
+
# @param name [String] Unique identifier for the system
|
|
139
|
+
# @param settings [Hash] Configuration options that override global defaults.
|
|
140
|
+
# @see Stoplight() documentation
|
|
141
|
+
#
|
|
142
|
+
# @return [Stoplight::Wiring::System] A new system instance.
|
|
143
|
+
#
|
|
144
|
+
# @raise [ArgumentError] If a system with the given name already exists.
|
|
145
|
+
#
|
|
146
|
+
# @note Systems are not cached for reuse. Assign the returned system to a constant
|
|
147
|
+
# for repeated access. Calling this method twice with the same name raises an error.
|
|
148
|
+
#
|
|
149
|
+
# @example Creating a system for payment services
|
|
150
|
+
# Payments = Stoplight.__stoplight__system(:payments, threshold: 3, cool_off_time: 30)
|
|
151
|
+
# Payments.light("stripe").run { process_payment }
|
|
152
|
+
#
|
|
153
|
+
# @example Isolated system with dedicated data store
|
|
154
|
+
# Analytics = Stoplight.__stoplight__system(:analytics, data_store: analytics_redis)
|
|
155
|
+
#
|
|
156
|
+
# @api private
|
|
157
|
+
def __stoplight__system(
|
|
158
|
+
name,
|
|
159
|
+
cool_off_time: T.undefined,
|
|
160
|
+
threshold: T.undefined,
|
|
161
|
+
recovery_threshold: T.undefined,
|
|
162
|
+
window_size: T.undefined,
|
|
163
|
+
tracked_errors: T.undefined,
|
|
164
|
+
skipped_errors: T.undefined,
|
|
165
|
+
data_store: T.undefined,
|
|
166
|
+
error_notifier: T.undefined,
|
|
167
|
+
notifiers: T.undefined,
|
|
168
|
+
traffic_control: T.undefined,
|
|
169
|
+
traffic_recovery: T.undefined
|
|
170
|
+
)
|
|
171
|
+
ensure_configured
|
|
172
|
+
|
|
173
|
+
systems.compute(name.to_s) do |existing_system|
|
|
174
|
+
if existing_system
|
|
175
|
+
raise ArgumentError, "system `#{name}` is already in use"
|
|
176
|
+
else
|
|
177
|
+
Wiring::System.new(
|
|
178
|
+
config: Wiring::ConfigurationDsl.new(
|
|
179
|
+
name: name.to_s,
|
|
180
|
+
cool_off_time:,
|
|
181
|
+
threshold:,
|
|
182
|
+
recovery_threshold:,
|
|
183
|
+
window_size:,
|
|
184
|
+
tracked_errors:,
|
|
185
|
+
skipped_errors:,
|
|
186
|
+
traffic_control:,
|
|
187
|
+
traffic_recovery:,
|
|
188
|
+
data_store:,
|
|
189
|
+
error_notifier:,
|
|
190
|
+
notifiers:
|
|
191
|
+
).configure!(default_config)
|
|
192
|
+
)
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
private attr_reader :systems
|
|
198
|
+
private def default_config = T.must(@default_config)
|
|
199
|
+
|
|
200
|
+
# Resets Stoplight to an unconfigured state.
|
|
201
|
+
#
|
|
202
|
+
# Clears all registered systems, default configuration, and the default light factory.
|
|
203
|
+
# After calling this method, the next call to +Stoplight()+ or +configure+ will
|
|
204
|
+
# initialize fresh state.
|
|
205
|
+
#
|
|
206
|
+
# @return [void]
|
|
207
|
+
#
|
|
208
|
+
# @note This method is intended for test suite setup/teardown. Do not use in production
|
|
209
|
+
# code, as it orphans any existing light or system references, leading to split-brain
|
|
210
|
+
# scenarios where different lights with the same name use different data stores.
|
|
211
|
+
#
|
|
212
|
+
# @note This method does not clean up state in external data stores (e.g., Redis keys).
|
|
213
|
+
# It only resets in-process configuration.
|
|
214
|
+
#
|
|
215
|
+
# @example RSpec test setup
|
|
216
|
+
# RSpec.configure do |config|
|
|
217
|
+
# config.before do
|
|
218
|
+
# Stoplight.__stoplight__reset!
|
|
219
|
+
# end
|
|
220
|
+
# end
|
|
221
|
+
#
|
|
222
|
+
# @api private
|
|
223
|
+
def __stoplight__reset!
|
|
224
|
+
@systems = Concurrent::Map.new
|
|
225
|
+
@default_config = nil
|
|
226
|
+
@default_light_factory = nil
|
|
227
|
+
@configured = nil
|
|
81
228
|
end
|
|
82
229
|
|
|
83
230
|
# Retrieves the current default dependencies.
|
|
@@ -86,12 +233,12 @@ module Stoplight # rubocop:disable Style/Documentation
|
|
|
86
233
|
# @api private
|
|
87
234
|
def __stoplight__default_light_factory
|
|
88
235
|
ensure_configured
|
|
89
|
-
@default_light_factory
|
|
236
|
+
T.must(@default_light_factory)
|
|
90
237
|
end
|
|
91
238
|
|
|
92
239
|
def __stoplight__default_configuration
|
|
93
240
|
ensure_configured
|
|
94
|
-
@
|
|
241
|
+
T.must(@default_config)
|
|
95
242
|
end
|
|
96
243
|
|
|
97
244
|
# @api private
|
|
@@ -115,13 +262,12 @@ module Stoplight # rubocop:disable Style/Documentation
|
|
|
115
262
|
end
|
|
116
263
|
end
|
|
117
264
|
|
|
118
|
-
# Creates a new Stoplight circuit
|
|
265
|
+
# Creates a new Stoplight circuit brNeaker with the given name and settings.
|
|
119
266
|
#
|
|
120
267
|
# @param name [String] The name of the circuit breaker.
|
|
121
268
|
# @param settings [Hash] Optional settings to configure the circuit breaker.
|
|
122
269
|
# @option settings [Numeric] :cool_off_time The time to wait before resetting the circuit breaker.
|
|
123
270
|
# @option settings [Stoplight::DataStore::Base] :data_store The data store to use for storing state.
|
|
124
|
-
# @option settings [Proc] :error_notifier A proc to handle error notifications.
|
|
125
271
|
# @option settings [Array<Stoplight::Notifier::Base>] :notifiers A list of notifiers to use.
|
|
126
272
|
# @option settings [Numeric] :threshold The failure threshold to trip the circuit breaker.
|
|
127
273
|
# @option settings [Numeric] :window_size The size of the rolling window for failure tracking.
|
|
@@ -160,6 +306,46 @@ end
|
|
|
160
306
|
# # When 66.6% error rate reached withing a sliding 5 minute window, the circuit breaker will trip.
|
|
161
307
|
# light = Stoplight("Payment API", traffic_control: :error_rate, threshold: 0.666, window_size: 300)
|
|
162
308
|
#
|
|
163
|
-
def Stoplight(
|
|
164
|
-
|
|
309
|
+
def Stoplight(
|
|
310
|
+
name,
|
|
311
|
+
cool_off_time: Stoplight::T.undefined,
|
|
312
|
+
threshold: Stoplight::T.undefined,
|
|
313
|
+
recovery_threshold: Stoplight::T.undefined,
|
|
314
|
+
window_size: Stoplight::T.undefined,
|
|
315
|
+
tracked_errors: Stoplight::T.undefined,
|
|
316
|
+
skipped_errors: Stoplight::T.undefined,
|
|
317
|
+
data_store: Stoplight::T.undefined,
|
|
318
|
+
error_notifier: Stoplight::T.undefined,
|
|
319
|
+
notifiers: Stoplight::T.undefined,
|
|
320
|
+
traffic_control: Stoplight::T.undefined,
|
|
321
|
+
traffic_recovery: Stoplight::T.undefined
|
|
322
|
+
) # rubocop:disable Naming/MethodName
|
|
323
|
+
Stoplight::Common::Deprecations.deprecate(<<~MSG) if error_notifier != Stoplight::T.undefined
|
|
324
|
+
Passing "error_notifier" to Stoplight('#{name}') is deprecated and will be removed in v6.0.0.
|
|
325
|
+
|
|
326
|
+
IMPORTANT: The `error_notifier` is NOT called for exceptions in your protected code.
|
|
327
|
+
It only reports internal Stoplight failures (e.g., Redis connection errors).
|
|
328
|
+
|
|
329
|
+
To fix: Move `error_notifier` to global configuration:
|
|
330
|
+
|
|
331
|
+
Stoplight.configure do |config|
|
|
332
|
+
config.error_notifier = ->(error) { Logger.warn(error) }
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
See: https://github.com/bolshakov/stoplight#error-notifiers
|
|
336
|
+
MSG
|
|
337
|
+
Stoplight.light(
|
|
338
|
+
name,
|
|
339
|
+
cool_off_time:,
|
|
340
|
+
threshold:,
|
|
341
|
+
recovery_threshold:,
|
|
342
|
+
window_size:,
|
|
343
|
+
tracked_errors:,
|
|
344
|
+
skipped_errors:,
|
|
345
|
+
data_store:,
|
|
346
|
+
error_notifier:,
|
|
347
|
+
notifiers:,
|
|
348
|
+
traffic_control:,
|
|
349
|
+
traffic_recovery:
|
|
350
|
+
)
|
|
165
351
|
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Stoplight
|
|
2
|
+
module Generators
|
|
3
|
+
class InstallGenerator < ::Rails::Generators::Base
|
|
4
|
+
ROUTES_PATH: String
|
|
5
|
+
STOPLIGHT_CONFIG_TEMPLATE: String
|
|
6
|
+
INITIALIZERS_PATH: String
|
|
7
|
+
AFTER_INSTALL_NOTIFICATION: String
|
|
8
|
+
STOPLIGHT_ADMIN_ROUTE: String
|
|
9
|
+
STOPLIGHT_AUTH: String
|
|
10
|
+
|
|
11
|
+
def options: -> Hash[Symbol, untyped]
|
|
12
|
+
def generate_redis_gem: -> void
|
|
13
|
+
def generate_sinatra_deps: -> void
|
|
14
|
+
def generate_initializer: -> void
|
|
15
|
+
def generate_admin_panel: -> void
|
|
16
|
+
def redis_configuration_notification: -> void
|
|
17
|
+
|
|
18
|
+
def copy_file: (String, String) -> void
|
|
19
|
+
def inject_into_file: (String path, String what, ?after: String) -> void
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Stoplight
|
|
4
|
+
module Domain
|
|
5
|
+
class CompatibilityResult
|
|
6
|
+
def self.compatible: -> CompatibilityResult
|
|
7
|
+
def self.incompatible: (*String) -> CompatibilityResult
|
|
8
|
+
|
|
9
|
+
attr_reader errors: Array[String]
|
|
10
|
+
|
|
11
|
+
def initialize: (?errors: Array[String]) -> void
|
|
12
|
+
|
|
13
|
+
def compatible?: -> bool
|
|
14
|
+
def incompatible?: -> bool
|
|
15
|
+
def error_messages: -> String?
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
module Stoplight
|
|
2
|
+
module Domain
|
|
3
|
+
class Config < Data
|
|
4
|
+
attr_reader threshold: percentage | Integer
|
|
5
|
+
attr_reader window_size: duration?
|
|
6
|
+
attr_reader tracked_errors: Array[_ExceptionMatcher]
|
|
7
|
+
attr_reader skipped_errors: Array[_ExceptionMatcher]
|
|
8
|
+
attr_reader name: String
|
|
9
|
+
attr_reader cool_off_time: duration
|
|
10
|
+
attr_reader recovery_threshold: Integer
|
|
11
|
+
attr_reader traffic_control: _TrafficControl
|
|
12
|
+
attr_reader traffic_recovery: _TrafficRecovery
|
|
13
|
+
attr_reader error_notifier: error_notifier
|
|
14
|
+
attr_reader notifiers: Array[state_transition_notifier]
|
|
15
|
+
attr_reader data_store: data_store
|
|
16
|
+
|
|
17
|
+
def self.new: (
|
|
18
|
+
name: String,
|
|
19
|
+
cool_off_time: duration,
|
|
20
|
+
threshold: percentage | Integer,
|
|
21
|
+
recovery_threshold: Integer,
|
|
22
|
+
window_size: duration?,
|
|
23
|
+
tracked_errors: Array[_ExceptionMatcher],
|
|
24
|
+
skipped_errors: Array[_ExceptionMatcher],
|
|
25
|
+
traffic_control: _TrafficControl,
|
|
26
|
+
traffic_recovery: _TrafficRecovery,
|
|
27
|
+
error_notifier: error_notifier,
|
|
28
|
+
notifiers: Array[state_transition_notifier],
|
|
29
|
+
data_store: data_store
|
|
30
|
+
) -> instance
|
|
31
|
+
|
|
32
|
+
def initialize: (
|
|
33
|
+
name: String,
|
|
34
|
+
cool_off_time: duration,
|
|
35
|
+
threshold: percentage | Integer,
|
|
36
|
+
recovery_threshold: Integer,
|
|
37
|
+
window_size: duration?,
|
|
38
|
+
tracked_errors: Array[_ExceptionMatcher],
|
|
39
|
+
skipped_errors: Array[_ExceptionMatcher],
|
|
40
|
+
traffic_control: _TrafficControl,
|
|
41
|
+
traffic_recovery: _TrafficRecovery,
|
|
42
|
+
error_notifier: error_notifier,
|
|
43
|
+
notifiers: Array[state_transition_notifier],
|
|
44
|
+
data_store: data_store
|
|
45
|
+
) -> void
|
|
46
|
+
|
|
47
|
+
def cool_off_time_in_milliseconds: () -> Integer
|
|
48
|
+
|
|
49
|
+
def with: (
|
|
50
|
+
?name: optional[String],
|
|
51
|
+
?cool_off_time: optional[duration],
|
|
52
|
+
?threshold: optional[percentage | Integer],
|
|
53
|
+
?recovery_threshold: optional[Integer],
|
|
54
|
+
?window_size: optional[duration?],
|
|
55
|
+
?tracked_errors: optional[Array[_ExceptionMatcher]],
|
|
56
|
+
?skipped_errors: optional[Array[_ExceptionMatcher]],
|
|
57
|
+
?traffic_control: optional[_TrafficControl],
|
|
58
|
+
?traffic_recovery: optional[_TrafficRecovery],
|
|
59
|
+
?error_notifier: optional[error_notifier],
|
|
60
|
+
?notifiers: optional[Array[state_transition_notifier]],
|
|
61
|
+
?data_store: optional[data_store],
|
|
62
|
+
) -> Config | () -> Config
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module Stoplight
|
|
2
|
+
module Domain
|
|
3
|
+
class ErrorTrackingPolicy
|
|
4
|
+
@tracked: Array[_ExceptionMatcher]
|
|
5
|
+
@skipped: Array[_ExceptionMatcher]
|
|
6
|
+
|
|
7
|
+
def initialize: (tracked: Array[_ExceptionMatcher], skipped: Array[_ExceptionMatcher]) -> void
|
|
8
|
+
def track?: (StandardError) -> bool
|
|
9
|
+
|
|
10
|
+
def skipped?: (StandardError) -> bool
|
|
11
|
+
def tracked?: (StandardError) -> bool
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Stoplight
|
|
2
|
+
module Domain
|
|
3
|
+
class Failure
|
|
4
|
+
attr_reader error_class: String
|
|
5
|
+
attr_reader error_message: String
|
|
6
|
+
attr_reader time: Time
|
|
7
|
+
alias occurred_at time
|
|
8
|
+
|
|
9
|
+
def self.from_error: (StandardError error, time: Time) -> Failure
|
|
10
|
+
|
|
11
|
+
def initialize: (String error_class, String error_message, Time time) -> void
|
|
12
|
+
|
|
13
|
+
def ==: (untyped other) -> bool
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Stoplight
|
|
2
|
+
module Domain
|
|
3
|
+
class Light
|
|
4
|
+
include _Light
|
|
5
|
+
attr_reader green_run_strategy: Strategies::GreenRunStrategy
|
|
6
|
+
attr_reader yellow_run_strategy: Strategies::YellowRunStrategy
|
|
7
|
+
attr_reader red_run_strategy: Strategies::RedRunStrategy
|
|
8
|
+
attr_reader state_store: Domain::_StateStore
|
|
9
|
+
attr_reader factory: _LightFactory
|
|
10
|
+
@name: String
|
|
11
|
+
|
|
12
|
+
def initialize: (
|
|
13
|
+
String name,
|
|
14
|
+
green_run_strategy: Strategies::GreenRunStrategy,
|
|
15
|
+
yellow_run_strategy: Strategies::YellowRunStrategy,
|
|
16
|
+
red_run_strategy: Strategies::RedRunStrategy,
|
|
17
|
+
factory: _LightFactory,
|
|
18
|
+
state_store: Domain::_StateStore
|
|
19
|
+
) -> void
|
|
20
|
+
|
|
21
|
+
private def state_strategy_factory: (color) -> _RunStrategy
|
|
22
|
+
private def state_snapshot: -> StateSnapshot
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Stoplight
|
|
2
|
+
module Domain
|
|
3
|
+
class LightInfo < Data
|
|
4
|
+
include _LightInfo
|
|
5
|
+
|
|
6
|
+
def self.new: (
|
|
7
|
+
name: String,
|
|
8
|
+
) -> instance
|
|
9
|
+
|
|
10
|
+
def initialize: (
|
|
11
|
+
name: String,
|
|
12
|
+
) -> void
|
|
13
|
+
|
|
14
|
+
def with: (
|
|
15
|
+
?name: String,
|
|
16
|
+
) -> LightInfo
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module Stoplight
|
|
2
|
+
module Domain
|
|
3
|
+
class MetricsSnapshot < Data
|
|
4
|
+
attr_reader successes: Integer?
|
|
5
|
+
attr_reader errors: Integer?
|
|
6
|
+
attr_reader consecutive_errors: Integer
|
|
7
|
+
attr_reader consecutive_successes: Integer
|
|
8
|
+
attr_reader last_error: Failure?
|
|
9
|
+
attr_reader last_success_at: Time?
|
|
10
|
+
|
|
11
|
+
def self.new: (
|
|
12
|
+
successes: Integer?,
|
|
13
|
+
errors: Integer?,
|
|
14
|
+
consecutive_errors: Integer,
|
|
15
|
+
consecutive_successes: Integer,
|
|
16
|
+
last_error: Failure?,
|
|
17
|
+
last_success_at: Time?
|
|
18
|
+
) -> instance
|
|
19
|
+
|
|
20
|
+
def initialize: (
|
|
21
|
+
successes: Integer?,
|
|
22
|
+
errors: Integer?,
|
|
23
|
+
consecutive_errors: Integer,
|
|
24
|
+
consecutive_successes: Integer,
|
|
25
|
+
last_error: Failure?,
|
|
26
|
+
last_success_at: Time?
|
|
27
|
+
) -> void
|
|
28
|
+
|
|
29
|
+
def errors!: -> Integer
|
|
30
|
+
def successes!: -> Integer
|
|
31
|
+
def error_rate: () -> Float?
|
|
32
|
+
|
|
33
|
+
def requests: () -> Integer?
|
|
34
|
+
|
|
35
|
+
def last_error_at: () -> Time?
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Stoplight
|
|
2
|
+
module Domain
|
|
3
|
+
# Wall-clock interface for time-dependent operations.
|
|
4
|
+
#
|
|
5
|
+
# Provides a centralized definition of how Stoplight obtains and
|
|
6
|
+
# interprets time. All time-dependent components should use this
|
|
7
|
+
# interface rather than calling Time methods directly, ensuring
|
|
8
|
+
# consistent time handling across the library.
|
|
9
|
+
#
|
|
10
|
+
interface _Clock
|
|
11
|
+
# Returns the current time.
|
|
12
|
+
def current_time: () -> Time
|
|
13
|
+
|
|
14
|
+
# Converts a Unix timestamp to a Time object.
|
|
15
|
+
def at: (timestamp) -> Time
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Stoplight
|
|
4
|
+
module Domain
|
|
5
|
+
interface _DataStore
|
|
6
|
+
# Retrieves the names of all lights stored in the data store.
|
|
7
|
+
#
|
|
8
|
+
# @return An array of light names.
|
|
9
|
+
def names: -> Array[String]
|
|
10
|
+
|
|
11
|
+
# Retrieves metrics for a specific light configuration.
|
|
12
|
+
def get_metrics: (Config) -> Domain::MetricsSnapshot
|
|
13
|
+
|
|
14
|
+
# Retrieves recovery metrics for a specific light configuration.
|
|
15
|
+
def get_recovery_metrics: (Config) -> Domain::MetricsSnapshot
|
|
16
|
+
|
|
17
|
+
# Retrieves State Snapshot for a specific light configuration.
|
|
18
|
+
def get_state_snapshot: (Config) -> StateSnapshot
|
|
19
|
+
|
|
20
|
+
# Clears windowed metrics (successes/errors) to prevent
|
|
21
|
+
# stale failures from before recovery from affecting post-recovery decisions.
|
|
22
|
+
# Consecutive counts are intentionally preserved as they track current streaks.
|
|
23
|
+
def clear_metrics: (Config) -> void
|
|
24
|
+
|
|
25
|
+
def clear_recovery_metrics: (Config) -> void
|
|
26
|
+
|
|
27
|
+
# Records a failure for a specific light configuration.
|
|
28
|
+
def record_failure: (Config, StandardError exception) -> void
|
|
29
|
+
|
|
30
|
+
# Records a success for a specific light configuration.
|
|
31
|
+
def record_success: (Config) -> void
|
|
32
|
+
|
|
33
|
+
# Records a failed recovery probe for a specific light configuration.
|
|
34
|
+
def record_recovery_probe_failure: (Config, StandardError exception) -> void
|
|
35
|
+
|
|
36
|
+
# Records a successful recovery probe for a specific light configuration.
|
|
37
|
+
def record_recovery_probe_success: (Config) -> void
|
|
38
|
+
|
|
39
|
+
# Sets the state of a specific light configuration.
|
|
40
|
+
def set_state: (Config, state state) -> state
|
|
41
|
+
|
|
42
|
+
# Acquires recovery lock for serializing probe execution.
|
|
43
|
+
def acquire_recovery_lock: (Config) -> _RecoveryLockToken?
|
|
44
|
+
|
|
45
|
+
# Releases previously acquired lock.
|
|
46
|
+
def release_recovery_lock: (_RecoveryLockToken lock) -> void
|
|
47
|
+
|
|
48
|
+
# Transitions the Stoplight to the specified color.
|
|
49
|
+
#
|
|
50
|
+
# This method performs a color transition operation that works across distributed instances
|
|
51
|
+
# of the light. It ensures that in a multi-instance environment, only one instance
|
|
52
|
+
# is considered the "first" to perform the transition (and therefore responsible for
|
|
53
|
+
# triggering notifications).
|
|
54
|
+
#
|
|
55
|
+
# @param config
|
|
56
|
+
# @param color The target color/state to transition to.
|
|
57
|
+
# Should be one of Stoplight::Color::GREEN, Stoplight::Color::YELLOW, or Stoplight::Color::RED.
|
|
58
|
+
#
|
|
59
|
+
# @return [Boolean] Returns +true+ if this instance was the first to perform this specific transition
|
|
60
|
+
# (and should therefore trigger notifications). Returns +false+ if another instance already
|
|
61
|
+
# initiated this transition.
|
|
62
|
+
#
|
|
63
|
+
# @note In distributed environments with multiple instances, race conditions can occur when instances
|
|
64
|
+
# attempt conflicting transitions simultaneously (e.g., one instance tries to transition from
|
|
65
|
+
# YELLOW to GREEN while another tries YELLOW to RED). The implementation handles this, but
|
|
66
|
+
# be aware that the last operation may determine the final color of the light.
|
|
67
|
+
#
|
|
68
|
+
def transition_to_color: (Config, color color) -> bool
|
|
69
|
+
|
|
70
|
+
# Deletes metadata (and related persistent state) for the given light.
|
|
71
|
+
#
|
|
72
|
+
# Implementations may choose to only remove metadata; metrics may expire via TTL.
|
|
73
|
+
def delete_light: (Config) -> void
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|