breaker_machines 0.9.2-arm64-darwin

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.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +184 -0
  4. data/ext/breaker_machines_native/extconf.rb +3 -0
  5. data/lib/breaker_machines/async_circuit.rb +47 -0
  6. data/lib/breaker_machines/async_support.rb +104 -0
  7. data/lib/breaker_machines/cascading_circuit.rb +177 -0
  8. data/lib/breaker_machines/circuit/async_state_management.rb +71 -0
  9. data/lib/breaker_machines/circuit/base.rb +59 -0
  10. data/lib/breaker_machines/circuit/callbacks.rb +135 -0
  11. data/lib/breaker_machines/circuit/configuration.rb +67 -0
  12. data/lib/breaker_machines/circuit/coordinated_state_management.rb +117 -0
  13. data/lib/breaker_machines/circuit/execution.rb +231 -0
  14. data/lib/breaker_machines/circuit/hedged_execution.rb +115 -0
  15. data/lib/breaker_machines/circuit/introspection.rb +93 -0
  16. data/lib/breaker_machines/circuit/native.rb +127 -0
  17. data/lib/breaker_machines/circuit/state_callbacks.rb +72 -0
  18. data/lib/breaker_machines/circuit/state_management.rb +59 -0
  19. data/lib/breaker_machines/circuit.rb +8 -0
  20. data/lib/breaker_machines/circuit_group.rb +153 -0
  21. data/lib/breaker_machines/console.rb +345 -0
  22. data/lib/breaker_machines/coordinated_circuit.rb +10 -0
  23. data/lib/breaker_machines/dsl/cascading_circuit_builder.rb +20 -0
  24. data/lib/breaker_machines/dsl/circuit_builder.rb +209 -0
  25. data/lib/breaker_machines/dsl/hedged_builder.rb +21 -0
  26. data/lib/breaker_machines/dsl/parallel_fallback_wrapper.rb +20 -0
  27. data/lib/breaker_machines/dsl.rb +283 -0
  28. data/lib/breaker_machines/errors.rb +71 -0
  29. data/lib/breaker_machines/hedged_async_support.rb +88 -0
  30. data/lib/breaker_machines/native_extension.rb +81 -0
  31. data/lib/breaker_machines/native_speedup.rb +10 -0
  32. data/lib/breaker_machines/registry.rb +243 -0
  33. data/lib/breaker_machines/storage/backend_state.rb +69 -0
  34. data/lib/breaker_machines/storage/base.rb +52 -0
  35. data/lib/breaker_machines/storage/bucket_memory.rb +176 -0
  36. data/lib/breaker_machines/storage/cache.rb +169 -0
  37. data/lib/breaker_machines/storage/fallback_chain.rb +294 -0
  38. data/lib/breaker_machines/storage/memory.rb +140 -0
  39. data/lib/breaker_machines/storage/native.rb +93 -0
  40. data/lib/breaker_machines/storage/null.rb +54 -0
  41. data/lib/breaker_machines/storage.rb +8 -0
  42. data/lib/breaker_machines/types.rb +41 -0
  43. data/lib/breaker_machines/version.rb +5 -0
  44. data/lib/breaker_machines.rb +200 -0
  45. data/lib/breaker_machines_native/breaker_machines_native.bundle +0 -0
  46. data/sig/README.md +74 -0
  47. data/sig/all.rbs +25 -0
  48. data/sig/breaker_machines/circuit.rbs +154 -0
  49. data/sig/breaker_machines/console.rbs +32 -0
  50. data/sig/breaker_machines/dsl.rbs +50 -0
  51. data/sig/breaker_machines/errors.rbs +24 -0
  52. data/sig/breaker_machines/interfaces.rbs +46 -0
  53. data/sig/breaker_machines/registry.rbs +30 -0
  54. data/sig/breaker_machines/storage.rbs +65 -0
  55. data/sig/breaker_machines/types.rbs +97 -0
  56. data/sig/breaker_machines.rbs +42 -0
  57. data/sig/manifest.yaml +5 -0
  58. metadata +227 -0
