Class: BreakerMachines::Storage::BucketMemory

Inherits:
Base
  • Object
show all
Defined in:
lib/breaker_machines/storage/bucket_memory.rb

Overview

Efficient bucket-based memory storage implementation Uses fixed-size circular buffers for constant-time event counting

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.

Constant Summary collapse

BUCKET_SIZE =

1 second per bucket

1

Instance Method Summary collapse

Constructor Details

#initialize(**options) ⇒ BucketMemory

Returns a new instance of BucketMemory.



17
18
19
20
21
22
23
24
25
26
# File 'lib/breaker_machines/storage/bucket_memory.rb', line 17

def initialize(**options)
  super
  @circuits = Concurrent::Map.new
  @circuit_buckets = Concurrent::Map.new
  @event_logs = Concurrent::Map.new
  @bucket_count = options[:bucket_count] || 300 # Default 5 minutes
  @max_events = options[: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



62
63
64
65
66
# File 'lib/breaker_machines/storage/bucket_memory.rb', line 62

def clear(circuit_name)
  @circuits.delete(circuit_name)
  @circuit_buckets.delete(circuit_name)
  @event_logs.delete(circuit_name)
end

#clear_allObject



68
69
70
71
72
# File 'lib/breaker_machines/storage/bucket_memory.rb', line 68

def clear_all
  @circuits.clear
  @circuit_buckets.clear
  @event_logs.clear
end

#event_log(circuit_name, limit) ⇒ Object



93
94
95
96
97
98
# File 'lib/breaker_machines/storage/bucket_memory.rb', line 93

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



58
59
60
# File 'lib/breaker_machines/storage/bucket_memory.rb', line 58

def failure_count(circuit_name, window_seconds)
  count_events(circuit_name, :failure, window_seconds)
end

#get_status(circuit_name) ⇒ Object



28
29
30
31
32
33
34
35
36
# File 'lib/breaker_machines/storage/bucket_memory.rb', line 28

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



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/breaker_machines/storage/bucket_memory.rb', line 74

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.message 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



50
51
52
# File 'lib/breaker_machines/storage/bucket_memory.rb', line 50

def record_failure(circuit_name, duration)
  record_event(circuit_name, :failure, duration)
end

#record_success(circuit_name, duration) ⇒ Object



46
47
48
# File 'lib/breaker_machines/storage/bucket_memory.rb', line 46

def record_success(circuit_name, duration)
  record_event(circuit_name, :success, duration)
end

#set_status(circuit_name, status, opened_at = nil) ⇒ Object



38
39
40
41
42
43
44
# File 'lib/breaker_machines/storage/bucket_memory.rb', line 38

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



54
55
56
# File 'lib/breaker_machines/storage/bucket_memory.rb', line 54

def success_count(circuit_name, window_seconds)
  count_events(circuit_name, :success, window_seconds)
end