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
|
@@ -2,76 +2,93 @@
|
|
|
2
2
|
|
|
3
3
|
module Stoplight
|
|
4
4
|
module Wiring
|
|
5
|
-
# User-facing configuration interface
|
|
5
|
+
# User-facing configuration interface for setting global Stoplight defaults.
|
|
6
|
+
#
|
|
7
|
+
# This class serves as the configuration DSL yielded to users when calling
|
|
8
|
+
# +Stoplight.configure+. It provides a clean interface for setting default
|
|
9
|
+
# values while internally tracking whether each setting was explicitly
|
|
10
|
+
# configured or should fall back to library defaults.
|
|
11
|
+
#
|
|
12
|
+
# @example Configuring Stoplight defaults
|
|
13
|
+
# Stoplight.configure do |config|
|
|
14
|
+
# config.data_store = Redis.new
|
|
15
|
+
# config.threshold = 5
|
|
16
|
+
# # window_size not set - will use library default
|
|
17
|
+
# end
|
|
18
|
+
#
|
|
19
|
+
# == Option-Based Configuration Tracking
|
|
20
|
+
#
|
|
21
|
+
# Internally, each setting is wrapped in an Option type (+Some+ or +None+).
|
|
22
|
+
# This design allows the class to distinguish between three states:
|
|
23
|
+
#
|
|
24
|
+
# 1. Not configured: Stored as +None+, getter returns library default
|
|
25
|
+
# 2. Explicitly configured: Stored as +Some(value)+, getter returns that value
|
|
26
|
+
# 3. Explicitly set to nil: Stored as +Some(nil)+, getter returns +nil+
|
|
27
|
+
#
|
|
28
|
+
# This distinction is critical when building {Settings} and {Dependencies}
|
|
29
|
+
# objects, which need to know whether a value was user-specified (and should
|
|
30
|
+
# be enforced) or inherited (and can be overridden per-circuit).
|
|
31
|
+
#
|
|
32
|
+
# == Dual Interface
|
|
33
|
+
#
|
|
34
|
+
# The class exposes two interfaces for each setting:
|
|
35
|
+
#
|
|
36
|
+
# - *Setters* (+attr_writer+): Accept raw values, wrap them in +Some+
|
|
37
|
+
# - *Getters* (custom methods): Unwrap the Option, returning the value
|
|
38
|
+
# or falling back to library defaults from {Default}
|
|
39
|
+
#
|
|
40
|
+
# The {#settings} and {#dependencies} methods preserve the raw Option
|
|
41
|
+
# values, allowing downstream code to detect explicit configuration.
|
|
42
|
+
#
|
|
43
|
+
# @see Settings Value object for circuit behavior configuration
|
|
44
|
+
# @see Dependencies Value object for infrastructure dependencies
|
|
45
|
+
# @see Default Library default constants
|
|
46
|
+
#
|
|
6
47
|
class DefaultConfiguration
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
48
|
+
def initialize
|
|
49
|
+
@config = DefaultConfig.with
|
|
50
|
+
@cool_off_time = T.undefined
|
|
51
|
+
@threshold = T.undefined
|
|
52
|
+
@recovery_threshold = T.undefined
|
|
53
|
+
@window_size = T.undefined
|
|
54
|
+
@tracked_errors = T.undefined
|
|
55
|
+
@skipped_errors = T.undefined
|
|
56
|
+
@traffic_control = T.undefined
|
|
57
|
+
@traffic_recovery = T.undefined
|
|
58
|
+
@error_notifier = T.undefined
|
|
59
|
+
@data_store = T.undefined
|
|
60
|
+
@notifiers = T.undefined
|
|
61
|
+
end
|
|
10
62
|
|
|
11
|
-
|
|
12
|
-
# @return [Integer, Float, nil] The default failure threshold to trip the circuit breaker.
|
|
13
|
-
attr_writer :threshold
|
|
63
|
+
def notifiers = @config.notifiers
|
|
14
64
|
|
|
15
|
-
|
|
16
|
-
|
|
65
|
+
attr_writer :cool_off_time
|
|
66
|
+
attr_writer :threshold
|
|
17
67
|
attr_writer :recovery_threshold
|
|
18
|
-
|
|
19
|
-
# @!attribute [w] window_size
|
|
20
|
-
# @return [Integer, nil] The default size of the rolling window for failure tracking.
|
|
21
68
|
attr_writer :window_size
|
|
22
|
-
|
|
23
|
-
# @!attribute [w] tracked_errors
|
|
24
|
-
# @return [Array<Class>, nil] The default list of errors to track.
|
|
25
69
|
attr_writer :tracked_errors
|
|
26
|
-
|
|
27
|
-
# @!attribute [w] skipped_errors
|
|
28
|
-
# @return [Array<Class>, nil] The default list of errors to skip.
|
|
29
70
|
attr_writer :skipped_errors
|
|
30
|
-
|
|
31
|
-
# @!attribute [w] error_notifier
|
|
32
|
-
# @return [Proc, nil] The default error notifier (callable object).
|
|
33
|
-
attr_writer :error_notifier
|
|
34
|
-
|
|
35
|
-
# @!attribute [rw] notifiers
|
|
36
|
-
# @return [Array<Stoplight::Domain::StateTransitionNotifier>] The default list of notifiers.
|
|
37
|
-
attr_accessor :notifiers
|
|
38
|
-
|
|
39
|
-
# @!attribute [rw] data_store
|
|
40
|
-
# @return [Stoplight::Domain::DataStore] The default data store instance.
|
|
41
|
-
attr_accessor :data_store
|
|
42
|
-
|
|
43
|
-
# @!attribute [w] traffic_control
|
|
44
|
-
# @return [Stoplight::Domain::TrafficControl::Base] The traffic control strategy.
|
|
45
71
|
attr_writer :traffic_control
|
|
46
|
-
|
|
47
|
-
# @!attribute [w] traffic_recovery
|
|
48
|
-
# @return [Stoplight::Domain::TrafficRecovery::Base] The traffic recovery strategy.
|
|
49
72
|
attr_writer :traffic_recovery
|
|
73
|
+
attr_writer :error_notifier
|
|
74
|
+
attr_writer :data_store
|
|
75
|
+
attr_writer :notifiers
|
|
50
76
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
@notifiers = Default::NOTIFIERS
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
# Converts the user-defined configuration to a hash.
|
|
58
|
-
#
|
|
59
|
-
# @return [Hash] A hash representation of the configuration, excluding nil values.
|
|
60
|
-
# @api private
|
|
61
|
-
def to_h
|
|
62
|
-
{
|
|
77
|
+
# Builds and validates configuration
|
|
78
|
+
def to_config!
|
|
79
|
+
ConfigurationDsl.new(
|
|
63
80
|
cool_off_time: @cool_off_time,
|
|
64
81
|
threshold: @threshold,
|
|
65
82
|
recovery_threshold: @recovery_threshold,
|
|
66
83
|
window_size: @window_size,
|
|
67
84
|
tracked_errors: @tracked_errors,
|
|
68
85
|
skipped_errors: @skipped_errors,
|
|
69
|
-
data_store: @data_store,
|
|
70
|
-
error_notifier: @error_notifier,
|
|
71
|
-
notifiers: @notifiers,
|
|
72
86
|
traffic_control: @traffic_control,
|
|
73
|
-
traffic_recovery: @traffic_recovery
|
|
74
|
-
|
|
87
|
+
traffic_recovery: @traffic_recovery,
|
|
88
|
+
error_notifier: @error_notifier,
|
|
89
|
+
data_store: @data_store,
|
|
90
|
+
notifiers: @notifiers
|
|
91
|
+
).configure!(@config)
|
|
75
92
|
end
|
|
76
93
|
end
|
|
77
94
|
end
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "concurrent/map"
|
|
4
|
+
|
|
5
|
+
module Stoplight
|
|
6
|
+
module Wiring
|
|
7
|
+
# Constructs a fully-wired Light instance from validated configuration.
|
|
8
|
+
#
|
|
9
|
+
# LightBuilder is the final assembly step in the Light creation pipeline.
|
|
10
|
+
# It receives validated config and dependencies from ConfigurationPipeline
|
|
11
|
+
# and wires together all infrastructure components (data stores, trackers,
|
|
12
|
+
# strategies) needed for a functioning circuit breaker.
|
|
13
|
+
#
|
|
14
|
+
# LightBuilder maintains a global registry (MEMORY_REGISTRY) that ensures
|
|
15
|
+
# the same Memory data store config object always produces the same
|
|
16
|
+
# data store instance:
|
|
17
|
+
#
|
|
18
|
+
# data_store = Stoplight::DataStore::Memory.new
|
|
19
|
+
# light1 = Stoplight("foo", data_store: data_store)
|
|
20
|
+
# light2 = Stoplight("bar", data_store: data_store)
|
|
21
|
+
# # light1 and light2 share the same underlying memory store
|
|
22
|
+
#
|
|
23
|
+
# light3 = Stoplight("baz", data_store: Stoplight::DataStore::Memory.new)
|
|
24
|
+
# # light3 has its own independent store
|
|
25
|
+
#
|
|
26
|
+
# This singleton behavior is keyed by config object identity (object_id),
|
|
27
|
+
# not by value equality.
|
|
28
|
+
#
|
|
29
|
+
# @api private
|
|
30
|
+
class LightBuilder
|
|
31
|
+
FAILOVER_DATA_STORE_CONFIG = Stoplight::DataStore::Memory.new
|
|
32
|
+
private_constant :FAILOVER_DATA_STORE_CONFIG
|
|
33
|
+
|
|
34
|
+
MEMORY_REGISTRY = Concurrent::Map.new
|
|
35
|
+
private_constant :MEMORY_REGISTRY
|
|
36
|
+
|
|
37
|
+
def initialize(config:, factory:)
|
|
38
|
+
@clock = Infrastructure::SystemClock.new
|
|
39
|
+
@config = config
|
|
40
|
+
@name = T.must(config.name)
|
|
41
|
+
@cool_off_time = config.cool_off_time
|
|
42
|
+
|
|
43
|
+
@data_store_config = config.data_store
|
|
44
|
+
@error_notifier = config.error_notifier
|
|
45
|
+
@factory = factory
|
|
46
|
+
@notifiers = config.notifiers
|
|
47
|
+
@traffic_recovery = config.traffic_recovery
|
|
48
|
+
@traffic_control = config.traffic_control
|
|
49
|
+
|
|
50
|
+
@error_tracking_policy = Domain::ErrorTrackingPolicy.new(
|
|
51
|
+
tracked: config.tracked_errors,
|
|
52
|
+
skipped: config.skipped_errors
|
|
53
|
+
)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def build
|
|
57
|
+
Stoplight::Domain::Light.new(
|
|
58
|
+
@name,
|
|
59
|
+
state_store:,
|
|
60
|
+
green_run_strategy:,
|
|
61
|
+
yellow_run_strategy:,
|
|
62
|
+
red_run_strategy:,
|
|
63
|
+
factory:
|
|
64
|
+
)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
attr_reader :data_store_config
|
|
70
|
+
attr_reader :error_notifier
|
|
71
|
+
attr_reader :factory
|
|
72
|
+
attr_reader :clock
|
|
73
|
+
attr_reader :traffic_control
|
|
74
|
+
attr_reader :traffic_recovery
|
|
75
|
+
attr_reader :config
|
|
76
|
+
|
|
77
|
+
def state_store = Stoplight::Infrastructure::Storage::CompatibilityState.new(config:, data_store:)
|
|
78
|
+
|
|
79
|
+
# @return [<Stoplight::Notifier::Base>]
|
|
80
|
+
def notifiers
|
|
81
|
+
Array(@notifiers).map do |notifier|
|
|
82
|
+
Infrastructure::Notifier::FailSafe.new(notifier:, error_notifier:)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def redis_recovery_lock_store
|
|
87
|
+
Infrastructure::Redis::DataStore::RecoveryLockStore.new(
|
|
88
|
+
redis:,
|
|
89
|
+
lock_timeout: config.cool_off_time_in_milliseconds,
|
|
90
|
+
scripting:
|
|
91
|
+
)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def scripting = Infrastructure::Redis::DataStore::Scripting.new(redis:)
|
|
95
|
+
|
|
96
|
+
def memory_recovery_lock_store
|
|
97
|
+
Infrastructure::Memory::DataStore::RecoveryLockStore.new
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def failover_data_store
|
|
101
|
+
create_data_store(FAILOVER_DATA_STORE_CONFIG)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def data_store
|
|
105
|
+
create_data_store(data_store_config)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def metrics_store
|
|
109
|
+
Stoplight::Infrastructure::Storage::CompatibilityMetrics.new(config:, data_store:)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def recovery_lock_store
|
|
113
|
+
Stoplight::Infrastructure::Storage::CompatibilityRecoveryLock.new(config:, data_store:)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def request_tracker
|
|
117
|
+
Domain::Tracker::Request.new(traffic_control:, notifiers:, config:, metrics_store:, state_store:)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def recovery_probe_tracker
|
|
121
|
+
Domain::Tracker::RecoveryProbe.new(
|
|
122
|
+
traffic_recovery:,
|
|
123
|
+
notifiers:,
|
|
124
|
+
config:,
|
|
125
|
+
metrics_store: recovery_metrics_store,
|
|
126
|
+
state_store:
|
|
127
|
+
)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def recovery_metrics_store
|
|
131
|
+
Stoplight::Infrastructure::Storage::CompatibilityRecoveryMetrics.new(config:, data_store:)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def green_run_strategy
|
|
135
|
+
Domain::Strategies::GreenRunStrategy.new(
|
|
136
|
+
error_tracking_policy: @error_tracking_policy,
|
|
137
|
+
request_tracker:
|
|
138
|
+
)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def yellow_run_strategy
|
|
142
|
+
Domain::Strategies::YellowRunStrategy.new(
|
|
143
|
+
name: @name,
|
|
144
|
+
error_tracking_policy: @error_tracking_policy,
|
|
145
|
+
notifiers:,
|
|
146
|
+
request_tracker: recovery_probe_tracker,
|
|
147
|
+
red_run_strategy:,
|
|
148
|
+
state_store:,
|
|
149
|
+
metrics_store:,
|
|
150
|
+
recovery_lock_store:,
|
|
151
|
+
config: @config
|
|
152
|
+
)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def red_run_strategy
|
|
156
|
+
Domain::Strategies::RedRunStrategy.new(name: @name, cool_off_time: @cool_off_time)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def create_data_store(data_store_config)
|
|
160
|
+
case data_store_config
|
|
161
|
+
when Stoplight::DataStore::Memory
|
|
162
|
+
memory_registry.compute_if_absent(data_store_config.object_id) do
|
|
163
|
+
Infrastructure::Memory::DataStore.new(
|
|
164
|
+
recovery_lock_store: memory_recovery_lock_store,
|
|
165
|
+
clock:
|
|
166
|
+
)
|
|
167
|
+
end
|
|
168
|
+
when Stoplight::DataStore::Redis
|
|
169
|
+
Infrastructure::FailSafe::DataStore.new(
|
|
170
|
+
data_store: Stoplight::Infrastructure::Redis::DataStore.new(
|
|
171
|
+
clock:,
|
|
172
|
+
redis: data_store_config.redis,
|
|
173
|
+
warn_on_clock_skew: data_store_config.warn_on_clock_skew,
|
|
174
|
+
recovery_lock_store: redis_recovery_lock_store,
|
|
175
|
+
scripting:
|
|
176
|
+
),
|
|
177
|
+
error_notifier:,
|
|
178
|
+
failover_data_store:,
|
|
179
|
+
circuit_breaker: Stoplight.system_light("data_store:fail_safe:redis")
|
|
180
|
+
)
|
|
181
|
+
else
|
|
182
|
+
raise NoMatchingPatternError, data_store_config
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def redis
|
|
187
|
+
case data_store_config
|
|
188
|
+
when DataStore::Redis
|
|
189
|
+
data_store_config.redis
|
|
190
|
+
else
|
|
191
|
+
raise TypeError, "Expected Stoplight::DataStore::Redis, got #{data_store_config.class}"
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def memory_registry = MEMORY_REGISTRY
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Stoplight
|
|
4
|
+
module Wiring
|
|
5
|
+
class LightFactory
|
|
6
|
+
TrafficControlDsl = ->(value) {
|
|
7
|
+
case value
|
|
8
|
+
in _ if value.respond_to?(:stop_traffic?) # TODO: can be removed in 6.0
|
|
9
|
+
value
|
|
10
|
+
in :consecutive_errors
|
|
11
|
+
Domain::TrafficControl::ConsecutiveErrors.new
|
|
12
|
+
in :error_rate
|
|
13
|
+
Domain::TrafficControl::ErrorRate.new
|
|
14
|
+
in {error_rate: error_rate_settings}
|
|
15
|
+
Domain::TrafficControl::ErrorRate.new(**error_rate_settings)
|
|
16
|
+
else
|
|
17
|
+
raise Stoplight::Error::ConfigurationError, <<~ERROR
|
|
18
|
+
unsupported traffic_control strategy provided (`#{value}`). Supported options:
|
|
19
|
+
* :consecutive_errors
|
|
20
|
+
* :error_rate
|
|
21
|
+
ERROR
|
|
22
|
+
end
|
|
23
|
+
}
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Stoplight
|
|
4
|
+
module Wiring
|
|
5
|
+
class LightFactory
|
|
6
|
+
TrafficRecoveryDsl = ->(value) {
|
|
7
|
+
case value
|
|
8
|
+
in _ if value.respond_to?(:determine_color) # TODO: remove in 6.0
|
|
9
|
+
value
|
|
10
|
+
in :consecutive_successes
|
|
11
|
+
Domain::TrafficRecovery::ConsecutiveSuccesses.new
|
|
12
|
+
else
|
|
13
|
+
raise Error::ConfigurationError, <<~ERROR
|
|
14
|
+
unsupported traffic_recovery strategy provided (`#{value}`). Supported options:
|
|
15
|
+
* :consecutive_successes
|
|
16
|
+
ERROR
|
|
17
|
+
end
|
|
18
|
+
}
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -13,34 +13,42 @@ module Stoplight
|
|
|
13
13
|
# @see Stoplight::Domain::LightFactory
|
|
14
14
|
# @see Stoplight()
|
|
15
15
|
# @api private
|
|
16
|
-
|
|
17
|
-
class LightFactory
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
# Contains config, data_store, notifiers, strategies, etc.
|
|
21
|
-
# @return [Stoplight::Wiring::Container]
|
|
22
|
-
protected attr_reader :container
|
|
23
|
-
|
|
24
|
-
# @param container [Stoplight::Wiring::Container]
|
|
25
|
-
def initialize(container)
|
|
26
|
-
@container = container
|
|
16
|
+
#
|
|
17
|
+
class LightFactory
|
|
18
|
+
def initialize(config:)
|
|
19
|
+
@config = config
|
|
27
20
|
end
|
|
28
21
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
self.class.new(
|
|
22
|
+
def with(
|
|
23
|
+
name: T.undefined,
|
|
24
|
+
cool_off_time: T.undefined,
|
|
25
|
+
threshold: T.undefined,
|
|
26
|
+
recovery_threshold: T.undefined,
|
|
27
|
+
window_size: T.undefined,
|
|
28
|
+
tracked_errors: T.undefined,
|
|
29
|
+
skipped_errors: T.undefined,
|
|
30
|
+
data_store: T.undefined,
|
|
31
|
+
error_notifier: T.undefined,
|
|
32
|
+
notifiers: T.undefined,
|
|
33
|
+
traffic_control: T.undefined,
|
|
34
|
+
traffic_recovery: T.undefined
|
|
35
|
+
)
|
|
36
|
+
self.class.new(
|
|
37
|
+
config: ConfigurationDsl.new(
|
|
38
|
+
name:,
|
|
39
|
+
cool_off_time:,
|
|
40
|
+
threshold:,
|
|
41
|
+
recovery_threshold:,
|
|
42
|
+
window_size:,
|
|
43
|
+
tracked_errors:,
|
|
44
|
+
skipped_errors:,
|
|
45
|
+
traffic_control:,
|
|
46
|
+
traffic_recovery:,
|
|
47
|
+
error_notifier:,
|
|
48
|
+
data_store:,
|
|
49
|
+
notifiers:
|
|
50
|
+
).configure!(config)
|
|
51
|
+
)
|
|
44
52
|
end
|
|
45
53
|
|
|
46
54
|
# Builds a fully-configured Light instance.
|
|
@@ -60,129 +68,60 @@ module Stoplight
|
|
|
60
68
|
# light.run { api_call }
|
|
61
69
|
|
|
62
70
|
def build
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
Stoplight::Domain::Light.new(
|
|
66
|
-
container.resolve(:config),
|
|
67
|
-
data_store: container.resolve(:data_store),
|
|
68
|
-
green_run_strategy: container.resolve(:green_run_strategy),
|
|
69
|
-
yellow_run_strategy: container.resolve(:yellow_run_strategy),
|
|
70
|
-
red_run_strategy: container.resolve(:red_run_strategy),
|
|
71
|
-
factory: self
|
|
72
|
-
)
|
|
71
|
+
light_builder(config:).build
|
|
73
72
|
end
|
|
74
73
|
|
|
75
74
|
def ==(other)
|
|
76
|
-
other.is_a?(self.class) && other.
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
private def extract_config_settings(settings)
|
|
80
|
-
settings.slice(*container.resolve(:config).members)
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
private def extract_dependency_settings(settings)
|
|
84
|
-
settings.slice(*container.keys)
|
|
75
|
+
other.is_a?(self.class) && other.config == config
|
|
85
76
|
end
|
|
86
77
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
78
|
+
alias_method :eql?, :==
|
|
79
|
+
|
|
80
|
+
def build_with(
|
|
81
|
+
name: T.undefined,
|
|
82
|
+
cool_off_time: T.undefined,
|
|
83
|
+
threshold: T.undefined,
|
|
84
|
+
recovery_threshold: T.undefined,
|
|
85
|
+
window_size: T.undefined,
|
|
86
|
+
tracked_errors: T.undefined,
|
|
87
|
+
skipped_errors: T.undefined,
|
|
88
|
+
data_store: T.undefined,
|
|
89
|
+
error_notifier: T.undefined,
|
|
90
|
+
notifiers: T.undefined,
|
|
91
|
+
traffic_control: T.undefined,
|
|
92
|
+
traffic_recovery: T.undefined
|
|
93
|
+
)
|
|
94
|
+
with(
|
|
95
|
+
name:,
|
|
96
|
+
cool_off_time:,
|
|
97
|
+
threshold:,
|
|
98
|
+
recovery_threshold:,
|
|
99
|
+
window_size:,
|
|
100
|
+
tracked_errors:,
|
|
101
|
+
skipped_errors:,
|
|
102
|
+
data_store:,
|
|
103
|
+
error_notifier:,
|
|
104
|
+
notifiers:,
|
|
105
|
+
traffic_control:,
|
|
106
|
+
traffic_recovery:
|
|
107
|
+
).build
|
|
93
108
|
end
|
|
94
109
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
transform_config_settings!(transformed_settings)
|
|
98
|
-
transform_dependencies_settings!(transformed_settings)
|
|
99
|
-
end
|
|
110
|
+
def hash
|
|
111
|
+
[self.class, config].hash
|
|
100
112
|
end
|
|
101
113
|
|
|
102
|
-
|
|
103
|
-
if settings.key?(:tracked_errors)
|
|
104
|
-
settings[:tracked_errors] = normalize_array(settings[:tracked_errors])
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
if settings.key?(:skipped_errors)
|
|
108
|
-
settings[:skipped_errors] = normalize_array(settings[:skipped_errors])
|
|
109
|
-
end
|
|
114
|
+
protected
|
|
110
115
|
|
|
111
|
-
|
|
112
|
-
settings[:cool_off_time] = normalize_cool_off_time(settings[:cool_off_time])
|
|
113
|
-
end
|
|
114
|
-
end
|
|
116
|
+
attr_reader :config
|
|
115
117
|
|
|
116
|
-
private
|
|
117
|
-
if settings.key?(:traffic_control)
|
|
118
|
-
settings[:traffic_control] = apply_traffic_control_dsl(settings[:traffic_control])
|
|
119
|
-
end
|
|
118
|
+
private
|
|
120
119
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
end
|
|
120
|
+
def light_builder(config:)
|
|
121
|
+
LightBuilder.new(config:, factory: light_factory)
|
|
124
122
|
end
|
|
125
123
|
|
|
126
|
-
|
|
127
|
-
private def normalize_cool_off_time(value) = value.to_i
|
|
128
|
-
|
|
129
|
-
private def apply_traffic_control_dsl(traffic_control)
|
|
130
|
-
case traffic_control
|
|
131
|
-
in Domain::TrafficControl::Base
|
|
132
|
-
traffic_control
|
|
133
|
-
in :consecutive_errors
|
|
134
|
-
Domain::TrafficControl::ConsecutiveErrors.new
|
|
135
|
-
in :error_rate
|
|
136
|
-
Domain::TrafficControl::ErrorRate.new
|
|
137
|
-
in {error_rate: error_rate_settings}
|
|
138
|
-
Domain::TrafficControl::ErrorRate.new(**error_rate_settings)
|
|
139
|
-
else
|
|
140
|
-
raise Domain::Error::ConfigurationError, <<~ERROR
|
|
141
|
-
unsupported traffic_control strategy provided (`#{traffic_control}`). Supported options:
|
|
142
|
-
* :consecutive_errors
|
|
143
|
-
* :error_rate
|
|
144
|
-
ERROR
|
|
145
|
-
end
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
def apply_traffic_recovery_dsl(traffic_recovery)
|
|
149
|
-
case traffic_recovery
|
|
150
|
-
in Domain::TrafficRecovery::Base
|
|
151
|
-
traffic_recovery
|
|
152
|
-
in :consecutive_successes
|
|
153
|
-
Domain::TrafficRecovery::ConsecutiveSuccesses.new
|
|
154
|
-
else
|
|
155
|
-
raise Domain::Error::ConfigurationError, <<~ERROR
|
|
156
|
-
unsupported traffic_recovery strategy provided (`#{traffic_recovery}`). Supported options:
|
|
157
|
-
* :consecutive_successes
|
|
158
|
-
ERROR
|
|
159
|
-
end
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
private def validate!
|
|
163
|
-
validate_traffic_control!(container.resolve(:traffic_control), container.resolve(:config))
|
|
164
|
-
validate_traffic_recovery!(container.resolve(:traffic_recovery), container.resolve(:config))
|
|
165
|
-
end
|
|
166
|
-
|
|
167
|
-
private def validate_traffic_control!(traffic_control, config)
|
|
168
|
-
traffic_control.check_compatibility(config).then do |compatibility_result|
|
|
169
|
-
if compatibility_result.incompatible?
|
|
170
|
-
raise Domain::Error::ConfigurationError.new(
|
|
171
|
-
"#{traffic_control.class.name} strategy is incompatible with the Stoplight configuration: #{compatibility_result.error_messages}"
|
|
172
|
-
)
|
|
173
|
-
end
|
|
174
|
-
end
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
private def validate_traffic_recovery!(traffic_recovery, config)
|
|
178
|
-
traffic_recovery.check_compatibility(config).then do |compatibility_result|
|
|
179
|
-
if compatibility_result.incompatible?
|
|
180
|
-
raise Domain::Error::ConfigurationError.new(
|
|
181
|
-
"#{traffic_recovery.class.name} strategy is incompatible with the Stoplight configuration: #{compatibility_result.error_messages}"
|
|
182
|
-
)
|
|
183
|
-
end
|
|
184
|
-
end
|
|
185
|
-
end
|
|
124
|
+
def light_factory = self
|
|
186
125
|
end
|
|
187
126
|
end
|
|
188
127
|
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Stoplight
|
|
4
|
+
module Wiring
|
|
5
|
+
module Memory
|
|
6
|
+
# In-memory storage backend for single-process deployments.
|
|
7
|
+
#
|
|
8
|
+
# All storage components use thread-safe in-memory data structures.
|
|
9
|
+
# State is not shared across processes and is lost on restart.
|
|
10
|
+
#
|
|
11
|
+
# Memory backend is also used as the fallback layer for Redis backend
|
|
12
|
+
# when Redis is unavailable.
|
|
13
|
+
#
|
|
14
|
+
# @example
|
|
15
|
+
# backend = Memory::Backend.new(clock: SystemClock.new, config:)
|
|
16
|
+
# backend.state_store #=> Memory::Storage::State
|
|
17
|
+
#
|
|
18
|
+
# @api private
|
|
19
|
+
class Backend < DataStoreBackend
|
|
20
|
+
def initialize(clock:, config:)
|
|
21
|
+
@clock = clock
|
|
22
|
+
@config = config
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def state_store
|
|
26
|
+
@state_store ||= Infrastructure::Memory::Storage::State.new(
|
|
27
|
+
clock: @clock,
|
|
28
|
+
cool_off_time: @config.cool_off_time
|
|
29
|
+
)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def recovery_lock_store
|
|
33
|
+
@recovery_lock_store ||= Infrastructure::Memory::Storage::RecoveryLock.new
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def recovery_metrics_store
|
|
37
|
+
@recovery_metrics_store ||= Infrastructure::Memory::Storage::RecoveryMetrics.new(
|
|
38
|
+
clock: @clock
|
|
39
|
+
)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def windowed_metrics_store
|
|
43
|
+
@windowed_metrics_store ||= Infrastructure::Memory::Storage::WindowMetrics.new(
|
|
44
|
+
window_size: T.must(@config.window_size),
|
|
45
|
+
clock: @clock
|
|
46
|
+
)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def unbounded_metrics_store
|
|
50
|
+
@unbounded_metrics_store ||= Infrastructure::Memory::Storage::UnboundedMetrics.new(
|
|
51
|
+
clock: @clock
|
|
52
|
+
)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|