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.
- checksums.yaml +4 -4
- data/README.md +25 -3
- data/ext/breaker_machines_native/Cargo.toml +8 -0
- data/ext/breaker_machines_native/core/Cargo.toml +18 -0
- data/ext/breaker_machines_native/core/examples/basic.rs +61 -0
- data/ext/breaker_machines_native/core/src/builder.rs +232 -0
- data/ext/breaker_machines_native/core/src/bulkhead.rs +223 -0
- data/ext/breaker_machines_native/core/src/callbacks.rs +58 -0
- data/ext/breaker_machines_native/core/src/circuit.rs +1156 -0
- data/ext/breaker_machines_native/core/src/classifier.rs +177 -0
- data/ext/breaker_machines_native/core/src/errors.rs +47 -0
- data/ext/breaker_machines_native/core/src/lib.rs +62 -0
- data/ext/breaker_machines_native/core/src/storage.rs +377 -0
- data/ext/breaker_machines_native/extconf.rb +40 -0
- data/ext/breaker_machines_native/ffi/Cargo.toml +16 -0
- data/ext/breaker_machines_native/ffi/src/lib.rs +218 -0
- data/ext/breaker_machines_native/target/debug/build/clang-sys-d961dfabd5f43fba/out/common.rs +355 -0
- data/ext/breaker_machines_native/target/debug/build/clang-sys-d961dfabd5f43fba/out/dynamic.rs +276 -0
- data/ext/breaker_machines_native/target/debug/build/clang-sys-d961dfabd5f43fba/out/macros.rs +49 -0
- 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
- 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
- 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
- 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
- data/ext/breaker_machines_native/target/package/breaker-machines-0.1.0/Cargo.toml +48 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.1.0/examples/basic.rs +61 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.1.0/src/builder.rs +154 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.1.0/src/callbacks.rs +55 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.1.0/src/circuit.rs +607 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.1.0/src/errors.rs +38 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.1.0/src/lib.rs +58 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.1.0/src/storage.rs +377 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.2.0/Cargo.toml +48 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.2.0/examples/basic.rs +61 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.2.0/src/builder.rs +173 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.2.0/src/callbacks.rs +55 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.2.0/src/circuit.rs +855 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.2.0/src/errors.rs +38 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.2.0/src/lib.rs +58 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.2.0/src/storage.rs +377 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.5.0/Cargo.toml +48 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.5.0/examples/basic.rs +61 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.5.0/src/builder.rs +154 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.5.0/src/callbacks.rs +55 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.5.0/src/circuit.rs +607 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.5.0/src/errors.rs +38 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.5.0/src/lib.rs +58 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.5.0/src/storage.rs +377 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.6.0/Cargo.toml +48 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.6.0/examples/basic.rs +61 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.6.0/src/builder.rs +232 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.6.0/src/bulkhead.rs +223 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.6.0/src/callbacks.rs +58 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.6.0/src/circuit.rs +1156 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.6.0/src/classifier.rs +177 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.6.0/src/errors.rs +47 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.6.0/src/lib.rs +62 -0
- data/ext/breaker_machines_native/target/package/breaker-machines-0.6.0/src/storage.rs +377 -0
- data/ext/breaker_machines_native/target/release/build/clang-sys-ef8ad8b846ac8b75/out/common.rs +355 -0
- data/ext/breaker_machines_native/target/release/build/clang-sys-ef8ad8b846ac8b75/out/dynamic.rs +276 -0
- data/ext/breaker_machines_native/target/release/build/clang-sys-ef8ad8b846ac8b75/out/macros.rs +49 -0
- 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
- data/lib/breaker_machines/async_circuit.rb +47 -0
- data/lib/breaker_machines/async_support.rb +4 -3
- data/lib/breaker_machines/cascading_circuit.rb +5 -3
- data/lib/breaker_machines/circuit/async_state_management.rb +71 -0
- data/lib/breaker_machines/circuit/base.rb +59 -0
- data/lib/breaker_machines/circuit/callbacks.rb +7 -12
- data/lib/breaker_machines/circuit/configuration.rb +6 -26
- data/lib/breaker_machines/circuit/coordinated_state_management.rb +117 -0
- data/lib/breaker_machines/circuit/hedged_execution.rb +115 -0
- data/lib/breaker_machines/circuit/introspection.rb +1 -0
- data/lib/breaker_machines/circuit/native.rb +127 -0
- data/lib/breaker_machines/circuit/state_callbacks.rb +72 -0
- data/lib/breaker_machines/circuit/state_management.rb +14 -61
- data/lib/breaker_machines/circuit.rb +1 -7
- data/lib/breaker_machines/circuit_group.rb +153 -0
- data/lib/breaker_machines/coordinated_circuit.rb +10 -0
- data/lib/breaker_machines/dsl.rb +2 -2
- data/lib/breaker_machines/errors.rb +20 -0
- data/lib/breaker_machines/hedged_async_support.rb +29 -36
- data/lib/breaker_machines/native_extension.rb +36 -0
- data/lib/breaker_machines/native_speedup.rb +6 -0
- data/lib/breaker_machines/storage/bucket_memory.rb +4 -1
- data/lib/breaker_machines/storage/memory.rb +4 -1
- data/lib/breaker_machines/storage/native.rb +90 -0
- data/lib/breaker_machines/version.rb +1 -1
- data/lib/breaker_machines.rb +115 -11
- data/lib/breaker_machines_native/breaker_machines_native.bundle +0 -0
- data/sig/breaker_machines.rbs +20 -8
- metadata +107 -7
- data/lib/breaker_machines/hedged_execution.rb +0 -113
data/lib/breaker_machines.rb
CHANGED
|
@@ -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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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
|
|
Binary file
|
data/sig/breaker_machines.rbs
CHANGED
|
@@ -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
|
-
|
|
16
|
+
self.@config: Configuration?
|
|
17
|
+
def self.config: () -> Configuration
|
|
18
|
+
|
|
19
|
+
# Class methods
|
|
20
|
+
def self.configure: () { (Configuration config) -> void } -> void
|
|
6
21
|
|
|
7
|
-
#
|
|
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
|
-
|
|
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
|
+
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: '
|
|
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: '
|
|
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.
|
|
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.
|
|
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/
|
|
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
|