breaker_machines 0.4.0 → 0.6.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.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +25 -3
  3. data/ext/breaker_machines_native/Cargo.toml +8 -0
  4. data/ext/breaker_machines_native/core/Cargo.toml +18 -0
  5. data/ext/breaker_machines_native/core/examples/basic.rs +61 -0
  6. data/ext/breaker_machines_native/core/src/builder.rs +232 -0
  7. data/ext/breaker_machines_native/core/src/bulkhead.rs +223 -0
  8. data/ext/breaker_machines_native/core/src/callbacks.rs +58 -0
  9. data/ext/breaker_machines_native/core/src/circuit.rs +1156 -0
  10. data/ext/breaker_machines_native/core/src/classifier.rs +177 -0
  11. data/ext/breaker_machines_native/core/src/errors.rs +47 -0
  12. data/ext/breaker_machines_native/core/src/lib.rs +62 -0
  13. data/ext/breaker_machines_native/core/src/storage.rs +377 -0
  14. data/ext/breaker_machines_native/extconf.rb +40 -0
  15. data/ext/breaker_machines_native/ffi/Cargo.toml +16 -0
  16. data/ext/breaker_machines_native/ffi/src/lib.rs +218 -0
  17. data/ext/breaker_machines_native/target/debug/build/clang-sys-d961dfabd5f43fba/out/common.rs +355 -0
  18. data/ext/breaker_machines_native/target/debug/build/clang-sys-d961dfabd5f43fba/out/dynamic.rs +276 -0
  19. data/ext/breaker_machines_native/target/debug/build/clang-sys-d961dfabd5f43fba/out/macros.rs +49 -0
  20. data/ext/breaker_machines_native/target/debug/build/rb-sys-2bb7281aac8faec8/out/bindings-0.9.117-mri-arm64-darwin24-3.4.7.rs +8936 -0
  21. data/ext/breaker_machines_native/target/debug/build/rb-sys-54cb99ea6aeab8bc/out/bindings-0.9.117-mri-arm64-darwin24-3.4.7.rs +8936 -0
  22. data/ext/breaker_machines_native/target/debug/build/rb-sys-9e64a270c6421e93/out/bindings-0.9.117-mri-arm64-darwin24-3.4.7.rs +8936 -0
  23. data/ext/breaker_machines_native/target/debug/build/rb-sys-e627030114d3fc19/out/bindings-0.9.117-mri-arm64-darwin24-3.4.7.rs +8936 -0
  24. data/ext/breaker_machines_native/target/package/breaker-machines-0.1.0/Cargo.toml +48 -0
  25. data/ext/breaker_machines_native/target/package/breaker-machines-0.1.0/examples/basic.rs +61 -0
  26. data/ext/breaker_machines_native/target/package/breaker-machines-0.1.0/src/builder.rs +154 -0
  27. data/ext/breaker_machines_native/target/package/breaker-machines-0.1.0/src/callbacks.rs +55 -0
  28. data/ext/breaker_machines_native/target/package/breaker-machines-0.1.0/src/circuit.rs +607 -0
  29. data/ext/breaker_machines_native/target/package/breaker-machines-0.1.0/src/errors.rs +38 -0
  30. data/ext/breaker_machines_native/target/package/breaker-machines-0.1.0/src/lib.rs +58 -0
  31. data/ext/breaker_machines_native/target/package/breaker-machines-0.1.0/src/storage.rs +377 -0
  32. data/ext/breaker_machines_native/target/package/breaker-machines-0.2.0/Cargo.toml +48 -0
  33. data/ext/breaker_machines_native/target/package/breaker-machines-0.2.0/examples/basic.rs +61 -0
  34. data/ext/breaker_machines_native/target/package/breaker-machines-0.2.0/src/builder.rs +173 -0
  35. data/ext/breaker_machines_native/target/package/breaker-machines-0.2.0/src/callbacks.rs +55 -0
  36. data/ext/breaker_machines_native/target/package/breaker-machines-0.2.0/src/circuit.rs +855 -0
  37. data/ext/breaker_machines_native/target/package/breaker-machines-0.2.0/src/errors.rs +38 -0
  38. data/ext/breaker_machines_native/target/package/breaker-machines-0.2.0/src/lib.rs +58 -0
  39. data/ext/breaker_machines_native/target/package/breaker-machines-0.2.0/src/storage.rs +377 -0
  40. data/ext/breaker_machines_native/target/package/breaker-machines-0.5.0/Cargo.toml +48 -0
  41. data/ext/breaker_machines_native/target/package/breaker-machines-0.5.0/examples/basic.rs +61 -0
  42. data/ext/breaker_machines_native/target/package/breaker-machines-0.5.0/src/builder.rs +154 -0
  43. data/ext/breaker_machines_native/target/package/breaker-machines-0.5.0/src/callbacks.rs +55 -0
  44. data/ext/breaker_machines_native/target/package/breaker-machines-0.5.0/src/circuit.rs +607 -0
  45. data/ext/breaker_machines_native/target/package/breaker-machines-0.5.0/src/errors.rs +38 -0
  46. data/ext/breaker_machines_native/target/package/breaker-machines-0.5.0/src/lib.rs +58 -0
  47. data/ext/breaker_machines_native/target/package/breaker-machines-0.5.0/src/storage.rs +377 -0
  48. data/ext/breaker_machines_native/target/package/breaker-machines-0.6.0/Cargo.toml +48 -0
  49. data/ext/breaker_machines_native/target/package/breaker-machines-0.6.0/examples/basic.rs +61 -0
  50. data/ext/breaker_machines_native/target/package/breaker-machines-0.6.0/src/builder.rs +232 -0
  51. data/ext/breaker_machines_native/target/package/breaker-machines-0.6.0/src/bulkhead.rs +223 -0
  52. data/ext/breaker_machines_native/target/package/breaker-machines-0.6.0/src/callbacks.rs +58 -0
  53. data/ext/breaker_machines_native/target/package/breaker-machines-0.6.0/src/circuit.rs +1156 -0
  54. data/ext/breaker_machines_native/target/package/breaker-machines-0.6.0/src/classifier.rs +177 -0
  55. data/ext/breaker_machines_native/target/package/breaker-machines-0.6.0/src/errors.rs +47 -0
  56. data/ext/breaker_machines_native/target/package/breaker-machines-0.6.0/src/lib.rs +62 -0
  57. data/ext/breaker_machines_native/target/package/breaker-machines-0.6.0/src/storage.rs +377 -0
  58. data/ext/breaker_machines_native/target/release/build/clang-sys-ef8ad8b846ac8b75/out/common.rs +355 -0
  59. data/ext/breaker_machines_native/target/release/build/clang-sys-ef8ad8b846ac8b75/out/dynamic.rs +276 -0
  60. data/ext/breaker_machines_native/target/release/build/clang-sys-ef8ad8b846ac8b75/out/macros.rs +49 -0
  61. data/ext/breaker_machines_native/target/release/build/rb-sys-064bf9961dd17810/out/bindings-0.9.117-mri-arm64-darwin24-3.4.7.rs +8936 -0
  62. data/lib/breaker_machines/async_circuit.rb +47 -0
  63. data/lib/breaker_machines/async_support.rb +4 -3
  64. data/lib/breaker_machines/cascading_circuit.rb +5 -3
  65. data/lib/breaker_machines/circuit/async_state_management.rb +71 -0
  66. data/lib/breaker_machines/circuit/base.rb +59 -0
  67. data/lib/breaker_machines/circuit/callbacks.rb +7 -12
  68. data/lib/breaker_machines/circuit/configuration.rb +6 -26
  69. data/lib/breaker_machines/circuit/coordinated_state_management.rb +117 -0
  70. data/lib/breaker_machines/circuit/hedged_execution.rb +115 -0
  71. data/lib/breaker_machines/circuit/introspection.rb +1 -0
  72. data/lib/breaker_machines/circuit/native.rb +127 -0
  73. data/lib/breaker_machines/circuit/state_callbacks.rb +72 -0
  74. data/lib/breaker_machines/circuit/state_management.rb +14 -61
  75. data/lib/breaker_machines/circuit.rb +1 -7
  76. data/lib/breaker_machines/circuit_group.rb +153 -0
  77. data/lib/breaker_machines/coordinated_circuit.rb +10 -0
  78. data/lib/breaker_machines/dsl.rb +2 -2
  79. data/lib/breaker_machines/errors.rb +20 -0
  80. data/lib/breaker_machines/hedged_async_support.rb +29 -36
  81. data/lib/breaker_machines/native_extension.rb +36 -0
  82. data/lib/breaker_machines/native_speedup.rb +6 -0
  83. data/lib/breaker_machines/storage/bucket_memory.rb +4 -1
  84. data/lib/breaker_machines/storage/memory.rb +4 -1
  85. data/lib/breaker_machines/storage/native.rb +90 -0
  86. data/lib/breaker_machines/version.rb +1 -1
  87. data/lib/breaker_machines.rb +115 -11
  88. data/lib/breaker_machines_native/breaker_machines_native.bundle +0 -0
  89. data/sig/breaker_machines.rbs +20 -8
  90. metadata +107 -7
  91. data/lib/breaker_machines/hedged_execution.rb +0 -113
