breaker_machines 0.20.0 → 0.21.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a533c91306760488de32d6ef3b3a3bfc9a6c874b1b6e77c6fed42b429a2da6b6
4
- data.tar.gz: 88991049dc9e83392a13880557ea199830291d21213749a84cd3716c56c9eaac
3
+ metadata.gz: 2917078ec6012a3ffd7c6bf1f6bb070e81172a023c3e1cf48b2e03141867cf40
4
+ data.tar.gz: f67ed52002fd12709e38846305c7690613fa56e15610802cc9a60932da742e02
5
5
  SHA512:
6
- metadata.gz: 7c25929aa77bacbca4857bc1961110680838e2ae83fee1356d10f3f67297e623f2b1bafe0a104485a372618281d45e542da063482e4ead55294fe9f2e7655478
7
- data.tar.gz: 7ef7f97ca50b64a56589ff6a3a062fa4016e33b70e81e3becd3fb705254a3ffbab6af89e75a6d8f0fc17f2c8a3784b48dbdaba4d8fe78383ca244fe15e7a0a5f
6
+ metadata.gz: 60f11940b9be26b46709c70d70e85fde1deb91e0d7b597ddb5af489b065f4cf1b7d344b66b083a40023829e1463b85600db14efad3975dc4a00c50f7561d2522
7
+ data.tar.gz: 2fe289725532b4e6177e5c4cdd4184e0ae7252065ab068449e080019047f1cbcbecb3a10a3d1e0b89e6723fdd364e83a4331632b0661048abb8939ce4f604525
data/README.md CHANGED
@@ -28,6 +28,23 @@ class PaymentService
28
28
  end
