Class: BreakerMachines::Storage::Cache
- Defined in:
- lib/breaker_machines/storage/cache.rb
Overview
Storage adapter for ActiveSupport::Cache Works with any Rails cache store (Redis, Memcached, Memory, etc.)
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(cache_store: Rails.cache, **options) ⇒ Cache
constructor
A new instance of Cache.
- #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(cache_store: Rails.cache, **options) ⇒ Cache
Returns a new instance of Cache.
8 9 10 11 12 13 |
# File 'lib/breaker_machines/storage/cache.rb', line 8 def initialize(cache_store: Rails.cache, **) super(**) @cache = cache_store @prefix = [:prefix] || 'breaker_machines' @expires_in = [:expires_in] || 300 # 5 minutes default end |
Instance Method Details
#clear(circuit_name) ⇒ Object
53 54 55 56 57 58 |
# File 'lib/breaker_machines/storage/cache.rb', line 53 def clear(circuit_name) @cache.delete(status_key(circuit_name)) @cache.delete(success_key(circuit_name)) @cache.delete(failure_key(circuit_name)) @cache.delete(events_key(circuit_name)) end |
#clear_all ⇒ Object
60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/breaker_machines/storage/cache.rb', line 60 def clear_all # Clear all circuit data by pattern if cache supports it if @cache.respond_to?(:delete_matched) @cache.delete_matched("#{@prefix}:*") else # Fallback: can't efficiently clear all without pattern support BreakerMachines.logger&.warn( "[BreakerMachines] Cache store doesn't support delete_matched. " \ 'Individual circuit data must be cleared manually.' ) end end |
#event_log(circuit_name, limit) ⇒ Object
92 93 94 95 |
# File 'lib/breaker_machines/storage/cache.rb', line 92 def event_log(circuit_name, limit) events = @cache.read(events_key(circuit_name)) || [] events.last(limit) end |
#failure_count(circuit_name, window_seconds) ⇒ Object
49 50 51 |
# File 'lib/breaker_machines/storage/cache.rb', line 49 def failure_count(circuit_name, window_seconds) get_window_count(failure_key(circuit_name), window_seconds) end |
#get_status(circuit_name) ⇒ Object
15 16 17 18 19 20 21 22 23 |
# File 'lib/breaker_machines/storage/cache.rb', line 15 def get_status(circuit_name) data = @cache.read(status_key(circuit_name)) return nil unless data BreakerMachines::Status.new( status: data[:status].to_sym, opened_at: data[:opened_at] ) end |
#record_event_with_details(circuit_name, type, duration, error: nil, new_state: nil) ⇒ Object
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/breaker_machines/storage/cache.rb', line 73 def record_event_with_details(circuit_name, type, duration, error: nil, new_state: nil) events = @cache.fetch(events_key(circuit_name)) { [] } 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 events.shift while events.size > (@max_events || 100) @cache.write(events_key(circuit_name), events, expires_in: @expires_in) end |
#record_failure(circuit_name, _duration) ⇒ Object
41 42 43 |
# File 'lib/breaker_machines/storage/cache.rb', line 41 def record_failure(circuit_name, _duration) increment_counter(failure_key(circuit_name)) end |
#record_success(circuit_name, _duration) ⇒ Object
37 38 39 |
# File 'lib/breaker_machines/storage/cache.rb', line 37 def record_success(circuit_name, _duration) increment_counter(success_key(circuit_name)) end |
#set_status(circuit_name, status, opened_at = nil) ⇒ Object
25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/breaker_machines/storage/cache.rb', line 25 def set_status(circuit_name, status, opened_at = nil) @cache.write( status_key(circuit_name), { status: status, opened_at: opened_at, updated_at: monotonic_time }, expires_in: @expires_in ) end |
#success_count(circuit_name, window_seconds) ⇒ Object
45 46 47 |
# File 'lib/breaker_machines/storage/cache.rb', line 45 def success_count(circuit_name, window_seconds) get_window_count(success_key(circuit_name), window_seconds) end |
#with_timeout(_timeout_ms) ⇒ Object
97 98 99 100 101 102 |
# File 'lib/breaker_machines/storage/cache.rb', line 97 def with_timeout(_timeout_ms) # Rails cache operations should rely on their own underlying timeouts # Using Ruby's Timeout.timeout is dangerous and can cause deadlocks # For Redis cache stores, configure connect_timeout and read_timeout instead yield end |