Class: Semian::AdaptiveCircuitBreaker
- Inherits:
-
Object
- Object
- Semian::AdaptiveCircuitBreaker
- Includes:
- CircuitBreakerBehaviour
- Defined in:
- lib/semian/adaptive_circuit_breaker.rb
Overview
Adaptive Circuit Breaker that uses PID controller for dynamic rejection
Direct Known Subclasses
Instance Attribute Summary collapse
-
#pid_controller ⇒ Object
readonly
Returns the value of attribute pid_controller.
-
#pid_controller_thread ⇒ Object
readonly
Returns the value of attribute pid_controller_thread.
-
#sliding_interval ⇒ Object
readonly
Returns the value of attribute sliding_interval.
-
#stopped ⇒ Object
readonly
Returns the value of attribute stopped.
-
#update_thread ⇒ Object
readonly
Returns the value of attribute update_thread.
Attributes included from CircuitBreakerBehaviour
#exceptions, #last_error, #name
Instance Method Summary collapse
- #acquire(resource = nil, scope: nil, adapter: nil, &block) ⇒ Object
- #closed? ⇒ Boolean
- #destroy ⇒ Object
-
#half_open? ⇒ Boolean
Compatibility with ProtectedResource - Adaptive circuit breaker does not have a half open state.
- #in_use? ⇒ Boolean
-
#initialize(name:, exceptions:, kp:, ki:, kd:, window_size:, initial_error_rate:, implementation:, sliding_interval:, dead_zone_ratio:, ideal_error_rate_estimator_cap_value:, integral_upper_cap:, integral_lower_cap:) ⇒ AdaptiveCircuitBreaker
constructor
A new instance of AdaptiveCircuitBreaker.
- #mark_failed(error, scope: nil, adapter: nil) ⇒ Object
- #mark_rejected(scope: nil, adapter: nil) ⇒ Object
- #mark_success(scope: nil, adapter: nil) ⇒ Object
- #metrics ⇒ Object
- #open? ⇒ Boolean
- #pid_controller_update ⇒ Object
- #request_allowed? ⇒ Boolean
- #reset(scope: nil, adapter: nil) ⇒ Object
- #stop ⇒ Object
Methods included from CircuitBreakerBehaviour
Constructor Details
#initialize(name:, exceptions:, kp:, ki:, kd:, window_size:, initial_error_rate:, implementation:, sliding_interval:, dead_zone_ratio:, ideal_error_rate_estimator_cap_value:, integral_upper_cap:, integral_lower_cap:) ⇒ AdaptiveCircuitBreaker
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/semian/adaptive_circuit_breaker.rb', line 15 def initialize(name:, exceptions:, kp:, ki:, kd:, window_size:, initial_error_rate:, implementation:, sliding_interval:, dead_zone_ratio:, ideal_error_rate_estimator_cap_value:, integral_upper_cap:, integral_lower_cap:) initialize_behaviour(name: name) @exceptions = exceptions @stopped = false @pid_controller = implementation::PIDController.new( kp: kp, ki: ki, kd: kd, window_size: window_size, implementation: implementation, sliding_interval: sliding_interval, initial_error_rate: initial_error_rate, dead_zone_ratio: dead_zone_ratio, ideal_error_rate_estimator_cap_value: ideal_error_rate_estimator_cap_value, integral_upper_cap: integral_upper_cap, integral_lower_cap: integral_lower_cap, ) @pid_controller_thread = PIDControllerThread.instance.register_resource(self) end |
Instance Attribute Details
#pid_controller ⇒ Object (readonly)
Returns the value of attribute pid_controller.
11 12 13 |
# File 'lib/semian/adaptive_circuit_breaker.rb', line 11 def pid_controller @pid_controller end |
#pid_controller_thread ⇒ Object (readonly)
Returns the value of attribute pid_controller_thread.
11 12 13 |
# File 'lib/semian/adaptive_circuit_breaker.rb', line 11 def pid_controller_thread @pid_controller_thread end |
#sliding_interval ⇒ Object (readonly)
Returns the value of attribute sliding_interval.
11 12 13 |
# File 'lib/semian/adaptive_circuit_breaker.rb', line 11 def sliding_interval @sliding_interval end |
#stopped ⇒ Object (readonly)
Returns the value of attribute stopped.
11 12 13 |
# File 'lib/semian/adaptive_circuit_breaker.rb', line 11 def stopped @stopped end |
#update_thread ⇒ Object (readonly)
Returns the value of attribute update_thread.
11 12 13 |
# File 'lib/semian/adaptive_circuit_breaker.rb', line 11 def update_thread @update_thread end |
Instance Method Details
#acquire(resource = nil, scope: nil, adapter: nil, &block) ⇒ Object
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/semian/adaptive_circuit_breaker.rb', line 40 def acquire(resource = nil, scope: nil, adapter: nil, &block) unless request_allowed? mark_rejected(scope:, adapter:) raise OpenCircuitError, "Rejected by adaptive circuit breaker" end result = nil begin result = block.call rescue *@exceptions => error if !error.respond_to?(:marks_semian_circuits?) || error.marks_semian_circuits? mark_failed(error, scope:, adapter:) end raise error else mark_success(scope:, adapter:) end result end |
#closed? ⇒ Boolean
83 84 85 |
# File 'lib/semian/adaptive_circuit_breaker.rb', line 83 def closed? @pid_controller.rejection_rate == 0 end |
#destroy ⇒ Object
69 70 71 72 73 |
# File 'lib/semian/adaptive_circuit_breaker.rb', line 69 def destroy @stopped = true PIDControllerThread.instance.unregister_resource(self) @pid_controller.reset end |
#half_open? ⇒ Boolean
Compatibility with ProtectedResource - Adaptive circuit breaker does not have a half open state
88 89 90 |
# File 'lib/semian/adaptive_circuit_breaker.rb', line 88 def half_open? !open? && !closed? end |
#in_use? ⇒ Boolean
109 110 111 |
# File 'lib/semian/adaptive_circuit_breaker.rb', line 109 def in_use? true end |
#mark_failed(error, scope: nil, adapter: nil) ⇒ Object
92 93 94 95 |
# File 'lib/semian/adaptive_circuit_breaker.rb', line 92 def mark_failed(error, scope: nil, adapter: nil) @last_error = error @pid_controller.record_request(:error) end |
#mark_rejected(scope: nil, adapter: nil) ⇒ Object
101 102 103 |
# File 'lib/semian/adaptive_circuit_breaker.rb', line 101 def mark_rejected(scope: nil, adapter: nil) @pid_controller.record_request(:rejected) end |
#mark_success(scope: nil, adapter: nil) ⇒ Object
97 98 99 |
# File 'lib/semian/adaptive_circuit_breaker.rb', line 97 def mark_success(scope: nil, adapter: nil) @pid_controller.record_request(:success) end |
#metrics ⇒ Object
75 76 77 |
# File 'lib/semian/adaptive_circuit_breaker.rb', line 75 def metrics @pid_controller.metrics end |
#open? ⇒ Boolean
79 80 81 |
# File 'lib/semian/adaptive_circuit_breaker.rb', line 79 def open? @pid_controller.rejection_rate == 1 end |
#pid_controller_update ⇒ Object
113 114 115 116 |
# File 'lib/semian/adaptive_circuit_breaker.rb', line 113 def pid_controller_update @pid_controller.update notify_metrics_update(@pid_controller.metrics(full: false)) end |
#request_allowed? ⇒ Boolean
105 106 107 |
# File 'lib/semian/adaptive_circuit_breaker.rb', line 105 def request_allowed? !@pid_controller.should_reject? end |
#reset(scope: nil, adapter: nil) ⇒ Object
60 61 62 63 |
# File 'lib/semian/adaptive_circuit_breaker.rb', line 60 def reset(scope: nil, adapter: nil) @last_error = nil @pid_controller.reset end |
#stop ⇒ Object
65 66 67 |
# File 'lib/semian/adaptive_circuit_breaker.rb', line 65 def stop destroy end |