@@ -14,32 +14,95 @@ loader.ignore("#{__dir__}/breaker_machines/types.rb")
14
14
  loader.ignore("#{__dir__}/breaker_machines/console.rb")
15
15
  loader.ignore("#{__dir__}/breaker_machines/async_support.rb")
16
16
  loader.ignore("#{__dir__}/breaker_machines/hedged_async_support.rb")
17
+ loader.ignore("#{__dir__}/breaker_machines/circuit/async_state_management.rb")
18
+ loader.ignore("#{__dir__}/breaker_machines/native_speedup.rb")
19
+ loader.ignore("#{__dir__}/breaker_machines/native_extension.rb")
17
20
  loader.setup
18
21
 
19
22
  # BreakerMachines provides a thread-safe implementation of the Circuit Breaker pattern
20
23
  # for Ruby applications, helping to prevent cascading failures in distributed systems.
21
24
  module BreakerMachines
25
+ # Global configuration class for BreakerMachines
26
+ class Configuration
27
+ attr_accessor :default_storage,
28
+ :default_timeout,
29
+ :default_reset_timeout,
30
+ :default_failure_threshold,
31
+ :log_events,
32
+ :fiber_safe
33
+
34
+ def initialize
35
+ @default_storage = :bucket_memory
36
+ @default_timeout = nil
37
+ @default_reset_timeout = 60.seconds
38
+ @default_failure_threshold = 5
39
+ @log_events = true
40
+ @fiber_safe = false
41
+ end
42
+ end
43
+
22
44
  class << self
