stoplight 5.7.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 +20 -4
- data/lib/stoplight/admin/lights_repository/light.rb +22 -6
- data/lib/stoplight/admin/lights_repository.rb +6 -5
- data/lib/stoplight/admin/views/_card.erb +8 -5
- data/lib/stoplight/color.rb +9 -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 -39
- 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 +2 -0
- data/lib/stoplight/domain/light.rb +15 -46
- 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 +41 -51
- data/lib/stoplight/domain/tracker/recovery_probe.rb +16 -33
- data/lib/stoplight/domain/tracker/request.rb +12 -31
- 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 +6 -10
- data/lib/stoplight/domain/traffic_recovery.rb +3 -4
- data/lib/stoplight/error.rb +46 -0
- data/lib/stoplight/infrastructure/{data_store/fail_safe.rb → fail_safe/data_store.rb} +39 -51
- 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/{data_store/memory → memory/data_store}/recovery_lock_store.rb +10 -12
- data/lib/stoplight/infrastructure/{data_store/memory → memory/data_store}/recovery_lock_token.rb +3 -6
- 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} +36 -32
- 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 +9 -21
- 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/{data_store/redis → redis/data_store}/recovery_lock_store.rb +9 -22
- data/lib/stoplight/infrastructure/{data_store/redis → redis/data_store}/recovery_lock_token.rb +7 -14
- data/lib/stoplight/infrastructure/{data_store/redis → redis/data_store}/scripting.rb +22 -20
- data/lib/stoplight/infrastructure/{data_store/redis.rb → redis/data_store.rb} +48 -56
- 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 +3 -10
- data/lib/stoplight/infrastructure/storage/compatibility_recovery_lock.rb +8 -11
- data/lib/stoplight/infrastructure/storage/compatibility_recovery_metrics.rb +6 -14
- data/lib/stoplight/infrastructure/storage/compatibility_state.rb +6 -17
- 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 +1 -1
- 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 +76 -63
- data/lib/stoplight/wiring/light_factory/traffic_control_dsl.rb +3 -3
- data/lib/stoplight/wiring/light_factory/traffic_recovery_dsl.rb +4 -4
- data/lib/stoplight/wiring/light_factory.rb +78 -52
- data/lib/stoplight/wiring/memory/backend.rb +57 -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 +196 -25
- 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/{lib/stoplight/domain/tracker/base.rb → sig/_private/stoplight/domain/tracker/base.rbs} +0 -4
- 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/{lib/stoplight/wiring/data_store/memory.rb → sig/_private/stoplight/wiring/default_config.rbs} +1 -4
- 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 +175 -47
- data/lib/stoplight/domain/color.rb +0 -11
- data/lib/stoplight/domain/data_store.rb +0 -146
- data/lib/stoplight/domain/error.rb +0 -42
- data/lib/stoplight/domain/metrics.rb +0 -64
- data/lib/stoplight/domain/recovery_lock_token.rb +0 -15
- data/lib/stoplight/domain/state.rb +0 -11
- data/lib/stoplight/domain/state_transition_notifier.rb +0 -25
- data/lib/stoplight/domain/storage/metrics.rb +0 -42
- data/lib/stoplight/domain/storage/recovery_lock.rb +0 -56
- data/lib/stoplight/domain/storage/state.rb +0 -87
- data/lib/stoplight/domain/strategies/run_strategy.rb +0 -22
- data/lib/stoplight/domain/traffic_control/base.rb +0 -74
- data/lib/stoplight/domain/traffic_recovery/base.rb +0 -79
- data/lib/stoplight/wiring/data_store/base.rb +0 -11
- data/lib/stoplight/wiring/data_store/redis.rb +0 -25
- data/lib/stoplight/wiring/default_factory_builder.rb +0 -25
- data/lib/stoplight/wiring/light/default_config.rb +0 -18
- data/lib/stoplight/wiring/light/system_config.rb +0 -11
- data/lib/stoplight/wiring/light_factory/compatibility_validator.rb +0 -55
- data/lib/stoplight/wiring/light_factory/config_normalizer.rb +0 -71
- data/lib/stoplight/wiring/light_factory/configuration_pipeline.rb +0 -72
- data/lib/stoplight/wiring/public_api.rb +0 -29
- /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_recovery_probe_failure.lua +0 -0
- /data/lib/stoplight/infrastructure/{data_store/redis → redis/data_store}/lua_scripts/record_recovery_probe_success.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/release_lock.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
|
@@ -10,69 +10,50 @@ module Stoplight
|
|
|
10
10
|
# raising them or invoking a fallback if provided.
|
|
11
11
|
#
|
|
12
12
|
# @api private
|
|
13
|
-
class YellowRunStrategy
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
# @!attribute [r] recovery_lock_store
|
|
27
|
-
# @return [Stoplight::Domain::Storage::RecoveryLock]
|
|
28
|
-
protected attr_reader :recovery_lock_store
|
|
29
|
-
|
|
30
|
-
# @!attribute [r] notifiers
|
|
31
|
-
# @return [Stoplight::Domain::StateTransitionNotifier]
|
|
32
|
-
protected attr_reader :notifiers
|
|
33
|
-
|
|
34
|
-
# @!attribute [r] request_tracker
|
|
35
|
-
# @return [Stoplight::Domain::RecoveryProbeRequestRecorder]
|
|
36
|
-
protected attr_reader :request_tracker
|
|
37
|
-
|
|
38
|
-
# @!attribute [r] red_run_strategy
|
|
39
|
-
# @return [Stoplight::Domain::Strategies::RedRunStrategy]
|
|
40
|
-
protected attr_reader :red_run_strategy
|
|
41
|
-
|
|
42
|
-
# @param config [Stoplight::Domain::Config]
|
|
43
|
-
# @param notifiers [Array<Stoplight::Domain::StateTransitionNotifier>]
|
|
44
|
-
# @param request_tracker [Stoplight::Domain::Tracker::RecoveryProbe]
|
|
45
|
-
# @param red_run_strategy [Stoplight::Domain::Strategies::RedRunStrategy]
|
|
46
|
-
# @param recovery_lock_store [Stoplight::Domain::Storage::RecoveryLock]
|
|
47
|
-
def initialize(config:, notifiers:, request_tracker:, red_run_strategy:, state_store:, metrics_store:, recovery_lock_store:)
|
|
48
|
-
@config = config
|
|
13
|
+
class YellowRunStrategy
|
|
14
|
+
def initialize(
|
|
15
|
+
name:,
|
|
16
|
+
error_tracking_policy:,
|
|
17
|
+
notifiers:,
|
|
18
|
+
request_tracker:,
|
|
19
|
+
red_run_strategy:,
|
|
20
|
+
state_store:,
|
|
21
|
+
metrics_store:,
|
|
22
|
+
recovery_lock_store:,
|
|
23
|
+
config: # FIXME: needed for backward compatibility, remove when notifier accepts light config
|
|
24
|
+
)
|
|
49
25
|
@notifiers = notifiers
|
|
50
26
|
@request_tracker = request_tracker
|
|
51
27
|
@red_run_strategy = red_run_strategy
|
|
52
28
|
@state_store = state_store
|
|
53
29
|
@metrics_store = metrics_store
|
|
54
30
|
@recovery_lock_store = recovery_lock_store
|
|
31
|
+
@name = name
|
|
32
|
+
@error_tracking_policy = error_tracking_policy
|
|
33
|
+
@config = config
|
|
55
34
|
end
|
|
56
35
|
|
|
57
36
|
# Executes the provided code block when the light is in the yellow state.
|
|
58
37
|
#
|
|
59
|
-
# @param fallback
|
|
60
|
-
# @param state_snapshot
|
|
38
|
+
# @param fallback A fallback proc to execute in case of an error.
|
|
39
|
+
# @param state_snapshot
|
|
61
40
|
# @yield The code block to execute.
|
|
62
|
-
# @return
|
|
63
|
-
# @raise
|
|
41
|
+
# @return The result of the code block if successful.
|
|
42
|
+
# @raise Re-raises the error if it is not tracked or no fallback is provided.
|
|
64
43
|
def execute(fallback, state_snapshot:, &code)
|
|
65
44
|
# Everything withing this block executed exclusively:
|
|
66
45
|
# - enter recovery
|
|
67
46
|
# - execute user's code
|
|
68
47
|
# - record outcome
|
|
69
48
|
# - transition to green or red if needed
|
|
70
|
-
with_recovery_lock(fallback:, state_snapshot:) do
|
|
49
|
+
with_recovery_lock(fallback:, state_snapshot:, code:) do
|
|
71
50
|
enter_recovery(state_snapshot)
|
|
72
51
|
|
|
73
|
-
code.call
|
|
52
|
+
result = code.call
|
|
53
|
+
record_recovery_probe_success
|
|
54
|
+
result
|
|
74
55
|
rescue => error
|
|
75
|
-
if
|
|
56
|
+
if @error_tracking_policy.track?(error)
|
|
76
57
|
record_recovery_probe_failure(error)
|
|
77
58
|
|
|
78
59
|
if fallback
|
|
@@ -87,10 +68,19 @@ module Stoplight
|
|
|
87
68
|
end
|
|
88
69
|
end
|
|
89
70
|
|
|
90
|
-
|
|
71
|
+
private
|
|
72
|
+
|
|
73
|
+
attr_reader :notifiers
|
|
74
|
+
attr_reader :request_tracker
|
|
75
|
+
attr_reader :red_run_strategy
|
|
76
|
+
attr_reader :state_store
|
|
77
|
+
attr_reader :metrics_store
|
|
78
|
+
attr_reader :recovery_lock_store
|
|
79
|
+
|
|
80
|
+
def with_recovery_lock(fallback:, state_snapshot:, code:)
|
|
91
81
|
recovery_lock_token = recovery_lock_store.acquire_lock
|
|
92
82
|
if recovery_lock_token.nil?
|
|
93
|
-
return red_run_strategy.execute(fallback, state_snapshot
|
|
83
|
+
return red_run_strategy.execute(fallback, state_snapshot:, &code)
|
|
94
84
|
end
|
|
95
85
|
|
|
96
86
|
begin
|
|
@@ -100,23 +90,23 @@ module Stoplight
|
|
|
100
90
|
end
|
|
101
91
|
end
|
|
102
92
|
|
|
103
|
-
|
|
93
|
+
def record_recovery_probe_success
|
|
104
94
|
request_tracker.record_success
|
|
105
95
|
end
|
|
106
96
|
|
|
107
|
-
|
|
97
|
+
def record_recovery_probe_failure(error)
|
|
108
98
|
request_tracker.record_failure(error)
|
|
109
99
|
end
|
|
110
100
|
|
|
111
|
-
|
|
112
|
-
# @return [void]
|
|
113
|
-
private def enter_recovery(state_snapshot)
|
|
101
|
+
def enter_recovery(state_snapshot)
|
|
114
102
|
return if state_snapshot.recovery_started?
|
|
115
103
|
|
|
116
104
|
state_store.transition_to_color(Color::YELLOW)
|
|
117
105
|
metrics_store.clear
|
|
106
|
+
# FIXME: use light config instead of @_config
|
|
107
|
+
# light_info = LightInfo.new(name: @name)
|
|
118
108
|
notifiers.each do |notifier|
|
|
119
|
-
notifier.notify(config, Color::RED, Color::YELLOW, nil)
|
|
109
|
+
notifier.notify(@config, Color::RED, Color::YELLOW, nil)
|
|
120
110
|
end
|
|
121
111
|
end
|
|
122
112
|
end
|
|
@@ -3,32 +3,7 @@
|
|
|
3
3
|
module Stoplight
|
|
4
4
|
module Domain
|
|
5
5
|
module Tracker
|
|
6
|
-
class RecoveryProbe
|
|
7
|
-
# @!attribute [r] traffic_recovery
|
|
8
|
-
# @return [Stoplight::Domain::TrafficRecovery::Base]
|
|
9
|
-
protected attr_reader :traffic_recovery
|
|
10
|
-
|
|
11
|
-
# @!attribute [r] traffic_control
|
|
12
|
-
# @return [Stoplight::Domain::TrafficControl::Base]
|
|
13
|
-
protected attr_reader :notifiers
|
|
14
|
-
|
|
15
|
-
# @!attribute [r] config
|
|
16
|
-
# @return [Stoplight::Domain::Config] The configuration for the light.
|
|
17
|
-
protected attr_reader :config
|
|
18
|
-
|
|
19
|
-
# @!attribute [r] metrics_store
|
|
20
|
-
# @return [Stoplight::Domain::Storage::Metrics]
|
|
21
|
-
protected attr_reader :metrics_store
|
|
22
|
-
|
|
23
|
-
# @!attribute [r] state_store
|
|
24
|
-
# @return [Stoplight::Domain::Storage::State]
|
|
25
|
-
protected attr_reader :state_store
|
|
26
|
-
|
|
27
|
-
# @param traffic_recovery [Stoplight::Domain::TrafficRecovery::Base]
|
|
28
|
-
# @param notifiers [<Stoplight::Domain::StateTransitionNotifier>]
|
|
29
|
-
# @param config [Stoplight::Domain::Config]
|
|
30
|
-
# @param metrics_store [Stoplight::Domain::Storage::Metrics]
|
|
31
|
-
# @param state_store [Stoplight::Domain::Storage::State]
|
|
6
|
+
class RecoveryProbe
|
|
32
7
|
def initialize(traffic_recovery:, notifiers:, config:, metrics_store:, state_store:)
|
|
33
8
|
@traffic_recovery = traffic_recovery
|
|
34
9
|
@notifiers = notifiers
|
|
@@ -49,25 +24,33 @@ module Stoplight
|
|
|
49
24
|
|
|
50
25
|
recover
|
|
51
26
|
end
|
|
52
|
-
RECOVERY_TRANSITIONS = {
|
|
53
|
-
TrafficRecovery::GREEN => [Color::YELLOW, Color::GREEN],
|
|
54
|
-
TrafficRecovery::RED => [Color::YELLOW, Color::RED]
|
|
55
|
-
}.freeze
|
|
56
27
|
|
|
57
|
-
private
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
attr_reader :traffic_recovery
|
|
31
|
+
attr_reader :notifiers
|
|
32
|
+
attr_reader :config
|
|
33
|
+
attr_reader :metrics_store
|
|
34
|
+
attr_reader :state_store
|
|
35
|
+
|
|
36
|
+
def recover
|
|
58
37
|
recovery_metrics = metrics_store.metrics_snapshot
|
|
59
38
|
recovery_result = traffic_recovery.determine_color(config, recovery_metrics)
|
|
60
39
|
|
|
61
40
|
return if recovery_result == TrafficRecovery::YELLOW
|
|
62
41
|
|
|
63
|
-
from_color, to_color =
|
|
42
|
+
from_color, to_color = case recovery_result
|
|
43
|
+
when TrafficRecovery::GREEN then [Color::YELLOW, Color::GREEN]
|
|
44
|
+
when TrafficRecovery::RED then [Color::YELLOW, Color::RED]
|
|
45
|
+
else
|
|
64
46
|
raise "recovery strategy returned unexpected color: #{recovery_result}"
|
|
65
47
|
end
|
|
66
48
|
|
|
67
49
|
state_store.transition_to_color(to_color)
|
|
68
50
|
metrics_store.clear
|
|
51
|
+
info = LightInfo.new(name: config.name)
|
|
69
52
|
notifiers.each do |notifier|
|
|
70
|
-
notifier.notify(
|
|
53
|
+
notifier.notify(info, from_color, to_color, nil)
|
|
71
54
|
end
|
|
72
55
|
end
|
|
73
56
|
end
|
|
@@ -9,32 +9,7 @@ module Stoplight
|
|
|
9
9
|
# Used by +GreenRunStrategy+ to track failures and potentially open the circuit.
|
|
10
10
|
#
|
|
11
11
|
# @api private
|
|
12
|
-
class Request
|
|
13
|
-
# @!attribute [r] traffic_control
|
|
14
|
-
# @return [Stoplight::Domain::TrafficControl::Base]
|
|
15
|
-
protected attr_reader :traffic_control
|
|
16
|
-
|
|
17
|
-
# @!attribute [r] traffic_control
|
|
18
|
-
# @return [Stoplight::Domain::TrafficControl::Base]
|
|
19
|
-
protected attr_reader :notifiers
|
|
20
|
-
|
|
21
|
-
# @!attribute [r] config
|
|
22
|
-
# @return [Stoplight::Domain::Config] The configuration for the light.
|
|
23
|
-
protected attr_reader :config
|
|
24
|
-
|
|
25
|
-
# @!attribute metrics_store
|
|
26
|
-
# @return [Stoplight::Storage::Metrics]
|
|
27
|
-
protected attr_reader :metrics_store
|
|
28
|
-
|
|
29
|
-
# @!attribute [r] state_store
|
|
30
|
-
# @return [Stoplight::Domain::Storage::State]
|
|
31
|
-
protected attr_reader :state_store
|
|
32
|
-
|
|
33
|
-
# @param traffic_control [Stoplight::Domain::TrafficControl::Base]
|
|
34
|
-
# @param notifiers [<Stoplight::Domain::StateTransitionNotifier>]
|
|
35
|
-
# @param config [Stoplight::Domain::Config]
|
|
36
|
-
# @param metrics_store [Stoplight::Storage::Metrics]
|
|
37
|
-
# @param state_store [Stoplight::Domain::Storage::State]
|
|
12
|
+
class Request
|
|
38
13
|
def initialize(traffic_control:, notifiers:, config:, metrics_store:, state_store:)
|
|
39
14
|
@traffic_control = traffic_control
|
|
40
15
|
@notifiers = notifiers
|
|
@@ -43,8 +18,6 @@ module Stoplight
|
|
|
43
18
|
@state_store = state_store
|
|
44
19
|
end
|
|
45
20
|
|
|
46
|
-
# @param exception [Exception]
|
|
47
|
-
# @return [void]
|
|
48
21
|
def record_failure(exception)
|
|
49
22
|
metrics_store.record_failure(exception)
|
|
50
23
|
metrics = metrics_store.metrics_snapshot
|
|
@@ -52,16 +25,24 @@ module Stoplight
|
|
|
52
25
|
transition_to_red(exception, metrics:)
|
|
53
26
|
end
|
|
54
27
|
|
|
55
|
-
# @return [void]
|
|
56
28
|
def record_success = metrics_store.record_success
|
|
57
29
|
|
|
58
|
-
private
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
attr_reader :traffic_control
|
|
33
|
+
attr_reader :notifiers
|
|
34
|
+
attr_reader :config
|
|
35
|
+
attr_reader :metrics_store
|
|
36
|
+
attr_reader :state_store
|
|
37
|
+
|
|
38
|
+
def transition_to_red(exception, metrics:)
|
|
59
39
|
if traffic_control.stop_traffic?(config, metrics)
|
|
60
40
|
# Returns true only if not yet in red therefore preventing
|
|
61
41
|
# duplicate notifications
|
|
62
42
|
if state_store.transition_to_color(Color::RED)
|
|
43
|
+
info = LightInfo.new(name: config.name)
|
|
63
44
|
notifiers.each do |notifier|
|
|
64
|
-
notifier.notify(
|
|
45
|
+
notifier.notify(info, Color::GREEN, Color::RED, exception)
|
|
65
46
|
end
|
|
66
47
|
end
|
|
67
48
|
end
|
|
@@ -26,27 +26,24 @@ module Stoplight
|
|
|
26
26
|
#
|
|
27
27
|
# Will switch to red only if 5 consecutive failures occur regardless of the time window
|
|
28
28
|
# @api private
|
|
29
|
-
class ConsecutiveErrors
|
|
30
|
-
# @param config [Stoplight::Domain::Config]
|
|
31
|
-
# @return [Stoplight::Domain::CompatibilityResult]
|
|
29
|
+
class ConsecutiveErrors
|
|
32
30
|
def check_compatibility(config)
|
|
33
31
|
if config.threshold <= 0
|
|
34
|
-
incompatible("`threshold` should be bigger than 0")
|
|
32
|
+
CompatibilityResult.incompatible("`threshold` should be bigger than 0")
|
|
35
33
|
elsif !config.threshold.is_a?(Integer)
|
|
36
|
-
incompatible("`threshold` should be an integer")
|
|
34
|
+
CompatibilityResult.incompatible("`threshold` should be an integer")
|
|
37
35
|
else
|
|
38
|
-
compatible
|
|
36
|
+
CompatibilityResult.compatible
|
|
39
37
|
end
|
|
40
38
|
end
|
|
41
39
|
|
|
42
|
-
# Determines if traffic should be stopped based on failure counts.
|
|
43
|
-
#
|
|
44
|
-
# @param config [Stoplight::Domain::Config]
|
|
45
|
-
# @param metrics [Stoplight::Domain::Metrics]
|
|
46
|
-
# @return [Boolean] true if failures have reached the threshold, false otherwise
|
|
47
40
|
def stop_traffic?(config, metrics)
|
|
48
41
|
metrics.consecutive_errors >= config.threshold
|
|
49
42
|
end
|
|
43
|
+
|
|
44
|
+
def ==(other)
|
|
45
|
+
other.is_a?(self.class)
|
|
46
|
+
end
|
|
50
47
|
end
|
|
51
48
|
end
|
|
52
49
|
end
|
|
@@ -16,35 +16,39 @@ module Stoplight
|
|
|
16
16
|
# traffic_control = Stoplight::Domain::TrafficControl::ErrorRate.new(min_requests: 100)
|
|
17
17
|
#
|
|
18
18
|
# @api private
|
|
19
|
-
class ErrorRate
|
|
20
|
-
#
|
|
21
|
-
# @return [Integer]
|
|
22
|
-
attr_reader :min_requests
|
|
23
|
-
|
|
24
|
-
# @param min_requests [Integer] Minimum number of requests before traffic control is applied.
|
|
19
|
+
class ErrorRate
|
|
20
|
+
# @param min_requests Minimum number of requests before traffic control is applied.
|
|
25
21
|
# until this number of requests is reached, the error rate will not be considered.
|
|
26
22
|
def initialize(min_requests: 10)
|
|
27
23
|
@min_requests = min_requests
|
|
28
24
|
end
|
|
29
25
|
|
|
30
|
-
# @param config [Stoplight::Domain::Config]
|
|
31
|
-
# @return [Stoplight::Domain::CompatibilityResult]
|
|
32
26
|
def check_compatibility(config)
|
|
33
27
|
if config.window_size.nil?
|
|
34
|
-
incompatible("`window_size` should be set")
|
|
28
|
+
CompatibilityResult.incompatible("`window_size` should be set")
|
|
35
29
|
elsif config.threshold < 0 || config.threshold > 1
|
|
36
|
-
incompatible("`threshold` should be between 0 and 1")
|
|
30
|
+
CompatibilityResult.incompatible("`threshold` should be between 0 and 1")
|
|
37
31
|
else
|
|
38
|
-
compatible
|
|
32
|
+
CompatibilityResult.compatible
|
|
39
33
|
end
|
|
40
34
|
end
|
|
41
35
|
|
|
42
|
-
# @param config [Stoplight::Domain::Config]
|
|
43
|
-
# @param metrics [Stoplight::Domain::Metrics]
|
|
44
|
-
# @return [Boolean]
|
|
45
36
|
def stop_traffic?(config, metrics)
|
|
46
|
-
|
|
37
|
+
error_rate = metrics.error_rate
|
|
38
|
+
requests = metrics.requests
|
|
39
|
+
|
|
40
|
+
raise ArgumentError, "accepts only windowed metrics" if error_rate.nil? || requests.nil?
|
|
41
|
+
|
|
42
|
+
requests >= min_requests && error_rate >= config.threshold
|
|
47
43
|
end
|
|
44
|
+
|
|
45
|
+
def ==(other)
|
|
46
|
+
other.is_a?(self.class) && min_requests == other.min_requests
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
protected
|
|
50
|
+
|
|
51
|
+
attr_reader :min_requests
|
|
48
52
|
end
|
|
49
53
|
end
|
|
50
54
|
end
|
|
@@ -33,24 +33,18 @@ module Stoplight
|
|
|
33
33
|
# conservative approach prioritizes stability over recovery speed.
|
|
34
34
|
#
|
|
35
35
|
# @api private
|
|
36
|
-
class ConsecutiveSuccesses
|
|
37
|
-
# @param config [Stoplight::Domain::Config]
|
|
38
|
-
# @return [Stoplight::Domain::CompatibilityResult]
|
|
36
|
+
class ConsecutiveSuccesses
|
|
39
37
|
def check_compatibility(config)
|
|
40
38
|
if config.recovery_threshold <= 0
|
|
41
|
-
incompatible("`recovery_threshold` should be bigger than 0")
|
|
39
|
+
CompatibilityResult.incompatible("`recovery_threshold` should be bigger than 0")
|
|
42
40
|
elsif !config.recovery_threshold.is_a?(Integer)
|
|
43
|
-
incompatible("`recovery_threshold` should be an integer")
|
|
41
|
+
CompatibilityResult.incompatible("`recovery_threshold` should be an integer")
|
|
44
42
|
else
|
|
45
|
-
compatible
|
|
43
|
+
CompatibilityResult.compatible
|
|
46
44
|
end
|
|
47
45
|
end
|
|
48
46
|
|
|
49
47
|
# Determines if traffic should be resumed based on successes counts.
|
|
50
|
-
#
|
|
51
|
-
# @param config [Stoplight::Domain::Config]
|
|
52
|
-
# @param recovery_metrics [Stoplight::Domain::Metrics]
|
|
53
|
-
# @return [TrafficRecovery::Decision]
|
|
54
48
|
def determine_color(config, recovery_metrics)
|
|
55
49
|
if recovery_metrics.consecutive_errors > 0
|
|
56
50
|
TrafficRecovery::RED
|
|
@@ -60,6 +54,8 @@ module Stoplight
|
|
|
60
54
|
TrafficRecovery::YELLOW
|
|
61
55
|
end
|
|
62
56
|
end
|
|
57
|
+
|
|
58
|
+
def ==(other) = other.is_a?(self.class)
|
|
63
59
|
end
|
|
64
60
|
end
|
|
65
61
|
end
|
|
@@ -3,10 +3,9 @@
|
|
|
3
3
|
module Stoplight
|
|
4
4
|
module Domain
|
|
5
5
|
module TrafficRecovery
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
RED = Decision.new("red")
|
|
6
|
+
GREEN = :green
|
|
7
|
+
YELLOW = :yellow
|
|
8
|
+
RED = :red
|
|
10
9
|
end
|
|
11
10
|
end
|
|
12
11
|
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Stoplight
|
|
4
|
+
module Error
|
|
5
|
+
class Base < StandardError
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class ConfigurationError < Base
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class IncorrectColor < Base
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class RedLight < Base
|
|
15
|
+
# @!attribute light_name
|
|
16
|
+
# @return [String] The light's name
|
|
17
|
+
attr_reader :light_name
|
|
18
|
+
|
|
19
|
+
# @!attribute cool_off_time
|
|
20
|
+
# @return [Numeric] Cool-off period in seconds
|
|
21
|
+
attr_reader :cool_off_time
|
|
22
|
+
|
|
23
|
+
# @!attribute retry_after
|
|
24
|
+
# @return [Time | nil] Absolute Time after which a recovery attempt can occur
|
|
25
|
+
# could be nil if the light is locked red
|
|
26
|
+
attr_reader :retry_after
|
|
27
|
+
|
|
28
|
+
# Initializes a new RedLight error.
|
|
29
|
+
#
|
|
30
|
+
# @param light_name [String] The light's name
|
|
31
|
+
#
|
|
32
|
+
# @option cool_off_time [Numeric] Cool-off period in seconds
|
|
33
|
+
#
|
|
34
|
+
# @option retry_after [Time | nil] Absolute Time after which a recovery attempt can occur
|
|
35
|
+
#
|
|
36
|
+
# @return [Stoplight::Error::RedLight]
|
|
37
|
+
def initialize(light_name, cool_off_time:, retry_after:)
|
|
38
|
+
@light_name = light_name
|
|
39
|
+
@cool_off_time = cool_off_time
|
|
40
|
+
@retry_after = retry_after
|
|
41
|
+
|
|
42
|
+
super(light_name)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -4,33 +4,22 @@ require "securerandom"
|
|
|
4
4
|
|
|
5
5
|
module Stoplight
|
|
6
6
|
module Infrastructure
|
|
7
|
-
module
|
|
7
|
+
module FailSafe
|
|
8
8
|
# A wrapper around a data store that provides fail-safe mechanisms using a
|
|
9
9
|
# circuit breaker. It ensures that operations on the data store can gracefully
|
|
10
10
|
# handle failures by falling back to default values when necessary.
|
|
11
11
|
#
|
|
12
12
|
# @api private
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
#
|
|
13
|
+
# steep:ignore:start
|
|
14
|
+
class DataStore
|
|
15
|
+
# The underlying primary data store being used
|
|
16
16
|
attr_reader :data_store
|
|
17
|
-
|
|
18
|
-
# @!attribute error_notifier
|
|
19
|
-
# @return [Proc]
|
|
20
17
|
attr_reader :error_notifier
|
|
21
|
-
|
|
22
|
-
# @!attribute failover_data_store
|
|
23
|
-
# @return [Stoplight::DataStore::Base] The fallback data store used when the primary fails.
|
|
18
|
+
# The fallback data store used when the primary fails.
|
|
24
19
|
attr_reader :failover_data_store
|
|
25
|
-
|
|
26
|
-
# @!attribute circuit_breaker
|
|
27
|
-
# @return [Stoplight::Light] The circuit breaker used to handle data store failures.
|
|
20
|
+
# The circuit breaker used to handle data store failures.
|
|
28
21
|
private attr_reader :circuit_breaker
|
|
29
22
|
|
|
30
|
-
# @param data_store [Stoplight::Domain::DataStore]
|
|
31
|
-
# @param error_notifier [Proc]
|
|
32
|
-
# @param failover_data_store [Stoplight::Domain::DataStore]
|
|
33
|
-
# @param circuit_breaker [Stoplight::Domain::Light]
|
|
34
23
|
def initialize(data_store:, error_notifier:, failover_data_store:, circuit_breaker:)
|
|
35
24
|
@data_store = data_store
|
|
36
25
|
@error_notifier = error_notifier
|
|
@@ -44,15 +33,15 @@ module Stoplight
|
|
|
44
33
|
end
|
|
45
34
|
end
|
|
46
35
|
|
|
47
|
-
def get_metrics(config
|
|
48
|
-
with_fallback(:get_metrics, config
|
|
49
|
-
data_store.get_metrics(config
|
|
36
|
+
def get_metrics(config)
|
|
37
|
+
with_fallback(:get_metrics, config) do
|
|
38
|
+
data_store.get_metrics(config)
|
|
50
39
|
end
|
|
51
40
|
end
|
|
52
41
|
|
|
53
|
-
def get_recovery_metrics(config
|
|
54
|
-
with_fallback(:get_recovery_metrics, config
|
|
55
|
-
data_store.get_recovery_metrics(config
|
|
42
|
+
def get_recovery_metrics(config)
|
|
43
|
+
with_fallback(:get_recovery_metrics, config) do
|
|
44
|
+
data_store.get_recovery_metrics(config)
|
|
56
45
|
end
|
|
57
46
|
end
|
|
58
47
|
|
|
@@ -74,45 +63,45 @@ module Stoplight
|
|
|
74
63
|
end
|
|
75
64
|
end
|
|
76
65
|
|
|
77
|
-
def record_failure(config,
|
|
78
|
-
with_fallback(:record_failure, config,
|
|
79
|
-
data_store.record_failure(config,
|
|
66
|
+
def record_failure(config, exception)
|
|
67
|
+
with_fallback(:record_failure, config, exception) do
|
|
68
|
+
data_store.record_failure(config, exception)
|
|
80
69
|
end
|
|
81
70
|
end
|
|
82
71
|
|
|
83
|
-
def record_success(config
|
|
84
|
-
with_fallback(:record_success, config
|
|
85
|
-
data_store.record_success(config
|
|
72
|
+
def record_success(config)
|
|
73
|
+
with_fallback(:record_success, config) do
|
|
74
|
+
data_store.record_success(config)
|
|
86
75
|
end
|
|
87
76
|
end
|
|
88
77
|
|
|
89
|
-
def record_recovery_probe_success(config
|
|
90
|
-
with_fallback(:record_recovery_probe_success, config
|
|
91
|
-
data_store.record_recovery_probe_success(config
|
|
78
|
+
def record_recovery_probe_success(config)
|
|
79
|
+
with_fallback(:record_recovery_probe_success, config) do
|
|
80
|
+
data_store.record_recovery_probe_success(config)
|
|
92
81
|
end
|
|
93
82
|
end
|
|
94
83
|
|
|
95
|
-
def record_recovery_probe_failure(config,
|
|
96
|
-
with_fallback(:record_recovery_probe_failure, config,
|
|
97
|
-
data_store.record_recovery_probe_failure(config,
|
|
84
|
+
def record_recovery_probe_failure(config, exception)
|
|
85
|
+
with_fallback(:record_recovery_probe_failure, config, exception) do
|
|
86
|
+
data_store.record_recovery_probe_failure(config, exception)
|
|
98
87
|
end
|
|
99
88
|
end
|
|
100
89
|
|
|
101
|
-
def set_state(config,
|
|
102
|
-
with_fallback(:set_state, config,
|
|
103
|
-
data_store.set_state(config,
|
|
90
|
+
def set_state(config, state)
|
|
91
|
+
with_fallback(:set_state, config, state) do
|
|
92
|
+
data_store.set_state(config, state)
|
|
104
93
|
end
|
|
105
94
|
end
|
|
106
95
|
|
|
107
|
-
def transition_to_color(config,
|
|
108
|
-
with_fallback(:transition_to_color, config,
|
|
109
|
-
data_store.transition_to_color(config,
|
|
96
|
+
def transition_to_color(config, color)
|
|
97
|
+
with_fallback(:transition_to_color, config, color) do
|
|
98
|
+
data_store.transition_to_color(config, color)
|
|
110
99
|
end
|
|
111
100
|
end
|
|
112
101
|
|
|
113
|
-
def delete_light(config
|
|
114
|
-
with_fallback(:delete_light, config
|
|
115
|
-
data_store.delete_light(config
|
|
102
|
+
def delete_light(config)
|
|
103
|
+
with_fallback(:delete_light, config) do
|
|
104
|
+
data_store.delete_light(config)
|
|
116
105
|
end
|
|
117
106
|
end
|
|
118
107
|
|
|
@@ -127,10 +116,9 @@ module Stoplight
|
|
|
127
116
|
# Redis tokens release via primary (with error notification on failure).
|
|
128
117
|
# Memory tokens release via failover directly.
|
|
129
118
|
#
|
|
130
|
-
# @param recovery_lock_token [Stoplight::Domain::RecoveryLockToken]
|
|
131
119
|
def release_recovery_lock(recovery_lock_token)
|
|
132
120
|
case recovery_lock_token
|
|
133
|
-
in Redis::RecoveryLockToken
|
|
121
|
+
in Redis::DataStore::RecoveryLockToken
|
|
134
122
|
fallback = proc do |error|
|
|
135
123
|
error_notifier.call(error) if error
|
|
136
124
|
end
|
|
@@ -138,7 +126,7 @@ module Stoplight
|
|
|
138
126
|
circuit_breaker.run(fallback) do
|
|
139
127
|
data_store.release_recovery_lock(recovery_lock_token)
|
|
140
128
|
end
|
|
141
|
-
in Memory::RecoveryLockToken
|
|
129
|
+
in Memory::DataStore::RecoveryLockToken
|
|
142
130
|
failover_data_store.release_recovery_lock(recovery_lock_token)
|
|
143
131
|
end
|
|
144
132
|
end
|
|
@@ -148,17 +136,17 @@ module Stoplight
|
|
|
148
136
|
other.failover_data_store == failover_data_store
|
|
149
137
|
end
|
|
150
138
|
|
|
151
|
-
# @param method_name [Symbol] protected method name
|
|
152
139
|
private def with_fallback(method_name, *args, **kwargs, &code)
|
|
153
|
-
fallback =
|
|
140
|
+
fallback = ->(error) {
|
|
154
141
|
config = args.first
|
|
155
142
|
error_notifier.call(error) if config && error
|
|
156
|
-
|
|
157
|
-
|
|
143
|
+
failover_data_store.public_send(method_name, *args, **kwargs)
|
|
144
|
+
}
|
|
158
145
|
|
|
159
146
|
circuit_breaker.run(fallback, &code)
|
|
160
147
|
end
|
|
161
148
|
end
|
|
149
|
+
# steep:ignore:end
|
|
162
150
|
end
|
|
163
151
|
end
|
|
164
152
|
end
|