breaker_machines 0.1.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 +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +1894 -0
- data/lib/breaker_machines/circuit/callbacks.rb +132 -0
- data/lib/breaker_machines/circuit/configuration.rb +73 -0
- data/lib/breaker_machines/circuit/execution.rb +211 -0
- data/lib/breaker_machines/circuit/introspection.rb +77 -0
- data/lib/breaker_machines/circuit/state_management.rb +105 -0
- data/lib/breaker_machines/circuit.rb +14 -0
- data/lib/breaker_machines/console.rb +345 -0
- data/lib/breaker_machines/dsl.rb +274 -0
- data/lib/breaker_machines/errors.rb +30 -0
- data/lib/breaker_machines/registry.rb +99 -0
- data/lib/breaker_machines/storage/base.rb +47 -0
- data/lib/breaker_machines/storage/bucket_memory.rb +163 -0
- data/lib/breaker_machines/storage/memory.rb +127 -0
- data/lib/breaker_machines/storage/null.rb +45 -0
- data/lib/breaker_machines/storage.rb +8 -0
- data/lib/breaker_machines/version.rb +5 -0
- data/lib/breaker_machines.rb +82 -0
- data/sig/README.md +74 -0
- data/sig/all.rbs +25 -0
- data/sig/breaker_machines/circuit.rbs +154 -0
- data/sig/breaker_machines/console.rbs +32 -0
- data/sig/breaker_machines/dsl.rbs +50 -0
- data/sig/breaker_machines/errors.rbs +24 -0
- data/sig/breaker_machines/interfaces.rbs +46 -0
- data/sig/breaker_machines/registry.rbs +30 -0
- data/sig/breaker_machines/storage.rbs +65 -0
- data/sig/breaker_machines/types.rbs +97 -0
- data/sig/breaker_machines.rbs +30 -0
- data/sig/manifest.yaml +5 -0
- metadata +167 -0
@@ -0,0 +1,154 @@
|
|
1
|
+
module BreakerMachines
|
2
|
+
class Circuit
|
3
|
+
include StateManagement
|
4
|
+
include Configuration
|
5
|
+
include Execution
|
6
|
+
include Introspection
|
7
|
+
include Callbacks
|
8
|
+
|
9
|
+
# Instance variables from Configuration module
|
10
|
+
@name: String
|
11
|
+
@config: Hash[Symbol, untyped]
|
12
|
+
@storage: _StorageBackend?
|
13
|
+
@metrics: _MetricsRecorder?
|
14
|
+
@opened_at: Concurrent::AtomicReference[Float?]
|
15
|
+
@half_open_attempts: Concurrent::AtomicFixnum
|
16
|
+
@half_open_successes: Concurrent::AtomicFixnum
|
17
|
+
@mutex: Concurrent::ReentrantReadWriteLock
|
18
|
+
@last_failure_at: Concurrent::AtomicReference[Float?]
|
19
|
+
@last_error: Concurrent::AtomicReference[StandardError?]
|
20
|
+
|
21
|
+
# State machine status (from StateManagement)
|
22
|
+
attr_reader status: (:open | :closed | :half_open)
|
23
|
+
end
|
24
|
+
|
25
|
+
module StateManagement
|
26
|
+
interface _StateManagementState
|
27
|
+
def status: () -> (:open | :closed | :half_open)
|
28
|
+
def status=: (:open | :closed | :half_open value) -> void
|
29
|
+
def status_name: () -> (:open | :closed | :half_open)
|
30
|
+
def open?: () -> bool
|
31
|
+
def closed?: () -> bool
|
32
|
+
def half_open?: () -> bool
|
33
|
+
def trip: () -> bool
|
34
|
+
def attempt_recovery: () -> bool
|
35
|
+
def reset: () -> bool
|
36
|
+
def force_open: () -> bool
|
37
|
+
def force_close: () -> bool
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.included: (singleton(Circuit) base) -> void
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def on_circuit_open: () -> void
|
45
|
+
def on_circuit_close: () -> void
|
46
|
+
def on_circuit_half_open: () -> void
|
47
|
+
def restore_status_from_storage: () -> void
|
48
|
+
def reset_timeout_elapsed?: () -> bool
|
49
|
+
def monotonic_time: () -> Float
|
50
|
+
end
|
51
|
+
|
52
|
+
module Configuration
|
53
|
+
extend ActiveSupport::Concern
|
54
|
+
|
55
|
+
interface _ConfigurationMethods
|
56
|
+
def name: () -> String
|
57
|
+
def config: () -> Hash[Symbol, untyped]
|
58
|
+
def opened_at: () -> Concurrent::AtomicReference[Float?]
|
59
|
+
end
|
60
|
+
|
61
|
+
type storage_type = Storage::Base | Storage::Memory | Storage::BucketMemory | Storage::Null
|
62
|
+
type metrics_type = untyped
|
63
|
+
type callback_type = Proc | nil
|
64
|
+
type fallback_type = Proc | Array[Proc | untyped] | untyped
|
65
|
+
|
66
|
+
type circuit_config = {
|
67
|
+
failure_threshold: Integer,
|
68
|
+
failure_window: Integer,
|
69
|
+
success_threshold: Integer,
|
70
|
+
timeout: Integer?,
|
71
|
+
reset_timeout: Integer,
|
72
|
+
reset_timeout_jitter: Float,
|
73
|
+
half_open_calls: Integer,
|
74
|
+
storage: storage_type?,
|
75
|
+
metrics: metrics_type?,
|
76
|
+
fallback: fallback_type?,
|
77
|
+
on_open: callback_type,
|
78
|
+
on_close: callback_type,
|
79
|
+
on_half_open: callback_type,
|
80
|
+
on_reject: callback_type,
|
81
|
+
exceptions: Array[Class],
|
82
|
+
owner: untyped
|
83
|
+
}
|
84
|
+
|
85
|
+
def initialize: (String name, ?circuit_config options) -> void
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def default_config: () -> circuit_config
|
90
|
+
def create_default_storage: () -> storage_type
|
91
|
+
end
|
92
|
+
|
93
|
+
module Execution
|
94
|
+
def call: [T] () { () -> T } -> untyped
|
95
|
+
def wrap: [T] () { () -> T } -> untyped
|
96
|
+
|
97
|
+
private
|
98
|
+
|
99
|
+
def handle_open_status: () { () -> untyped } -> untyped
|
100
|
+
def handle_half_open_status: () { () -> untyped } -> untyped
|
101
|
+
def handle_closed_status: () { () -> untyped } -> untyped
|
102
|
+
def execute_call: () { () -> untyped } -> untyped
|
103
|
+
def reject_call: () -> untyped
|
104
|
+
def handle_success: () -> void
|
105
|
+
def handle_failure: () -> void
|
106
|
+
def failure_threshold_exceeded?: () -> bool
|
107
|
+
def success_threshold_reached?: () -> bool
|
108
|
+
def record_success: (Float duration) -> void
|
109
|
+
def record_failure: (Float duration, ?StandardError? error) -> void
|
110
|
+
end
|
111
|
+
|
112
|
+
module Introspection
|
113
|
+
type stats_hash = {
|
114
|
+
state: (:open | :closed | :half_open),
|
115
|
+
failure_count: Integer,
|
116
|
+
success_count: Integer,
|
117
|
+
last_failure_at: Float?,
|
118
|
+
opened_at: Float?,
|
119
|
+
half_open_attempts: Integer,
|
120
|
+
half_open_successes: Integer
|
121
|
+
}
|
122
|
+
|
123
|
+
type error_info = {
|
124
|
+
class: String,
|
125
|
+
message: String,
|
126
|
+
occurred_at: Float
|
127
|
+
}
|
128
|
+
|
129
|
+
type circuit_hash = {
|
130
|
+
name: String,
|
131
|
+
state: (:open | :closed | :half_open),
|
132
|
+
stats: stats_hash,
|
133
|
+
config: Hash[Symbol, untyped],
|
134
|
+
event_log: Array[untyped],
|
135
|
+
last_error: error_info?
|
136
|
+
}
|
137
|
+
|
138
|
+
def stats: () -> stats_hash
|
139
|
+
def configuration: () -> Hash[Symbol, untyped]
|
140
|
+
def event_log: (?limit: Integer) -> Array[untyped]?
|
141
|
+
def last_error: () -> StandardError?
|
142
|
+
def to_h: () -> circuit_hash
|
143
|
+
def summary: () -> String
|
144
|
+
def last_error_info: () -> error_info?
|
145
|
+
end
|
146
|
+
|
147
|
+
module Callbacks
|
148
|
+
private
|
149
|
+
|
150
|
+
def invoke_callback: (Symbol callback_name) -> void
|
151
|
+
def invoke_fallback: (StandardError error) -> untyped
|
152
|
+
def invoke_single_fallback: (Proc | untyped fallback, StandardError error) -> untyped
|
153
|
+
end
|
154
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module BreakerMachines
|
2
|
+
class Console
|
3
|
+
@running: bool
|
4
|
+
|
5
|
+
def self.start: () -> void
|
6
|
+
|
7
|
+
def initialize: () -> void
|
8
|
+
def run: () -> void
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def print_header: () -> void
|
13
|
+
def print_help: () -> void
|
14
|
+
def print_prompt: () -> void
|
15
|
+
def process_command: (String command) -> void
|
16
|
+
|
17
|
+
# Command methods
|
18
|
+
def list_circuits: () -> void
|
19
|
+
def show_stats: () -> void
|
20
|
+
def show_circuit: (String? name) -> void
|
21
|
+
def show_events: (String? name, Integer limit) -> void
|
22
|
+
def reset_circuit: (String? name) -> void
|
23
|
+
def force_open_circuit: (String? name) -> void
|
24
|
+
def force_close_circuit: (String? name) -> void
|
25
|
+
def generate_report: () -> void
|
26
|
+
def cleanup_registry: () -> void
|
27
|
+
|
28
|
+
# Utility methods
|
29
|
+
def colorize_state: (Symbol state) -> String
|
30
|
+
def colorize_event_type: (Symbol type) -> String
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module BreakerMachines
|
2
|
+
module DSL
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
@instance_registries: Concurrent::Map[Class, Concurrent::Array[WeakRef[untyped]]]
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
@circuits: Hash[Symbol, Hash[Symbol, untyped]]
|
9
|
+
|
10
|
+
def instance_registry: () -> Concurrent::Array[WeakRef[untyped]]
|
11
|
+
def cleanup_instance_registry: () -> void
|
12
|
+
def circuit: (Symbol name) ?{ (CircuitBuilder) -> void } -> Hash[Symbol, untyped]
|
13
|
+
def circuits: () -> Hash[Symbol, Hash[Symbol, untyped]]
|
14
|
+
def circuit_definitions: () -> Hash[Symbol, Hash[Symbol, untyped]]
|
15
|
+
def reset_all_circuits: () -> void
|
16
|
+
def circuit_stats: () -> Hash[Symbol, { total: Integer, by_state: Hash[Symbol, Integer] }]
|
17
|
+
end
|
18
|
+
|
19
|
+
def circuit: (Symbol name) -> Circuit
|
20
|
+
def circuit_instances: () -> Hash[Symbol, Circuit]
|
21
|
+
def circuits_summary: () -> Hash[Symbol, String]
|
22
|
+
def circuits_report: () -> Hash[Symbol, untyped]
|
23
|
+
def reset_all_circuits: () -> void
|
24
|
+
|
25
|
+
class CircuitBuilder
|
26
|
+
attr_reader config: Hash[Symbol, untyped]
|
27
|
+
|
28
|
+
def initialize: () -> void
|
29
|
+
|
30
|
+
# Configuration methods
|
31
|
+
def threshold: (?failures: Integer?, ?within: Integer, ?successes: Integer?) -> void
|
32
|
+
def reset_after: (Integer duration, ?jitter: Float?) -> void
|
33
|
+
def timeout: (Integer duration) -> void
|
34
|
+
def half_open_requests: (Integer count) -> void
|
35
|
+
def storage: ((:memory | :bucket_memory | :redis | Class | Storage::Base) backend, **untyped) -> void
|
36
|
+
def metrics: (?untyped recorder) ?{ () -> void } -> void
|
37
|
+
def fallback: (?untyped value) ?{ (StandardError) -> untyped } -> void
|
38
|
+
def on_open: () { () -> void } -> void
|
39
|
+
def on_close: () { () -> void } -> void
|
40
|
+
def on_half_open: () { () -> void } -> void
|
41
|
+
def on_reject: () { () -> void } -> void
|
42
|
+
def notify: (Symbol service, ?String? url, ?events: Array[Symbol], **untyped options) -> void
|
43
|
+
def handle: (*Class exceptions) -> void
|
44
|
+
|
45
|
+
# Advanced features
|
46
|
+
def backends: (Array[untyped] list) -> void
|
47
|
+
def parallel_calls: (Integer count, ?timeout: Integer?) -> void
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module BreakerMachines
|
2
|
+
class Error < StandardError
|
3
|
+
end
|
4
|
+
|
5
|
+
class CircuitOpenError < Error
|
6
|
+
attr_reader circuit_name: String
|
7
|
+
attr_reader opened_at: Float?
|
8
|
+
|
9
|
+
def initialize: (String circuit_name, ?Float? opened_at) -> void
|
10
|
+
end
|
11
|
+
|
12
|
+
class CircuitTimeoutError < Error
|
13
|
+
attr_reader circuit_name: String
|
14
|
+
attr_reader timeout: Numeric
|
15
|
+
|
16
|
+
def initialize: (String circuit_name, Numeric timeout) -> void
|
17
|
+
end
|
18
|
+
|
19
|
+
class ConfigurationError < Error
|
20
|
+
end
|
21
|
+
|
22
|
+
class StorageError < Error
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module BreakerMachines
|
2
|
+
# Interface for objects that can record metrics
|
3
|
+
interface _MetricsRecorder
|
4
|
+
def record_success: (String circuit_name, Float duration) -> void
|
5
|
+
def record_failure: (String circuit_name, Float duration) -> void
|
6
|
+
def record_rejection: (String circuit_name) -> void
|
7
|
+
end
|
8
|
+
|
9
|
+
# Interface for storage backends
|
10
|
+
interface _StorageBackend
|
11
|
+
def get_status: (String circuit_name) -> status_record?
|
12
|
+
def set_status: (String circuit_name, circuit_state status, ?Float? opened_at) -> void
|
13
|
+
def record_success: (String circuit_name, Float duration) -> void
|
14
|
+
def record_failure: (String circuit_name, Float duration) -> void
|
15
|
+
def success_count: (String circuit_name, Integer window_seconds) -> Integer
|
16
|
+
def failure_count: (String circuit_name, Integer window_seconds) -> Integer
|
17
|
+
def clear: (String circuit_name) -> void
|
18
|
+
def clear_all: () -> void
|
19
|
+
end
|
20
|
+
|
21
|
+
# Interface for advanced storage backends with event logging
|
22
|
+
interface _AdvancedStorageBackend
|
23
|
+
def record_success: (String circuit_name, ?Float? duration) -> void
|
24
|
+
def record_failure: (String circuit_name, ?Float? duration) -> void
|
25
|
+
def success_count: (String circuit_name, ?Integer? window) -> Integer
|
26
|
+
def failure_count: (String circuit_name, ?Integer? window) -> Integer
|
27
|
+
def get_status: (String circuit_name) -> Hash[Symbol, untyped]?
|
28
|
+
def set_status: (String circuit_name, circuit_state status, ?Float? opened_at) -> void
|
29
|
+
def clear: (String circuit_name) -> void
|
30
|
+
def record_event_with_details: (String circuit_name, event_type event_type, Float duration, ?Hash[Symbol, untyped] details) -> void
|
31
|
+
def event_log: (String circuit_name, ?Integer limit) -> Array[event_record]
|
32
|
+
end
|
33
|
+
|
34
|
+
# Interface for circuit-like objects
|
35
|
+
interface _CircuitLike
|
36
|
+
def name: () -> String
|
37
|
+
def call: () { () -> untyped } -> untyped
|
38
|
+
def wrap: () { () -> untyped } -> untyped
|
39
|
+
def status_name: () -> circuit_state
|
40
|
+
def open?: () -> bool
|
41
|
+
def closed?: () -> bool
|
42
|
+
def half_open?: () -> bool
|
43
|
+
def reset: () -> bool
|
44
|
+
def stats: () -> Hash[Symbol, untyped]
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module BreakerMachines
|
2
|
+
class Registry
|
3
|
+
include Singleton
|
4
|
+
|
5
|
+
@circuits: Concurrent::Map[Integer, WeakRef[Circuit]]
|
6
|
+
@mutex: Mutex
|
7
|
+
@registration_count: Integer
|
8
|
+
@cleanup_interval: Integer
|
9
|
+
|
10
|
+
def initialize: () -> void
|
11
|
+
|
12
|
+
# Circuit management
|
13
|
+
def register: (Circuit circuit) -> void
|
14
|
+
def unregister: (Circuit circuit) -> void
|
15
|
+
def all_circuits: () -> Array[Circuit]
|
16
|
+
def find_by_name: (Symbol name) -> Array[Circuit]
|
17
|
+
|
18
|
+
# Reporting
|
19
|
+
def stats_summary: () -> { total: Integer, by_state: Hash[Symbol, Integer], by_name: Hash[Symbol, Integer] }
|
20
|
+
def detailed_report: () -> Array[Hash[Symbol, untyped]]
|
21
|
+
|
22
|
+
# Maintenance
|
23
|
+
def clear: () -> void
|
24
|
+
def cleanup_dead_references: () -> void
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def cleanup_dead_references_unsafe: () -> void
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module BreakerMachines
|
2
|
+
module Storage
|
3
|
+
class Base
|
4
|
+
@options: Hash[Symbol, untyped]
|
5
|
+
|
6
|
+
def initialize: (**untyped options) -> void
|
7
|
+
|
8
|
+
# Status management
|
9
|
+
def get_status: (String circuit_name) -> { status: (:open | :closed | :half_open), opened_at: Float? }?
|
10
|
+
def set_status: (String circuit_name, (:open | :closed | :half_open) status, ?Float? opened_at) -> void
|
11
|
+
|
12
|
+
# Metrics tracking
|
13
|
+
def record_success: (String circuit_name, Float duration) -> void
|
14
|
+
def record_failure: (String circuit_name, Float duration) -> void
|
15
|
+
def success_count: (String circuit_name, Integer window_seconds) -> Integer
|
16
|
+
def failure_count: (String circuit_name, Integer window_seconds) -> Integer
|
17
|
+
|
18
|
+
# Cleanup
|
19
|
+
def clear: (String circuit_name) -> void
|
20
|
+
def clear_all: () -> void
|
21
|
+
end
|
22
|
+
|
23
|
+
class Memory < Base
|
24
|
+
@circuits: Concurrent::Map[String, untyped]
|
25
|
+
@events: Concurrent::Map[String, Concurrent::Array[untyped]]
|
26
|
+
@event_logs: Concurrent::Map[String, Concurrent::Array[untyped]]
|
27
|
+
@max_events: Integer
|
28
|
+
|
29
|
+
def initialize: (**untyped options) -> void
|
30
|
+
def record_event_with_details: (String circuit_name, (:success | :failure | :state_change) type, Float duration, ?error: StandardError?, ?new_state: (:open | :closed | :half_open)?) -> void
|
31
|
+
def event_log: (String circuit_name, Integer limit) -> Array[event_record]
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def record_event: (String circuit_name, (:success | :failure) type, Float duration) -> void
|
36
|
+
def count_events: (String circuit_name, (:success | :failure) type, Integer window_seconds) -> Integer
|
37
|
+
def monotonic_time: () -> Float
|
38
|
+
end
|
39
|
+
|
40
|
+
class BucketMemory < Base
|
41
|
+
@buckets: Concurrent::Map[String, untyped]
|
42
|
+
@bucket_duration: Integer
|
43
|
+
@bucket_count: Integer
|
44
|
+
@lock: Concurrent::ReentrantReadWriteLock
|
45
|
+
@last_cleanup: Concurrent::AtomicReference[Float]
|
46
|
+
@cleanup_interval: Integer
|
47
|
+
|
48
|
+
def record_event_with_details: (String circuit_name, (:success | :failure | :state_change) event_type, Float duration, ?Hash[Symbol, untyped] details) -> void
|
49
|
+
def event_log: (String circuit_name, ?Integer limit) -> Array[event_record]
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def circuit_buckets: (String circuit_name) -> Hash[Symbol, untyped]
|
54
|
+
def current_bucket_index: () -> Integer
|
55
|
+
def bucket_indices_for_window: (Integer window_seconds) -> Array[Integer]
|
56
|
+
def cleanup_old_buckets: (Hash[Symbol, untyped] buckets) -> void
|
57
|
+
def maybe_cleanup_all_buckets: () -> void
|
58
|
+
end
|
59
|
+
|
60
|
+
class Null < Base
|
61
|
+
def record_event_with_details: (String circuit_name, Symbol event_type, Float duration, ?Hash[Symbol, untyped] metadata) -> void
|
62
|
+
def event_log: (String circuit_name, ?Integer limit) -> Array[untyped]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# Common type aliases used throughout BreakerMachines
|
2
|
+
|
3
|
+
# External dependencies type declarations not included in their gems
|
4
|
+
module Concurrent
|
5
|
+
class AtomicReference[T]
|
6
|
+
def initialize: (?T initial_value) -> void
|
7
|
+
def value: () -> T
|
8
|
+
def value=: (T value) -> T
|
9
|
+
def get: () -> T
|
10
|
+
def set: (T value) -> T
|
11
|
+
end
|
12
|
+
|
13
|
+
class AtomicFixnum
|
14
|
+
def initialize: (?Integer initial_value) -> void
|
15
|
+
def value: () -> Integer
|
16
|
+
def value=: (Integer value) -> Integer
|
17
|
+
def increment: (?Integer delta) -> Integer
|
18
|
+
def decrement: (?Integer delta) -> Integer
|
19
|
+
end
|
20
|
+
|
21
|
+
class ReentrantReadWriteLock
|
22
|
+
def initialize: () -> void
|
23
|
+
def with_read_lock: [T] () { () -> T } -> T
|
24
|
+
def with_write_lock: [T] () { () -> T } -> T
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class WeakRef[T]
|
29
|
+
def initialize: (T object) -> void
|
30
|
+
def weakref_alive?: () -> bool
|
31
|
+
def __getobj__: () -> T
|
32
|
+
end
|
33
|
+
|
34
|
+
module Zeitwerk
|
35
|
+
class Loader
|
36
|
+
def push_dir: (String path) -> void
|
37
|
+
def setup: () -> void
|
38
|
+
def eager_load: () -> void
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
module BreakerMachines
|
43
|
+
# Circuit states
|
44
|
+
type circuit_state = :open | :closed | :half_open
|
45
|
+
|
46
|
+
# Event types
|
47
|
+
type event_type = :success | :failure | :state_change | :rejection
|
48
|
+
|
49
|
+
# Callback names
|
50
|
+
type callback_name = :on_open | :on_close | :on_half_open | :on_reject
|
51
|
+
|
52
|
+
# Storage backend symbols
|
53
|
+
type storage_backend = :memory | :bucket_memory | :null | :redis
|
54
|
+
|
55
|
+
# Generic callback proc
|
56
|
+
type callback_proc = Proc | nil
|
57
|
+
|
58
|
+
# Fallback can be a proc, array of procs/values, or any static value
|
59
|
+
type fallback_value = Proc | Array[Proc | untyped] | untyped
|
60
|
+
|
61
|
+
# Options hash for circuits
|
62
|
+
type circuit_options = {
|
63
|
+
failure_threshold: Integer?,
|
64
|
+
failure_window: Integer?,
|
65
|
+
success_threshold: Integer?,
|
66
|
+
timeout: Integer?,
|
67
|
+
reset_timeout: Integer?,
|
68
|
+
reset_timeout_jitter: Float?,
|
69
|
+
half_open_calls: Integer?,
|
70
|
+
storage: (Storage::Base | storage_backend | Class)?,
|
71
|
+
metrics: untyped,
|
72
|
+
fallback: fallback_value?,
|
73
|
+
on_open: callback_proc,
|
74
|
+
on_close: callback_proc,
|
75
|
+
on_half_open: callback_proc,
|
76
|
+
on_reject: callback_proc,
|
77
|
+
exceptions: Array[Class]?,
|
78
|
+
owner: untyped
|
79
|
+
}
|
80
|
+
|
81
|
+
# Event record structure
|
82
|
+
type event_record = {
|
83
|
+
timestamp: Float,
|
84
|
+
type: event_type,
|
85
|
+
duration: Float,
|
86
|
+
duration_ms: Float?,
|
87
|
+
error_class: String?,
|
88
|
+
new_state: circuit_state?,
|
89
|
+
details: Hash[Symbol, untyped]?
|
90
|
+
}
|
91
|
+
|
92
|
+
# Status record from storage
|
93
|
+
type status_record = {
|
94
|
+
status: circuit_state,
|
95
|
+
opened_at: Float?
|
96
|
+
}
|
97
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module BreakerMachines
|
2
|
+
VERSION: String
|
3
|
+
|
4
|
+
# Global configuration
|
5
|
+
extend ActiveSupport::Configurable
|
6
|
+
|
7
|
+
# Configuration accessors
|
8
|
+
self.@config: untyped
|
9
|
+
def self.config: () -> ActiveSupport::Configurable::Configuration
|
10
|
+
def self.default_storage: () -> (:memory | :bucket_memory | :null | untyped)
|
11
|
+
def self.default_storage=: (:memory | :bucket_memory | :null | untyped value) -> void
|
12
|
+
def self.default_timeout: () -> Integer?
|
13
|
+
def self.default_timeout=: (Integer? value) -> void
|
14
|
+
def self.default_reset_timeout: () -> Integer
|
15
|
+
def self.default_reset_timeout=: (Integer value) -> void
|
16
|
+
def self.default_failure_threshold: () -> Integer
|
17
|
+
def self.default_failure_threshold=: (Integer value) -> void
|
18
|
+
def self.log_events: () -> bool
|
19
|
+
def self.log_events=: (bool value) -> void
|
20
|
+
|
21
|
+
# Class methods
|
22
|
+
def self.configure: () { (untyped config) -> void } -> void
|
23
|
+
def self.setup_notifications: () -> void
|
24
|
+
def self.logger: () -> ActiveSupport::Logger?
|
25
|
+
def self.logger=: (ActiveSupport::Logger? logger) -> void
|
26
|
+
def self.instrument: (String event, ?Hash[Symbol, untyped] payload) -> void
|
27
|
+
def self.console: () -> void
|
28
|
+
def self.registry: () -> Registry
|
29
|
+
def self.loader: () -> Zeitwerk::Loader
|
30
|
+
end
|