23
45
  def loader
24
46
  loader
25
47
  end
26
- end
27
-
28
- # Global configuration
29
- include ActiveSupport::Configurable
30
48
 
31
- config_accessor :default_storage, default: :bucket_memory
32
- config_accessor :default_timeout, default: nil
33
- config_accessor :default_reset_timeout, default: 60.seconds
34
- config_accessor :default_failure_threshold, default: 5
35
- config_accessor :log_events, default: true
36
- config_accessor :fiber_safe, default: false
49
+ def config
50
+ @config ||= Configuration.new
51
+ end
37
52
 
38
- class << self
39
53
  def configure
40
54
  yield config
41
55
  end
42
56
 
57
+ # Delegate config attributes to config object for backward compatibility
58
+ def default_storage
59
+ config.default_storage
60
+ end
61
+
62
+ def default_storage=(value)
63
+ config.default_storage = value
64
+ end
65
+
66
+ def default_timeout
67
+ config.default_timeout
68
+ end
69
+
70
+ def default_timeout=(value)
71
+ config.default_timeout = value
72
+ end
73
+
74
+ def default_reset_timeout
75
+ config.default_reset_timeout
76
+ end
77
+
78
+ def default_reset_timeout=(value)
79
+ config.default_reset_timeout = value
80
+ end
81
+
82
+ def default_failure_threshold
83
+ config.default_failure_threshold
84
+ end
85
+
86
+ def default_failure_threshold=(value)
87
+ config.default_failure_threshold = value
88
+ end
89
+
90
+ def log_events
91
+ config.log_events
92
+ end
93
+
94
+ def log_events=(value)
95
+ config.log_events = value
96
+ end
97
+
98
+ def fiber_safe
99
+ config.fiber_safe
100
+ end
101
+
102
+ def fiber_safe=(value)
103
+ config.fiber_safe = value
104
+ end
105
+
43
106
  def setup_notifications
