Class: BreakerMachines::Storage::Memory
- Defined in:
- lib/breaker_machines/storage/memory.rb
Overview
High-performance in-memory storage backend with thread-safe operations
WARNING: This storage backend is NOT compatible with DRb (distributed Ruby) environments as memory is not shared between processes. Use Cache backend with an external cache store (Redis, Memcached) for distributed setups.
Instance Method Summary collapse
- #clear(circuit_name) ⇒ Object
- #clear_all ⇒ Object
- #event_log(circuit_name, limit) ⇒ Object
- #failure_count(circuit_name, window_seconds) ⇒ Object
- #get_status(circuit_name) ⇒ Object
-
#initialize(**options) ⇒ Memory
constructor
A new instance of Memory.
- #record_event_with_details(circuit_name, type, duration, error: nil, new_state: nil) ⇒ Object
- #record_failure(circuit_name, duration) ⇒ Object
- #record_success(circuit_name, duration) ⇒ Object
- #set_status(circuit_name, status, opened_at = nil) ⇒ Object
- #success_count(circuit_name, window_seconds) ⇒ Object
- #with_timeout(_timeout_ms) ⇒ Object
Constructor Details
#initialize(**options) ⇒ Memory
Returns a new instance of Memory.
14 15 16 17 18 19 20 21 22 |
# File 'lib/breaker_machines/storage/memory.rb', line 14 def initialize(**) super @circuits = Concurrent::Map.new @events = Concurrent::Map.new @event_logs = Concurrent::Map.new @max_events = [:max_events] || 100 # Store creation time as anchor for relative timestamps (like Rust implementation) @start_time = BreakerMachines.monotonic_time end |
Instance Method Details
#clear(circuit_name) ⇒ Object
58 59 60 61 62 |
# File 'lib/breaker_machines/storage/memory.rb', line 58 def clear(circuit_name) @circuits.delete(circuit_name) @events.delete(circuit_name) @event_logs.delete(circuit_name) end |
#clear_all ⇒ Object
64 65 66 67 68 |
# File 'lib/breaker_machines/storage/memory.rb', line 64 def clear_all @circuits.clear @events.clear @event_logs.clear end |
#event_log(circuit_name, limit) ⇒ Object
89 90 91 92 93 94 |
# File 'lib/breaker_machines/storage/memory.rb', line 89 def event_log(circuit_name, limit) events = @event_logs[circuit_name] return [] unless events events.last(limit).map(&:dup) end |
#failure_count(circuit_name, window_seconds) ⇒ Object
54 55 56 |
# File 'lib/breaker_machines/storage/memory.rb', line 54 def failure_count(circuit_name, window_seconds) count_events(circuit_name, :failure, window_seconds) end |
#get_status(circuit_name) ⇒ Object
24 25 26 27 28 29 30 31 32 |
# File 'lib/breaker_machines/storage/memory.rb', line 24 def get_status(circuit_name) circuit_data = @circuits[circuit_name] return nil unless circuit_data BreakerMachines::Status.new( status: circuit_data[:status], opened_at: circuit_data[:opened_at] ) end |
#record_event_with_details(circuit_name, type, duration, error: nil, new_state: nil) ⇒ Object
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/breaker_machines/storage/memory.rb', line 70 def record_event_with_details(circuit_name, type, duration, error: nil, new_state: nil) events = @event_logs.compute_if_absent(circuit_name) { Concurrent::Array.new } event = { type: type, timestamp: monotonic_time, duration_ms: (duration * 1000).round(2) } event[:error_class] = error.class.name if error event[:error_message] = error. if error event[:new_state] = new_state if new_state events << event # Keep only the most recent events events.shift while events.size > @max_events end |
#record_failure(circuit_name, duration) ⇒ Object
46 47 48 |
# File 'lib/breaker_machines/storage/memory.rb', line 46 def record_failure(circuit_name, duration) record_event(circuit_name, :failure, duration) end |
#record_success(circuit_name, duration) ⇒ Object
42 43 44 |
# File 'lib/breaker_machines/storage/memory.rb', line 42 def record_success(circuit_name, duration) record_event(circuit_name, :success, duration) end |
#set_status(circuit_name, status, opened_at = nil) ⇒ Object
34 35 36 37 38 39 40 |
# File 'lib/breaker_machines/storage/memory.rb', line 34 def set_status(circuit_name, status, opened_at = nil) @circuits[circuit_name] = { status: status, opened_at: opened_at, updated_at: monotonic_time } end |
#success_count(circuit_name, window_seconds) ⇒ Object
50 51 52 |
# File 'lib/breaker_machines/storage/memory.rb', line 50 def success_count(circuit_name, window_seconds) count_events(circuit_name, :success, window_seconds) end |
#with_timeout(_timeout_ms) ⇒ Object
96 97 98 99 100 |
# File 'lib/breaker_machines/storage/memory.rb', line 96 def with_timeout(_timeout_ms) # Memory operations should be instant, but we'll still respect the timeout # This is more for consistency and to catch any potential deadlocks yield end |