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

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.



13
14
15
16
17
18
19
20
# File 'lib/breaker_machines/storage/bucket_memory.rb', line 13

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
end

Instance Method Details

#clear(circuit_name) ⇒ Object



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

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

#clear_allObject



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

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

#event_log(circuit_name, limit) ⇒ Object



87
88
89
90
91
92
# File 'lib/breaker_machines/storage/bucket_memory.rb', line 87

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



52
53
54
# File 'lib/breaker_machines/storage/bucket_memory.rb', line 52

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

#get_status(circuit_name) ⇒ Object



22
23
24
25
26
27
28
29
30
# File 'lib/breaker_machines/storage/bucket_memory.rb', line 22

def get_status(circuit_name)
  circuit_data = @circuits[circuit_name]
  return nil unless circuit_data

  {
    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



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/breaker_machines/storage/bucket_memory.rb', line 68

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



44
45
46
# File 'lib/breaker_machines/storage/bucket_memory.rb', line 44

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

#record_success(circuit_name, duration) ⇒ Object



40
41
42
# File 'lib/breaker_machines/storage/bucket_memory.rb', line 40

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

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



32
33
34
35
36
37
38
# File 'lib/breaker_machines/storage/bucket_memory.rb', line 32

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



48
49
50
# File 'lib/breaker_machines/storage/bucket_memory.rb', line 48

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