44
107
  return unless config.log_events
45
108
 
@@ -64,12 +127,27 @@ module BreakerMachines
64
127
 
65
128
  attr_writer :logger
66
129
 
130
+ # Centralized logging helper
131
+ # @param level [Symbol] log level (:debug, :info, :warn, :error)
132
+ # @param message [String] message to log
133
+ def log(level, message)
134
+ return unless config.log_events && logger
135
+
136
+ logger.public_send(level, "[BreakerMachines] #{message}")
137
+ end
138
+
67
139
  def instrument(event, payload = {})
68
140
  return unless config.log_events
69
141
 
70
142
  ActiveSupport::Notifications.instrument("breaker_machines.#{event}", payload)
71
143
  end
72
144
 
145
+ # Check if native extension is available
146
+ # @return [Boolean] true if native extension loaded successfully
147
+ def native_available?
148
+ @native_available || false
149
+ end
150
+
73
151
  # Launch the interactive console
74
152
  def console
75
153
  require_relative 'breaker_machines/console'
@@ -81,6 +159,22 @@ module BreakerMachines
81
159
  Registry.instance
82
160
  end
83
161
 
162
+ # Register a circuit with the global registry
163
+ def register(circuit)
164
+ registry.register(circuit)
165
+ end
166
+
167
+ # Reset the registry and configurations (useful for testing)
168
+ def reset!
169
+ registry.clear
170
+ config.default_storage = :bucket_memory
171
+ config.default_timeout = nil
172
+ config.default_reset_timeout = 60.seconds
173
+ config.default_failure_threshold = 5
174
+ config.log_events = true
175
+ config.fiber_safe = false
176
+ end
177
+
84
178
  # Returns the current monotonic time in seconds.
85
179
  # Monotonic time is guaranteed to always increase and is not affected
86
180
  # by system clock adjustments, making it ideal for measuring durations.
@@ -94,3 +188,13 @@ module BreakerMachines
94
188
  # Set up notifications on first use
95
189
  setup_notifications if config.log_events
96
190
  end
191
+
192
+ # Load optional native speedup after core is loaded
193
+ # Opt-in with BREAKER_MACHINES_NATIVE=1 to enable native extensions
194
+ if ENV['BREAKER_MACHINES_NATIVE'] == '1'
195
+ begin
196
+ require_relative 'breaker_machines/native_speedup'
197
+ rescue LoadError
198
+ # Native gem not available, skip native support
199
+ end
200
+ end
@@ -1,14 +1,27 @@
1
1
  module BreakerMachines
2
2
  VERSION: String
3
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
+
4
15
  # Global configuration
5
- extend ActiveSupport::Configurable
16
+ self.@config: Configuration?
17
+ def self.config: () -> Configuration
18
+
19
+ # Class methods
20
+ def self.configure: () { (Configuration config) -> void } -> void
6
21
 
7
- # Configuration accessors
8
- self.@config: untyped
9
- def self.config: () -> ActiveSupport::Configurable::Configuration
22
+ # Delegated config accessors for backward compatibility
10
23
  def self.default_storage: () -> (:memory | :bucket_memory | :null | untyped)