@@ -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,42 @@
1
+ module BreakerMachines
2
+ VERSION: String
3
+
4
+ class Configuration
5
+ attr_accessor default_storage: (:memory | :bucket_memory | :null | untyped)
6
+ attr_accessor default_timeout: Integer?
7
+ attr_accessor default_reset_timeout: Integer
8
+ attr_accessor default_failure_threshold: Integer
9
+ attr_accessor log_events: bool
10
+ attr_accessor fiber_safe: bool
11
+
12
+ def initialize: () -> void
13
+ end
14
+
15
+ # Global configuration
16
+ self.@config: Configuration?
17
+ def self.config: () -> Configuration
18
+
19
+ # Class methods
20
+ def self.configure: () { (Configuration config) -> void } -> void
21
+
22
+ # Delegated config accessors for backward compatibility
23
+ def self.default_storage: () -> (:memory | :bucket_memory | :null | untyped)
24
+ def self.default_storage=: ((:memory | :bucket_memory | :null | untyped) value) -> void
25
+ def self.default_timeout: () -> Integer?
26
+ def self.default_timeout=: (Integer? value) -> void
27
+ def self.default_reset_timeout: () -> Integer
28
+ def self.default_reset_timeout=: (Integer value) -> void
29
+ def self.default_failure_threshold: () -> Integer
30
+ def self.default_failure_threshold=: (Integer value) -> void
31
+ def self.log_events: () -> bool
32
+ def self.log_events=: (bool value) -> void
33
+ def self.fiber_safe: () -> bool
34
+ def self.fiber_safe=: (bool value) -> void
35
+ def self.setup_notifications: () -> void
36
+ def self.logger: () -> ActiveSupport::Logger?
37
+ def self.logger=: (ActiveSupport::Logger? logger) -> void
38
+ def self.instrument: (String event, ?Hash[Symbol, untyped] payload) -> void
39
+ def self.console: () -> void
40
+ def self.registry: () -> Registry
41
+ def self.loader: () -> Zeitwerk::Loader
42
+ end
data/sig/manifest.yaml ADDED
@@ -0,0 +1,5 @@
1
+ dependencies:
2
+ - name: activesupport
3
+ - name: concurrent-ruby
4
+ - name: state_machines
5
+ - name: zeitwerk
metadata ADDED
@@ -0,0 +1,227 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: breaker_machines
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.2
5
+ platform: arm64-darwin
6
+ authors:
7
+ - Abdelkader Boudih
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2025-11-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '8.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '8.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: chrono_machines
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: concurrent-ruby
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.3'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: state_machines
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 0.100.4
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 0.100.4
69
+ - !ruby/object:Gem::Dependency
70
+ name: zeitwerk
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '2.7'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '2.7'
83
+ - !ruby/object:Gem::Dependency
84
+ name: minitest
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '5.16'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '5.16'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '13.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '13.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rake-compiler
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '1.3'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '1.3'
125
+ description: |
126
+ BreakerMachines is a production-ready circuit breaker implementation for Ruby that prevents
127
+ cascade failures in distributed systems. Built on the battle-tested state_machines gem, it
128
+ provides a clean DSL, thread-safe operations, multiple storage backends, and comprehensive
129
+ introspection tools. Unlike other solutions, BreakerMachines prioritizes safety by avoiding
130
+ dangerous forceful timeouts while supporting fallback chains, jitter, and event callbacks.
131
+ email:
132
+ - terminale@gmail.com
133
+ executables: []
134
+ extensions: []
135
+ extra_rdoc_files: []
136
+ files:
137
+ - LICENSE.txt
138
+ - README.md
139
+ - ext/breaker_machines_native/extconf.rb
140
+ - lib/breaker_machines.rb
141
+ - lib/breaker_machines/async_circuit.rb
142
+ - lib/breaker_machines/async_support.rb
143
+ - lib/breaker_machines/cascading_circuit.rb
144
+ - lib/breaker_machines/circuit.rb
145
+ - lib/breaker_machines/circuit/async_state_management.rb
146
+ - lib/breaker_machines/circuit/base.rb
147
+ - lib/breaker_machines/circuit/callbacks.rb
148
+ - lib/breaker_machines/circuit/configuration.rb
149
+ - lib/breaker_machines/circuit/coordinated_state_management.rb
150
+ - lib/breaker_machines/circuit/execution.rb
151
+ - lib/breaker_machines/circuit/hedged_execution.rb
152
+ - lib/breaker_machines/circuit/introspection.rb
153
+ - lib/breaker_machines/circuit/native.rb
154
+ - lib/breaker_machines/circuit/state_callbacks.rb
155
+ - lib/breaker_machines/circuit/state_management.rb
156
+ - lib/breaker_machines/circuit_group.rb
157
+ - lib/breaker_machines/console.rb
158
+ - lib/breaker_machines/coordinated_circuit.rb
159
+ - lib/breaker_machines/dsl.rb
160
+ - lib/breaker_machines/dsl/cascading_circuit_builder.rb
161
+ - lib/breaker_machines/dsl/circuit_builder.rb
162
+ - lib/breaker_machines/dsl/hedged_builder.rb
163
+ - lib/breaker_machines/dsl/parallel_fallback_wrapper.rb
164
+ - lib/breaker_machines/errors.rb
165
+ - lib/breaker_machines/hedged_async_support.rb
166
+ - lib/breaker_machines/native_extension.rb
167
+ - lib/breaker_machines/native_speedup.rb
168
+ - lib/breaker_machines/registry.rb
169
+ - lib/breaker_machines/storage.rb
170
+ - lib/breaker_machines/storage/backend_state.rb
171
+ - lib/breaker_machines/storage/base.rb
172
+ - lib/breaker_machines/storage/bucket_memory.rb
173
+ - lib/breaker_machines/storage/cache.rb
174
+ - lib/breaker_machines/storage/fallback_chain.rb
175
+ - lib/breaker_machines/storage/memory.rb
176
+ - lib/breaker_machines/storage/native.rb
177
+ - lib/breaker_machines/storage/null.rb
178
+ - lib/breaker_machines/types.rb
179
+ - lib/breaker_machines/version.rb
180
+ - lib/breaker_machines_native/breaker_machines_native.bundle
181
+ - sig/README.md
182
+ - sig/all.rbs
183
+ - sig/breaker_machines.rbs
184
+ - sig/breaker_machines/circuit.rbs
185
+ - sig/breaker_machines/console.rbs
186
+ - sig/breaker_machines/dsl.rbs
187
+ - sig/breaker_machines/errors.rbs
188
+ - sig/breaker_machines/interfaces.rbs
189
+ - sig/breaker_machines/registry.rbs
190
+ - sig/breaker_machines/storage.rbs
191
+ - sig/breaker_machines/types.rbs
192
+ - sig/manifest.yaml
193
+ homepage: https://github.com/seuros/breaker_machines
194
+ licenses:
195
+ - MIT
196
+ metadata:
197
+ homepage_uri: https://github.com/seuros/breaker_machines
198
+ source_code_uri: https://github.com/seuros/breaker_machines
199
+ bug_tracker_uri: https://github.com/seuros/breaker_machines/issues
200
+ documentation_uri: https://github.com/seuros/breaker_machines#readme
201
+ rubygems_mfa_required: 'true'
202
+ cargo_crate_name: breaker_machines_native
203
+ cargo_manifest_path: ext/breaker_machines_native/ffi/Cargo.toml
204
+ post_install_message:
205
+ rdoc_options: []
206
+ require_paths:
207
+ - lib
208
+ required_ruby_version: !ruby/object:Gem::Requirement
209
+ requirements:
210
+ - - ">="
211
+ - !ruby/object:Gem::Version
212
+ version: '3.4'
213
+ - - "<"
214
+ - !ruby/object:Gem::Version
215
+ version: 3.5.dev
216
+ required_rubygems_version: !ruby/object:Gem::Requirement
217
+ requirements:
218
+ - - ">="
219
+ - !ruby/object:Gem::Version
220
+ version: '0'
221
+ requirements: []
222
+ rubygems_version: 3.5.23
223
+ signing_key:
224
+ specification_version: 4
225
+ summary: Circuit breaker implementation for Ruby with a clean DSL and state_machines
226
+ under the hood
227
+ test_files: []