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
|
@@ -4,24 +4,6 @@ module Stoplight
|
|
|
4
4
|
module Domain
|
|
5
5
|
# A +Stoplight::Light+ configuration object.
|
|
6
6
|
#
|
|
7
|
-
# # @!attribute [r] name
|
|
8
|
-
# @return [String]
|
|
9
|
-
#
|
|
10
|
-
# @!attribute [r] cool_off_time - cool-off time in seconds
|
|
11
|
-
# @return [Numeric]
|
|
12
|
-
#
|
|
13
|
-
# @!attribute [r] threshold
|
|
14
|
-
# @return [Numeric]
|
|
15
|
-
#
|
|
16
|
-
# @!attribute [r] window_size
|
|
17
|
-
# @return [Numeric]
|
|
18
|
-
#
|
|
19
|
-
# @!attribute [r] tracked_errors
|
|
20
|
-
# @return [Array<StandardError>]
|
|
21
|
-
#
|
|
22
|
-
# @!attribute [r] skipped_errors
|
|
23
|
-
# @return [Array<Exception>]
|
|
24
|
-
#
|
|
25
7
|
# @api private
|
|
26
8
|
Config = Data.define(
|
|
27
9
|
:name,
|
|
@@ -30,29 +12,46 @@ module Stoplight
|
|
|
30
12
|
:recovery_threshold,
|
|
31
13
|
:window_size,
|
|
32
14
|
:tracked_errors,
|
|
33
|
-
:skipped_errors
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
# Checks if the given error should be tracked
|
|
44
|
-
#
|
|
45
|
-
# @param error [#==] The error to check, e.g. an Exception, Class or Proc
|
|
46
|
-
# @return [Boolean]
|
|
47
|
-
def track_error?(error)
|
|
48
|
-
skip = skipped_errors.any? { |klass| klass === error }
|
|
49
|
-
track = tracked_errors.any? { |klass| klass === error }
|
|
50
|
-
|
|
51
|
-
!skip && track
|
|
15
|
+
:skipped_errors,
|
|
16
|
+
:traffic_control,
|
|
17
|
+
:traffic_recovery,
|
|
18
|
+
:error_notifier,
|
|
19
|
+
:notifiers,
|
|
20
|
+
:data_store
|
|
21
|
+
)
|
|
22
|
+
class Config
|
|
23
|
+
def cool_off_time_in_milliseconds
|
|
24
|
+
(cool_off_time * 1_000).to_i
|
|
52
25
|
end
|
|
53
26
|
|
|
54
|
-
def
|
|
55
|
-
|
|
27
|
+
def with(
|
|
28
|
+
name: T.undefined,
|
|
29
|
+
cool_off_time: T.undefined,
|
|
30
|
+
threshold: T.undefined,
|
|
31
|
+
recovery_threshold: T.undefined,
|
|
32
|
+
window_size: T.undefined,
|
|
33
|
+
skipped_errors: T.undefined,
|
|
34
|
+
tracked_errors: T.undefined,
|
|
35
|
+
traffic_control: T.undefined,
|
|
36
|
+
traffic_recovery: T.undefined,
|
|
37
|
+
error_notifier: T.undefined,
|
|
38
|
+
notifiers: T.undefined,
|
|
39
|
+
data_store: T.undefined
|
|
40
|
+
)
|
|
41
|
+
super(
|
|
42
|
+
name: name.is_a?(Undefined) ? self.name : name,
|
|
43
|
+
cool_off_time: cool_off_time.is_a?(Undefined) ? self.cool_off_time : cool_off_time,
|
|
44
|
+
threshold: threshold.is_a?(Undefined) ? self.threshold : threshold,
|
|
45
|
+
recovery_threshold: recovery_threshold.is_a?(Undefined) ? self.recovery_threshold : recovery_threshold,
|
|
46
|
+
window_size: window_size.is_a?(Undefined) ? self.window_size : window_size,
|
|
47
|
+
skipped_errors: skipped_errors.is_a?(Undefined) ? self.skipped_errors : skipped_errors,
|
|
48
|
+
tracked_errors: tracked_errors.is_a?(Undefined) ? self.tracked_errors : tracked_errors,
|
|
49
|
+
traffic_control: traffic_control.is_a?(Undefined) ? self.traffic_control : traffic_control,
|
|
50
|
+
traffic_recovery: traffic_recovery.is_a?(Undefined) ? self.traffic_recovery : traffic_recovery,
|
|
51
|
+
error_notifier: error_notifier.is_a?(Undefined) ? self.error_notifier : error_notifier,
|
|
52
|
+
notifiers: notifiers.is_a?(Undefined) ? self.notifiers : notifiers,
|
|
53
|
+
data_store: data_store.is_a?(Undefined) ? self.data_store : data_store,
|
|
54
|
+
)
|
|
56
55
|
end
|
|
57
56
|
end
|
|
58
57
|
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Stoplight
|
|
4
|
+
module Domain
|
|
5
|
+
# Determines which errors should be traced
|
|
6
|
+
class ErrorTrackingPolicy
|
|
7
|
+
def initialize(tracked:, skipped:)
|
|
8
|
+
@tracked = tracked
|
|
9
|
+
@skipped = skipped
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def track?(error)
|
|
13
|
+
!skipped?(error) && tracked?(error)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def skipped?(error)
|
|
19
|
+
@skipped.any? { |matcher| matcher === error }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def tracked?(error)
|
|
23
|
+
@tracked.any? { |matcher| matcher === error }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -6,6 +6,7 @@ module Stoplight
|
|
|
6
6
|
module Domain
|
|
7
7
|
class Light
|
|
8
8
|
# Implements light configuration behavior
|
|
9
|
+
# steep:ignore:start
|
|
9
10
|
module ConfigurationBuilderInterface
|
|
10
11
|
# Configures data store to be used with this circuit breaker
|
|
11
12
|
#
|
|
@@ -229,6 +230,7 @@ module Stoplight
|
|
|
229
230
|
with_without_warning(skipped_errors:)
|
|
230
231
|
end
|
|
231
232
|
end
|
|
233
|
+
# steep:ignore:end
|
|
232
234
|
end
|
|
233
235
|
end
|
|
234
236
|
end
|
|
@@ -1,49 +1,23 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "forwardable"
|
|
4
|
-
|
|
5
3
|
module Stoplight
|
|
6
4
|
module Domain
|
|
7
5
|
#
|
|
8
6
|
# @api private use +Stoplight()+ method instead
|
|
9
7
|
class Light
|
|
10
|
-
extend Forwardable
|
|
11
8
|
include Common::Deprecations
|
|
12
|
-
include ConfigurationBuilderInterface
|
|
13
|
-
|
|
14
|
-
# @!attribute [r] config
|
|
15
|
-
# @return [Stoplight::Domain::Config]
|
|
16
|
-
# @api private
|
|
17
|
-
attr_reader :config
|
|
18
|
-
|
|
19
|
-
# @!attribute [r] name
|
|
20
|
-
# The name of the light.
|
|
21
|
-
# @return [String]
|
|
22
|
-
def_delegator :config, :name
|
|
23
|
-
|
|
24
|
-
# @!attribute [r] green_run_strategy
|
|
25
|
-
# @return [Stoplight::Domain::Strategies::GreenRunStrategy]
|
|
26
|
-
protected attr_reader :green_run_strategy
|
|
9
|
+
include ConfigurationBuilderInterface # steep:ignore
|
|
27
10
|
|
|
28
|
-
|
|
29
|
-
# @return [Stoplight::Domain::Strategies::YellowRunStrategy]
|
|
30
|
-
protected attr_reader :yellow_run_strategy
|
|
11
|
+
attr_reader :name
|
|
31
12
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
13
|
+
attr_reader :green_run_strategy
|
|
14
|
+
attr_reader :yellow_run_strategy
|
|
15
|
+
attr_reader :red_run_strategy
|
|
16
|
+
attr_reader :factory
|
|
17
|
+
attr_reader :state_store
|
|
35
18
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
protected attr_reader :factory
|
|
39
|
-
|
|
40
|
-
# @!attribute state_store
|
|
41
|
-
# @param [Stoplight::Domain::Storage::State]
|
|
42
|
-
protected attr_reader :state_store
|
|
43
|
-
|
|
44
|
-
# @param config [Stoplight::Domain::Config]
|
|
45
|
-
def initialize(config, green_run_strategy:, yellow_run_strategy:, red_run_strategy:, factory:, state_store:)
|
|
46
|
-
@config = config
|
|
19
|
+
def initialize(name, green_run_strategy:, yellow_run_strategy:, red_run_strategy:, factory:, state_store:)
|
|
20
|
+
@name = name
|
|
47
21
|
@green_run_strategy = green_run_strategy
|
|
48
22
|
@yellow_run_strategy = yellow_run_strategy
|
|
49
23
|
@red_run_strategy = red_run_strategy
|
|
@@ -56,7 +30,6 @@ module Stoplight
|
|
|
56
30
|
# * +Stoplight::State::LOCKED_RED+ -- light is locked red and blocks all traffic
|
|
57
31
|
# * +Stoplight::State::UNLOCKED+ -- light is not locked and follow the configured rules
|
|
58
32
|
#
|
|
59
|
-
# @return [String]
|
|
60
33
|
def state = state_snapshot.locked_state
|
|
61
34
|
|
|
62
35
|
# Returns current color:
|
|
@@ -68,7 +41,6 @@ module Stoplight
|
|
|
68
41
|
# light = Stoplight('example')
|
|
69
42
|
# light.color #=> Color::GREEN
|
|
70
43
|
#
|
|
71
|
-
# @return [String] returns current light color
|
|
72
44
|
def color = state_snapshot.color
|
|
73
45
|
|
|
74
46
|
# Runs the given block of code with this circuit breaker
|
|
@@ -81,9 +53,7 @@ module Stoplight
|
|
|
81
53
|
# light = Stoplight('example')
|
|
82
54
|
# light.run(->(error) { 0 }) { 1 / 0 } #=> 0
|
|
83
55
|
#
|
|
84
|
-
# @param fallback
|
|
85
|
-
# @raise [Stoplight::Error::RedLight]
|
|
86
|
-
# @return [any]
|
|
56
|
+
# @param fallback fallback code to run if the circuit breaker is open
|
|
87
57
|
# @raise [Stoplight::Error::RedLight]
|
|
88
58
|
def run(fallback = nil, &code)
|
|
89
59
|
raise ArgumentError, "nothing to run. Please, pass a block into `Light#run`" unless block_given?
|
|
@@ -100,8 +70,8 @@ module Stoplight
|
|
|
100
70
|
# light = Stoplight('example-locked')
|
|
101
71
|
# light.lock(Stoplight::Color::RED)
|
|
102
72
|
#
|
|
103
|
-
# @param color
|
|
104
|
-
# @return
|
|
73
|
+
# @param color should be either +Color::RED+ or +Color::GREEN+
|
|
74
|
+
# @return locked light
|
|
105
75
|
def lock(color)
|
|
106
76
|
state = case color
|
|
107
77
|
when Color::RED then State::LOCKED_RED
|
|
@@ -121,7 +91,7 @@ module Stoplight
|
|
|
121
91
|
# light.lock(Stoplight::Color::RED)
|
|
122
92
|
# light.unlock
|
|
123
93
|
#
|
|
124
|
-
# @return
|
|
94
|
+
# @return returns unlocked light (circuit breaker)
|
|
125
95
|
def unlock
|
|
126
96
|
state_store.set_state(State::UNLOCKED)
|
|
127
97
|
|
|
@@ -129,9 +99,6 @@ module Stoplight
|
|
|
129
99
|
end
|
|
130
100
|
|
|
131
101
|
# Two lights considered equal if they have the same configuration.
|
|
132
|
-
#
|
|
133
|
-
# @param other [any]
|
|
134
|
-
# @return [Boolean]
|
|
135
102
|
def ==(other)
|
|
136
103
|
other.is_a?(self.class) && factory == other.factory
|
|
137
104
|
end
|
|
@@ -168,6 +135,7 @@ module Stoplight
|
|
|
168
135
|
# payment_light.run(->(error) { nil }) { call_payment_api }
|
|
169
136
|
# @deprecated
|
|
170
137
|
# @see +Stoplight()+
|
|
138
|
+
# steep:ignore:start
|
|
171
139
|
def with(**settings)
|
|
172
140
|
deprecate(<<~MSG)
|
|
173
141
|
Light#with is deprecated and will be removed in v6.0.0.
|
|
@@ -188,6 +156,7 @@ module Stoplight
|
|
|
188
156
|
private def with_without_warning(**settings)
|
|
189
157
|
factory.build_with(**settings)
|
|
190
158
|
end
|
|
159
|
+
# steep:ignore:end
|
|
191
160
|
|
|
192
161
|
private
|
|
193
162
|
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Stoplight
|
|
4
|
+
module Domain
|
|
5
|
+
# Request metrics over a given window.
|
|
6
|
+
#
|
|
7
|
+
# @api private
|
|
8
|
+
MetricsSnapshot = Data.define(
|
|
9
|
+
:successes,
|
|
10
|
+
:errors,
|
|
11
|
+
:consecutive_errors,
|
|
12
|
+
:consecutive_successes,
|
|
13
|
+
:last_error,
|
|
14
|
+
:last_success_at
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
class MetricsSnapshot
|
|
18
|
+
# @!attribute successes
|
|
19
|
+
# A number of successes withing requested window. Zero for non-windowed metrics
|
|
20
|
+
#
|
|
21
|
+
# @!attribute errors
|
|
22
|
+
# A number of errors withing requested window. Zero for non-windowed metrics
|
|
23
|
+
|
|
24
|
+
# Calculates the error rate based on the number of successes and errors.
|
|
25
|
+
#
|
|
26
|
+
# @return [Float]
|
|
27
|
+
def error_rate
|
|
28
|
+
return unless requests # we effectively check if this is windowed metrics
|
|
29
|
+
|
|
30
|
+
if (successes! + errors!).zero?
|
|
31
|
+
0.0
|
|
32
|
+
else
|
|
33
|
+
errors!.fdiv(successes! + errors!)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# @return [Integer]
|
|
38
|
+
def requests
|
|
39
|
+
if successes && errors # we effectively check if this is windowed metrics
|
|
40
|
+
successes! + errors!
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# @return [Time, nil]
|
|
45
|
+
def last_error_at
|
|
46
|
+
last_error&.time
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def successes!
|
|
50
|
+
successes or raise TypeError, "success must not be nil"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def errors!
|
|
54
|
+
errors or raise TypeError, "errors must not be nil"
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -2,39 +2,34 @@
|
|
|
2
2
|
|
|
3
3
|
module Stoplight
|
|
4
4
|
module Domain
|
|
5
|
-
# @!attribute breached_at
|
|
6
|
-
# The time when the light became red (breached threshold)
|
|
7
|
-
# @return [Time, nil]
|
|
8
|
-
#
|
|
9
|
-
# @!attribute locked_state
|
|
10
|
-
# @return [State::UNLOCKED | State::LOCKED_GREEN | State::LOCKED_RED]
|
|
11
|
-
#
|
|
12
|
-
# @!attribute recovery_scheduled_after
|
|
13
|
-
# When Light transitions to RED, it schedules recovery after the Cool Off Time.
|
|
14
|
-
# @return [Time, nil]
|
|
15
|
-
#
|
|
16
|
-
# @!attribute recovery_started_at
|
|
17
|
-
# When in YELLOW state, this time indicates the time of transitioning to YELLOW
|
|
18
|
-
# @return [Time, nil]
|
|
19
|
-
#
|
|
20
|
-
# @!attribute time
|
|
21
|
-
# The time when the snapshot was taken
|
|
22
|
-
# @return [Time]
|
|
23
|
-
#
|
|
24
5
|
StateSnapshot = Data.define(
|
|
25
6
|
:breached_at,
|
|
26
7
|
:locked_state,
|
|
27
8
|
:recovery_scheduled_after,
|
|
28
9
|
:recovery_started_at,
|
|
29
10
|
:time
|
|
30
|
-
)
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
class StateSnapshot
|
|
14
|
+
# @!attribute breached_at
|
|
15
|
+
# The time when the light became red (breached threshold)
|
|
16
|
+
#
|
|
17
|
+
# @!attribute recovery_scheduled_after
|
|
18
|
+
# When Light transitions to RED, it schedules recovery after the Cool Off Time.
|
|
19
|
+
#
|
|
20
|
+
# @!attribute recovery_started_at
|
|
21
|
+
# When in YELLOW state, this time indicates the time of transitioning to YELLOW
|
|
22
|
+
#
|
|
23
|
+
# @!attribute time
|
|
24
|
+
# The time when the snapshot was taken
|
|
25
|
+
|
|
31
26
|
# @return [String] one of +Color::GREEN+, +Color::RED+, or +Color::YELLOW+
|
|
32
27
|
def color
|
|
33
28
|
if locked_state == State::LOCKED_GREEN
|
|
34
29
|
Color::GREEN
|
|
35
30
|
elsif locked_state == State::LOCKED_RED
|
|
36
31
|
Color::RED
|
|
37
|
-
elsif (recovery_scheduled_after && recovery_scheduled_after < time) || recovery_started_at
|
|
32
|
+
elsif (recovery_scheduled_after && recovery_scheduled_after! < time) || recovery_started_at
|
|
38
33
|
Color::YELLOW
|
|
39
34
|
elsif breached_at
|
|
40
35
|
Color::RED
|
|
@@ -48,9 +43,20 @@ module Stoplight
|
|
|
48
43
|
#
|
|
49
44
|
# This method indicates whether the recovery has already started explicitly
|
|
50
45
|
#
|
|
51
|
-
# @return [Boolean]
|
|
52
46
|
def recovery_started?
|
|
53
|
-
|
|
47
|
+
if recovery_started_at.nil?
|
|
48
|
+
false
|
|
49
|
+
else
|
|
50
|
+
recovery_started_at! <= time
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def recovery_started_at!
|
|
55
|
+
recovery_started_at or raise TypeError, "recovery_started_at must not be nil"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def recovery_scheduled_after!
|
|
59
|
+
recovery_scheduled_after or raise TypeError, "recovery_scheduled_after must not be nil"
|
|
54
60
|
end
|
|
55
61
|
end
|
|
56
62
|
end
|
|
@@ -9,34 +9,26 @@ module Stoplight
|
|
|
9
9
|
# by either raising them or invoking a fallback if provided.
|
|
10
10
|
#
|
|
11
11
|
# @api private
|
|
12
|
-
class GreenRunStrategy
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
protected attr_reader :request_tracker
|
|
16
|
-
|
|
17
|
-
# @!attribute [r] config
|
|
18
|
-
# @return [Stoplight::Domain::Config] The configuration for the light.
|
|
19
|
-
protected attr_reader :config
|
|
20
|
-
|
|
21
|
-
# @param config [Stoplight::Domain::Config]
|
|
22
|
-
# @param request_tracker [Stoplight::Domain::Tracker::Request
|
|
23
|
-
def initialize(config:, request_tracker:)
|
|
24
|
-
@config = config
|
|
12
|
+
class GreenRunStrategy
|
|
13
|
+
def initialize(error_tracking_policy:, request_tracker:)
|
|
14
|
+
@error_tracking_policy = error_tracking_policy
|
|
25
15
|
@request_tracker = request_tracker
|
|
26
16
|
end
|
|
27
17
|
|
|
28
18
|
# Executes the provided code block when the light is in the green state.
|
|
29
19
|
#
|
|
30
|
-
# @param fallback
|
|
31
|
-
# @param state_snapshot
|
|
20
|
+
# @param fallback A fallback proc to execute in case of an error.
|
|
21
|
+
# @param state_snapshot
|
|
32
22
|
# @yield The code block to execute.
|
|
33
|
-
# @return
|
|
34
|
-
# @raise
|
|
23
|
+
# @return The result of the code block if successful.
|
|
24
|
+
# @raise re-raises the error if it is not tracked or no fallback is provided.
|
|
35
25
|
def execute(fallback, state_snapshot:, &code)
|
|
36
26
|
# TODO: Consider implementing sampling rate to limit the memory footprint
|
|
37
|
-
code.call
|
|
27
|
+
result = code.call
|
|
28
|
+
record_success
|
|
29
|
+
result
|
|
38
30
|
rescue => error
|
|
39
|
-
if
|
|
31
|
+
if @error_tracking_policy.track?(error)
|
|
40
32
|
record_error(error)
|
|
41
33
|
|
|
42
34
|
if fallback
|
|
@@ -51,18 +43,18 @@ module Stoplight
|
|
|
51
43
|
end
|
|
52
44
|
end
|
|
53
45
|
|
|
54
|
-
private
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
attr_reader :config
|
|
49
|
+
attr_reader :request_tracker
|
|
50
|
+
|
|
51
|
+
def record_error(error)
|
|
55
52
|
request_tracker.record_failure(error)
|
|
56
53
|
end
|
|
57
54
|
|
|
58
|
-
|
|
55
|
+
def record_success
|
|
59
56
|
request_tracker.record_success
|
|
60
57
|
end
|
|
61
|
-
|
|
62
|
-
# @return [Boolean]
|
|
63
|
-
def ==(other)
|
|
64
|
-
super && config == other.config && request_tracker == other.request_tracker
|
|
65
|
-
end
|
|
66
58
|
end
|
|
67
59
|
end
|
|
68
60
|
end
|
|
@@ -9,28 +9,25 @@ module Stoplight
|
|
|
9
9
|
# or invokes a fallback if provided.
|
|
10
10
|
#
|
|
11
11
|
# @api private
|
|
12
|
-
class RedRunStrategy
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def initialize(config:)
|
|
18
|
-
@config = config
|
|
12
|
+
class RedRunStrategy
|
|
13
|
+
def initialize(name:, cool_off_time:)
|
|
14
|
+
@name = name
|
|
15
|
+
@cool_off_time = cool_off_time
|
|
19
16
|
end
|
|
20
17
|
|
|
21
18
|
# Executes the fallback proc when the light is in the red state.
|
|
22
19
|
#
|
|
23
|
-
# @param fallback
|
|
24
|
-
# @param state_snapshot
|
|
25
|
-
# @return
|
|
20
|
+
# @param fallback A fallback proc to execute instead of the code block.
|
|
21
|
+
# @param state_snapshot
|
|
22
|
+
# @return The result of the fallback proc if provided.
|
|
26
23
|
# @raise [Stoplight::Error::RedLight] Raises an error if no fallback is provided.
|
|
27
24
|
def execute(fallback, state_snapshot:)
|
|
28
25
|
if fallback
|
|
29
26
|
fallback.call(nil)
|
|
30
27
|
else
|
|
31
28
|
raise Error::RedLight.new(
|
|
32
|
-
|
|
33
|
-
cool_off_time:
|
|
29
|
+
@name,
|
|
30
|
+
cool_off_time: @cool_off_time,
|
|
34
31
|
retry_after: state_snapshot.recovery_scheduled_after
|
|
35
32
|
)
|
|
36
33
|
end
|