11
- def self.default_storage=: (:memory | :bucket_memory | :null | untyped value) -> void
24
+ def self.default_storage=: ((:memory | :bucket_memory | :null | untyped) value) -> void
12
25
  def self.default_timeout: () -> Integer?
13
26
  def self.default_timeout=: (Integer? value) -> void
14
27
  def self.default_reset_timeout: () -> Integer
@@ -17,9 +30,8 @@ module BreakerMachines
17
30
  def self.default_failure_threshold=: (Integer value) -> void
18
31
  def self.log_events: () -> bool
19
32
  def self.log_events=: (bool value) -> void
20
-
21
- # Class methods
22
- def self.configure: () { (untyped config) -> void } -> void
33
+ def self.fiber_safe: () -> bool
34
+ def self.fiber_safe=: (bool value) -> void
23
35
  def self.setup_notifications: () -> void
24
36
  def self.logger: () -> ActiveSupport::Logger?
25
37
  def self.logger=: (ActiveSupport::Logger? logger) -> void
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: breaker_machines
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Abdelkader Boudih
@@ -15,14 +15,28 @@ dependencies:
15
15
  requirements:
16
16
  - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: '7.2'
18
+ version: '8.0'
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
- version: '7.2'
25
+ version: '8.0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: chrono_machines
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '0.2'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '0.2'
26
40
  - !ruby/object:Gem::Dependency
27
41
  name: concurrent-ruby
28
42
  requirement: !ruby/object:Gem::Requirement
@@ -43,14 +57,14 @@ dependencies:
43
57
  requirements:
44
58
  - - ">="
45
59
  - !ruby/object:Gem::Version
46
- version: 0.50.0
60
+ version: 0.100.4
47
61
  type: :runtime
48
62
  prerelease: false
49
63
  version_requirements: !ruby/object:Gem::Requirement
50
64
  requirements:
51
65
  - - ">="
52
66
  - !ruby/object:Gem::Version
53
- version: 0.50.0
67
+ version: 0.100.4
54
68
  - !ruby/object:Gem::Dependency
55
69
  name: zeitwerk
56
70
  requirement: !ruby/object:Gem::Requirement
@@ -93,6 +107,20 @@ dependencies:
93
107
  - - "~>"
94
108
  - !ruby/object:Gem::Version
95
109
  version: '13.0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: rb_sys
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '0.9'
117
+ type: :development
118
+ prerelease: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '0.9'
96
124
  description: |
97
125
  BreakerMachines is a production-ready circuit breaker implementation for Ruby that prevents
98
126
  cascade failures in distributed systems. Built on the battle-tested state_machines gem, it
@@ -102,21 +130,90 @@ description: |
102
130
  email:
103
131
  - terminale@gmail.com
104
132
  executables: []
105
- extensions: []
133
+ extensions:
134
+ - ext/breaker_machines_native/extconf.rb
106
135
  extra_rdoc_files: []
107
136
  files:
108
137
  - LICENSE.txt
109
138
  - README.md