29
29
  ```
30
30
 
31
+ ### Protect an existing client
32
+
33
+ Use `protect` to route selected public methods through an existing circuit:
34
+
35
+ ```ruby
36
+ circuit = BreakerMachines::Circuit.new(:teleporter, failure_threshold: 3)
37
+ protected_client = circuit.protect(teleporter, methods: %i[beam_up beam_down])
38
+
39
+ protected_client.beam_up('Schrödinger', destination: :sickbay)
40
+ ```
41
+
42
+ The wrapper forwards arguments, keywords, blocks, and results through `circuit.call`, including its configured error handling and fallback. Other methods pass through without consulting the circuit. `methods:` must be nonempty and name public methods the client responds to; otherwise `protect` raises `ArgumentError`.
43
+
44
+ The original client stays unchanged. Each call through the wrapper counts as one operation, including any internal method calls. Returned objects stay unchanged too: later calls on a returned client or lazy stream need their own protection. Wrap the object that performs the external operation.
45
+
46
+ Available on Ruby and native circuits, including circuits obtained through the DSL. Multiple wrappers can share the same circuit.
47
+
31
48
  ## A Message to the Resistance
32
49
 
33
50
  So AI took your job while you were waiting for Fireship to drop the next JavaScript framework?
@@ -12,6 +12,7 @@ module BreakerMachines
12
12
  include Circuit::Configuration
13
13
  include Circuit::Admission
14
14
  include Circuit::Execution
15
+ include Circuit::Protection
15
16
  include Circuit::HedgedExecution
16
17
  include Circuit::Introspection
17
18
  include Circuit::Callbacks
@@ -16,6 +16,8 @@ module BreakerMachines
16
16
  #
17
17
  # circuit.call { api.fetch_data }
18
18
  class Native
19
+ include Circuit::Protection
20
+
19
21
  # @return [String] Circuit name
20
22
  attr_reader :name
21
23
 
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BreakerMachines
4
+ class Circuit
5
+ # Protection adds `protect`, which wraps selected public methods of an
6
+ # object so that each call runs through this circuit's `call`.
7
+ module Protection
8
+ def protect(object, methods:)
9
+ Proxy.new(object, circuit: self, methods:)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'delegate'
4
+
5
+ module BreakerMachines
6
+ class Circuit
7
+ # Proxy delegates to a wrapped object and routes the configured methods
8
+ # through a circuit. Unlisted methods pass straight through.
9
+ class Proxy < SimpleDelegator
10
+ def initialize(object, circuit:, methods:)
11
+ raise ArgumentError, 'methods must not be empty' if methods.empty?
12
+
13
+ methods.each do |name|
14
+ raise ArgumentError, "Unknown public method: #{name}" unless object.respond_to?(name)
15
+ end
16
+
17
+ super(object)
18
+
19
+ methods.each do |name|
20
+ define_singleton_method(name) do |*args, **kwargs, &block|
21
+ circuit.call { __getobj__.public_send(name, *args, **kwargs, &block) }
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BreakerMachines
4
- VERSION = '0.20.0'
4
+ VERSION = '0.21.0'
5
5
  end
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.20.0
4
+ version: 0.21.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Abdelkader Boudih
@@ -164,6 +164,8 @@ files:
164
164
  - lib/breaker_machines/circuit/hedged_execution.rb
165
165
  - lib/breaker_machines/circuit/introspection.rb
166
166
  - lib/breaker_machines/circuit/native.rb
167
+ - lib/breaker_machines/circuit/protection.rb
168
+ - lib/breaker_machines/circuit/proxy.rb
167
169
  - lib/breaker_machines/circuit/state_callbacks.rb
168
170
  - lib/breaker_machines/circuit/state_machine_definition.rb
169
171
  - lib/breaker_machines/circuit/state_management.rb
@@ -192,18 +194,6 @@ files:
192
194
  - lib/breaker_machines/storage/null.rb
193
195
  - lib/breaker_machines/types.rb
194
196
  - lib/breaker_machines/version.rb
195
- - sig/README.md
196
- - sig/all.rbs
197
- - sig/breaker_machines.rbs
198
- - sig/breaker_machines/circuit.rbs
199
- - sig/breaker_machines/console.rbs
200
- - sig/breaker_machines/dsl.rbs
201
- - sig/breaker_machines/errors.rbs
202
- - sig/breaker_machines/interfaces.rbs
203
- - sig/breaker_machines/registry.rbs
204
- - sig/breaker_machines/storage.rbs
205
- - sig/breaker_machines/types.rbs
206
- - sig/manifest.yaml
207
197
  homepage: https://github.com/seuros/breaker_machines
208
198
  licenses:
209
199
  - MIT
data/sig/README.md DELETED
@@ -1,74 +0,0 @@
1
- # BreakerMachines RBS Type Signatures
2
-
3
- This directory contains RBS (Ruby type signatures) for the BreakerMachines gem.
4
-
5
- ## Structure
6
-
7
- - `breaker_machines.rbs` - Main module and configuration
8
- - `breaker_machines/` - Type signatures for all classes and modules
9
- - `circuit.rbs` - Circuit class and its modules
10
- - `errors.rbs` - Error classes
11
- - `storage.rbs` - Storage backends
12
- - `dsl.rbs` - DSL module for including in classes
13
- - `registry.rbs` - Global circuit registry
14
- - `console.rbs` - Interactive console
15
- - `types.rbs` - Common type aliases
16
- - `interfaces.rbs` - Interface definitions
17
-
18
- ## Usage
19
-
20
- To use these type signatures in your project:
21
-
22
- 1. Add to your `Steepfile`:
23
- ```ruby
24
- target :app do
25
- signature "sig"
26
- check "lib"
27
-
28
- library "breaker_machines"
29
- end
30
- ```
31
-
32
- 2. Or with RBS directly:
33
- ```bash
34
- rbs validate
35
- ```
36
-
37
- ## Type Checking Examples
38
-
39
- ### Basic Circuit Usage
40
- ```ruby
41
- circuit = BreakerMachines::Circuit.new("api",
42
- failure_threshold: 5,
43
- reset_timeout: 30
44
- )
45
-
46
- result = circuit.call { api.fetch_data }
47
- ```
48
-
49
- ### DSL Usage
50
- ```ruby
51
- class MyService
52
- include BreakerMachines::DSL
53
-
54
- circuit :database do
55
- threshold failures: 10, within: 60
56
- reset_after 120
57
- fallback { [] }
58
- end
59
- end
60
- ```
61
-
62
- ## Key Types
63
-
64
- - `circuit_state` - `:open | :closed | :half_open`
65
- - `storage_backend` - `:memory | :bucket_memory | :null | :redis`
66
- - `circuit_options` - Configuration hash for circuits
67
- - `event_record` - Structure for logged events
68
-
69
- ## Interfaces
70
-
71
- The type signatures define several interfaces:
72
- - `_StorageBackend` - For custom storage implementations
73
- - `_MetricsRecorder` - For custom metrics recording
74
- - `_CircuitLike` - For circuit-compatible objects
data/sig/all.rbs DELETED
@@ -1,25 +0,0 @@
1
- # Main entry point for BreakerMachines RBS types
2
- #
3
- # This file provides a complete type definition for the BreakerMachines gem,
4
- # a Ruby implementation of the Circuit Breaker pattern.
5
- #
6
- # Usage:
7
- # class MyService
8
- # include BreakerMachines::DSL
9
- #
10
- # circuit :api_call do
11
- # threshold failures: 5, within: 60
12
- # reset_after 30
13
- # fallback { |error| { error: "Service unavailable" } }
14
- # end
15
- #
16
- # def fetch_data
17
- # circuit(:api_call).call do
18
- # # Your API call here
19
- # end
20
- # end
21
- # end
22
-
23
- # Import all type definitions
24
- use BreakerMachines::*
25
- use BreakerMachines::Storage::*
@@ -1,179 +0,0 @@
1
- module BreakerMachines
2
- class Circuit
3
- include StateManagement
4
- include Configuration
5
- include Admission
6
- include Execution
7
- include Introspection
8
- include Callbacks
9
-
10
- # Instance variables from Configuration module
11
- @name: String
12
- @config: Hash[Symbol, untyped]
13
- @storage: _StorageBackend?
14
- @metrics: _MetricsRecorder?
15
- @opened_at: Concurrent::AtomicReference[Float?]
16
- @half_open_attempts: Concurrent::AtomicFixnum
17
- @half_open_successes: Concurrent::AtomicFixnum
18
- @state_epoch: Concurrent::AtomicFixnum
19
- @mutex: Concurrent::ReentrantReadWriteLock
20
- @last_failure_at: Concurrent::AtomicReference[Float?]
21
- @last_error: Concurrent::AtomicReference[StandardError?]
22
-
23
- # State machine status (from StateManagement)
24
- attr_reader status: (:open | :closed | :half_open)
25
- end
26
-
27
- module Admission
28
- class Call
29
- attr_reader state: (:closed | :half_open)
30
- attr_reader state_epoch: Integer
31
-
32
- def self.new: (state: (:closed | :half_open), state_epoch: Integer) -> Call
33
- def closed?: () -> bool
34
- def half_open?: () -> bool
35
- end
36
-
37
- private
38
-
39
- def attempt_recovery_if_ready: () -> void
40
- def admit_call: () -> Call?
41
- def admit_half_open_call: () -> Call?
42
- def admission_current?: (Call admission) -> bool
43
- def handle_success: (Call admission) -> void
44
- def handle_failure: (Call admission) -> void
45
- def release_abandoned_admission: (Call admission) -> void
46
- end
47
-
48
- module StateManagement
49
- interface _StateManagementState
50
- def status: () -> (:open | :closed | :half_open)
51
- def status=: (:open | :closed | :half_open value) -> void
52
- def status_name: () -> (:open | :closed | :half_open)
53
- def open?: () -> bool
54
- def closed?: () -> bool
55
- def half_open?: () -> bool
56
- def trip: () -> bool
57
- def attempt_recovery: () -> bool
58
- def reset: () -> bool
59
- def force_open: () -> bool
60
- def force_close: () -> bool
61
- end
62
-
63
- def self.included: (singleton(Circuit) base) -> void
64
-
65
- private
66
-
67
- def on_circuit_open: () -> void
68
- def on_circuit_close: () -> void
69
- def on_circuit_half_open: () -> void
70
- def restore_status_from_storage: () -> void
71
- def reset_timeout_elapsed?: () -> bool
72
- def monotonic_time: () -> Float
73
- end
74
-
75
- module Configuration
76
- extend ActiveSupport::Concern
77
-
78
- interface _ConfigurationMethods
79
- def name: () -> String
80
- def config: () -> Hash[Symbol, untyped]
81
- def opened_at: () -> Concurrent::AtomicReference[Float?]
82
- end
83
-
84
- type storage_type = Storage::Base | Storage::Memory | Storage::BucketMemory | Storage::Null
85
- type metrics_type = untyped
86
- type callback_type = Proc | nil
87
- type fallback_type = Proc | Array[Proc | untyped] | untyped
88
-
89
- type circuit_config = {
90
- failure_threshold: Integer,
91
- failure_window: Integer,
92
- success_threshold: Integer,
93
- timeout: Integer?,
94
- reset_timeout: Integer,
95
- reset_timeout_jitter: Float,
96
- half_open_calls: Integer,
97
- storage: storage_type?,
98
- metrics: metrics_type?,
99
- fallback: fallback_type?,
100
- on_open: callback_type,
101
- on_close: callback_type,
102
- on_half_open: callback_type,
103
- on_reject: callback_type,
104
- exceptions: Array[Class],
105
- owner: untyped
106
- }
107
-
108
- def initialize: (String name, ?circuit_config options) -> void
109
-
110
- private
111
-
112
- def default_config: () -> circuit_config
113
- def create_default_storage: () -> storage_type
114
- end
115
-
116
- module Execution
117
- def call: [T] () { () -> T } -> untyped
118
- def wrap: [T] () { () -> T } -> untyped
119
-
120
- private
121
-
122
- def execute_with_state_check: [T] () { () -> T } -> untyped
123
- def execute_call: [T] (Admission::Call admission) { () -> T } -> untyped
124
- def execute_call_sync: [T] (Admission::Call admission) { () -> T } -> untyped
125
- def execute_sync_operation: [T] () { () -> T } -> T
126
- def warn_about_sync_timeout: () -> void
127
- def complete_call_success: (Admission::Call admission, Float start_time) -> void
128
- def complete_call_failure: (Admission::Call admission, Float start_time, Exception error) -> void
129
- def reject_call: () -> untyped
130
- def reject_call_bulkhead: () -> untyped
131
- def failure_threshold_exceeded?: () -> bool
132
- def success_threshold_reached?: () -> bool
133
- def record_success: (Float duration) -> void
134
- def record_failure: (Float duration, ?StandardError? error) -> void
135
- end
136
-
137
- module Introspection
138
- type stats_hash = {
139
- state: (:open | :closed | :half_open),
140
- failure_count: Integer,
141
- success_count: Integer,
142
- last_failure_at: Float?,
143
- opened_at: Float?,
144
- half_open_attempts: Integer,
145
- half_open_successes: Integer
146
- }
147
-
148
- type error_info = {
149
- class: String,
150
- message: String,
151
- occurred_at: Float
152
- }
153
-
154
- type circuit_hash = {
155
- name: String,
156
- state: (:open | :closed | :half_open),
157
- stats: stats_hash,
158
- config: Hash[Symbol, untyped],
159
- event_log: Array[untyped],
160
- last_error: error_info?
161
- }
162
-
163
- def stats: () -> stats_hash
164
- def configuration: () -> Hash[Symbol, untyped]
165
- def event_log: (?limit: Integer) -> Array[untyped]?
166
- def last_error: () -> StandardError?
167
- def to_h: () -> circuit_hash
168
- def summary: () -> String
169
- def last_error_info: () -> error_info?
170
- end
171
-
172
- module Callbacks
173
- private
174
-
175
- def invoke_callback: (Symbol callback_name) -> void
176
- def invoke_fallback: (StandardError error) -> untyped
177
- def invoke_single_fallback: (Proc | untyped fallback, StandardError error) -> untyped
178
- end
179
- end
@@ -1,32 +0,0 @@
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
@@ -1,50 +0,0 @@
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
@@ -1,24 +0,0 @@
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
@@ -1,46 +0,0 @@
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
@@ -1,30 +0,0 @@
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
@@ -1,65 +0,0 @@
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
@@ -1,97 +0,0 @@
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
@@ -1,42 +0,0 @@
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 DELETED
@@ -1,5 +0,0 @@
1
- dependencies:
2
- - name: activesupport
3
- - name: concurrent-ruby
4
- - name: state_machines
5
- - name: zeitwerk