139
+ - ext/breaker_machines_native/Cargo.toml
140
+ - ext/breaker_machines_native/core/Cargo.toml
141
+ - ext/breaker_machines_native/core/examples/basic.rs
142
+ - ext/breaker_machines_native/core/src/builder.rs
143
+ - ext/breaker_machines_native/core/src/bulkhead.rs
144
+ - ext/breaker_machines_native/core/src/callbacks.rs
145
+ - ext/breaker_machines_native/core/src/circuit.rs
146
+ - ext/breaker_machines_native/core/src/classifier.rs
147
+ - ext/breaker_machines_native/core/src/errors.rs
148
+ - ext/breaker_machines_native/core/src/lib.rs
149
+ - ext/breaker_machines_native/core/src/storage.rs
150
+ - ext/breaker_machines_native/extconf.rb
151
+ - ext/breaker_machines_native/ffi/Cargo.toml
152
+ - ext/breaker_machines_native/ffi/src/lib.rs
153
+ - ext/breaker_machines_native/target/debug/build/clang-sys-d961dfabd5f43fba/out/common.rs
154
+ - ext/breaker_machines_native/target/debug/build/clang-sys-d961dfabd5f43fba/out/dynamic.rs
155
+ - ext/breaker_machines_native/target/debug/build/clang-sys-d961dfabd5f43fba/out/macros.rs
156
+ - ext/breaker_machines_native/target/debug/build/rb-sys-2bb7281aac8faec8/out/bindings-0.9.117-mri-arm64-darwin24-3.4.7.rs
157
+ - ext/breaker_machines_native/target/debug/build/rb-sys-54cb99ea6aeab8bc/out/bindings-0.9.117-mri-arm64-darwin24-3.4.7.rs
158
+ - ext/breaker_machines_native/target/debug/build/rb-sys-9e64a270c6421e93/out/bindings-0.9.117-mri-arm64-darwin24-3.4.7.rs
159
+ - ext/breaker_machines_native/target/debug/build/rb-sys-e627030114d3fc19/out/bindings-0.9.117-mri-arm64-darwin24-3.4.7.rs
160
+ - ext/breaker_machines_native/target/package/breaker-machines-0.1.0/Cargo.toml
161
+ - ext/breaker_machines_native/target/package/breaker-machines-0.1.0/examples/basic.rs
162
+ - ext/breaker_machines_native/target/package/breaker-machines-0.1.0/src/builder.rs
163
+ - ext/breaker_machines_native/target/package/breaker-machines-0.1.0/src/callbacks.rs
164
+ - ext/breaker_machines_native/target/package/breaker-machines-0.1.0/src/circuit.rs
165
+ - ext/breaker_machines_native/target/package/breaker-machines-0.1.0/src/errors.rs
166
+ - ext/breaker_machines_native/target/package/breaker-machines-0.1.0/src/lib.rs
167
+ - ext/breaker_machines_native/target/package/breaker-machines-0.1.0/src/storage.rs
168
+ - ext/breaker_machines_native/target/package/breaker-machines-0.2.0/Cargo.toml
169
+ - ext/breaker_machines_native/target/package/breaker-machines-0.2.0/examples/basic.rs
170
+ - ext/breaker_machines_native/target/package/breaker-machines-0.2.0/src/builder.rs
171
+ - ext/breaker_machines_native/target/package/breaker-machines-0.2.0/src/callbacks.rs
172
+ - ext/breaker_machines_native/target/package/breaker-machines-0.2.0/src/circuit.rs
173
+ - ext/breaker_machines_native/target/package/breaker-machines-0.2.0/src/errors.rs
174
+ - ext/breaker_machines_native/target/package/breaker-machines-0.2.0/src/lib.rs
175
+ - ext/breaker_machines_native/target/package/breaker-machines-0.2.0/src/storage.rs
176
+ - ext/breaker_machines_native/target/package/breaker-machines-0.5.0/Cargo.toml
177
+ - ext/breaker_machines_native/target/package/breaker-machines-0.5.0/examples/basic.rs
178
+ - ext/breaker_machines_native/target/package/breaker-machines-0.5.0/src/builder.rs
179
+ - ext/breaker_machines_native/target/package/breaker-machines-0.5.0/src/callbacks.rs
180
+ - ext/breaker_machines_native/target/package/breaker-machines-0.5.0/src/circuit.rs
181
+ - ext/breaker_machines_native/target/package/breaker-machines-0.5.0/src/errors.rs
182
+ - ext/breaker_machines_native/target/package/breaker-machines-0.5.0/src/lib.rs
183
+ - ext/breaker_machines_native/target/package/breaker-machines-0.5.0/src/storage.rs
184
+ - ext/breaker_machines_native/target/package/breaker-machines-0.6.0/Cargo.toml
185
+ - ext/breaker_machines_native/target/package/breaker-machines-0.6.0/examples/basic.rs
186
+ - ext/breaker_machines_native/target/package/breaker-machines-0.6.0/src/builder.rs
187
+ - ext/breaker_machines_native/target/package/breaker-machines-0.6.0/src/bulkhead.rs
188
+ - ext/breaker_machines_native/target/package/breaker-machines-0.6.0/src/callbacks.rs
189
+ - ext/breaker_machines_native/target/package/breaker-machines-0.6.0/src/circuit.rs
190
+ - ext/breaker_machines_native/target/package/breaker-machines-0.6.0/src/classifier.rs
191
+ - ext/breaker_machines_native/target/package/breaker-machines-0.6.0/src/errors.rs
192
+ - ext/breaker_machines_native/target/package/breaker-machines-0.6.0/src/lib.rs
193
+ - ext/breaker_machines_native/target/package/breaker-machines-0.6.0/src/storage.rs
194
+ - ext/breaker_machines_native/target/release/build/clang-sys-ef8ad8b846ac8b75/out/common.rs
195
+ - ext/breaker_machines_native/target/release/build/clang-sys-ef8ad8b846ac8b75/out/dynamic.rs
196
+ - ext/breaker_machines_native/target/release/build/clang-sys-ef8ad8b846ac8b75/out/macros.rs
197
+ - ext/breaker_machines_native/target/release/build/rb-sys-064bf9961dd17810/out/bindings-0.9.117-mri-arm64-darwin24-3.4.7.rs
110
198
  - lib/breaker_machines.rb
199
+ - lib/breaker_machines/async_circuit.rb
111
200
  - lib/breaker_machines/async_support.rb
112
201
  - lib/breaker_machines/cascading_circuit.rb
113
202
  - lib/breaker_machines/circuit.rb
203
+ - lib/breaker_machines/circuit/async_state_management.rb
204
+ - lib/breaker_machines/circuit/base.rb
114
205
  - lib/breaker_machines/circuit/callbacks.rb
115
206
  - lib/breaker_machines/circuit/configuration.rb
207
+ - lib/breaker_machines/circuit/coordinated_state_management.rb
116
208
  - lib/breaker_machines/circuit/execution.rb
209
+ - lib/breaker_machines/circuit/hedged_execution.rb
117
210
  - lib/breaker_machines/circuit/introspection.rb
211
+ - lib/breaker_machines/circuit/native.rb
212
+ - lib/breaker_machines/circuit/state_callbacks.rb
118
213
  - lib/breaker_machines/circuit/state_management.rb
214
+ - lib/breaker_machines/circuit_group.rb
119
215
  - lib/breaker_machines/console.rb
216
+ - lib/breaker_machines/coordinated_circuit.rb
120
217
  - lib/breaker_machines/dsl.rb
121
218
  - lib/breaker_machines/dsl/cascading_circuit_builder.rb
122
219
  - lib/breaker_machines/dsl/circuit_builder.rb
@@ -124,7 +221,8 @@ files:
124
221
  - lib/breaker_machines/dsl/parallel_fallback_wrapper.rb
125
222
  - lib/breaker_machines/errors.rb
126
223
  - lib/breaker_machines/hedged_async_support.rb
127
- - lib/breaker_machines/hedged_execution.rb
224
+ - lib/breaker_machines/native_extension.rb
225
+ - lib/breaker_machines/native_speedup.rb
128
226
  - lib/breaker_machines/registry.rb
129
227
  - lib/breaker_machines/storage.rb
130
228
  - lib/breaker_machines/storage/backend_state.rb
@@ -133,9 +231,11 @@ files:
133
231
  - lib/breaker_machines/storage/cache.rb
134
232
  - lib/breaker_machines/storage/fallback_chain.rb
135
233
  - lib/breaker_machines/storage/memory.rb
234
+ - lib/breaker_machines/storage/native.rb
136
235
  - lib/breaker_machines/storage/null.rb
137
236
  - lib/breaker_machines/types.rb
138
237
  - lib/breaker_machines/version.rb
238
+ - lib/breaker_machines_native/breaker_machines_native.bundle
139
239
  - sig/README.md
140
240
  - sig/all.rbs
141
241
  - sig/breaker_machines.rbs
@@ -1,113 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'concurrent'
4
- require 'timeout'
5
-
6
- module BreakerMachines
7
- # HedgedExecution provides hedged request functionality for circuit breakers
8
- # Hedged requests improve latency by sending duplicate requests to multiple backends
9
- # and returning the first successful response
10
- module HedgedExecution
11
- extend ActiveSupport::Concern
12
-
13
- # Execute a hedged request pattern
14
- def execute_hedged(&)
15
- return execute_single_hedged(&) unless @config[:backends]&.any?
16
-
17
- execute_multi_backend_hedged
18
- end
19
-
20
- private
21
-
22
- # Execute hedged request with a single backend (original block)
23
- def execute_single_hedged(&block)
24
- return yield unless hedged_requests_enabled?
25
-
26
- max_requests = @config[:max_hedged_requests] || 2
27
- delay_ms = @config[:hedging_delay] || 50
28
-
29
- if @config[:fiber_safe]
30
- execute_hedged_async(Array.new(max_requests) { block }, delay_ms)
31
- else
32
- execute_hedged_sync(Array.new(max_requests) { block }, delay_ms)
33
- end
34
- end
35
-
36
- # Execute hedged requests across multiple backends
37
- def execute_multi_backend_hedged
38
- backends = @config[:backends]
39
- return backends.first.call if backends.size == 1
40
-
41
- if @config[:fiber_safe]
42
- execute_hedged_async(backends, @config[:hedging_delay] || 0)
43
- else
44
- execute_hedged_sync(backends, @config[:hedging_delay] || 0)
45
- end
46
- end
47
-
48
- # Synchronous hedged execution using threads
49
- def execute_hedged_sync(callables, delay_ms)
50
- result_queue = Queue.new
51
- error_queue = Queue.new
52
- threads = []
53
- cancelled = Concurrent::AtomicBoolean.new(false)
54
-
55
- callables.each_with_index do |callable, index|
56
- # Add delay for hedge requests (not the first one)
57
- sleep(delay_ms / 1000.0) if index.positive? && delay_ms.positive?
58
-
59
- # Skip if already got a result
60
- break if cancelled.value
61
-
62
- threads << Thread.new do
63
- unless cancelled.value
64
- begin
65
- result = callable.call
66
- result_queue << result unless cancelled.value
67
- cancelled.value = true
68
- rescue StandardError => e
69
- error_queue << e unless cancelled.value
70
- end
71
- end
72
- end
73
- end
74
-
75
- # Wait for first result or all errors
76
- begin
77
- Timeout.timeout(@config[:timeout] || 30) do
78
- # Check for successful result
79
- loop do
80
- unless result_queue.empty?
81
- result = result_queue.pop
82
- cancelled.value = true
83
- return result
84
- end
85
-
86
- # Check if all requests failed
87
- raise error_queue.pop if error_queue.size >= callables.size
88
-
89
- # Small sleep to prevent busy waiting
90
- sleep 0.001
91
- end
92
- end
93
- ensure
94
- # Cancel remaining threads
95
- cancelled.value = true
96
- threads.each(&:kill)
97
- end
98
- end
99
-
100
- # Async hedged execution (requires async support)
101
- def execute_hedged_async(callables, delay_ms)
102
- # This will be implemented when async support is loaded
103
- # For now, fall back to sync implementation
104
- return execute_hedged_sync(callables, delay_ms) unless respond_to?(:execute_hedged_with_async)
105
-
106
- execute_hedged_with_async(callables, delay_ms)
107
- end
108
-
109
- def hedged_requests_enabled?
110
- @config[:hedged_requests] == true
111
- end
112
- end
113
- end