class Breakers::Outage
A class defining an outage on a service
Attributes
Public Class Methods
Create a new outage on the given service
@param service [Breakers::Service] the service to create it for @param forced [Boolean] is the service forced, or created via the middleware @return [Breakers::Outage] the new outage
# File lib/breakers/outage.rb, line 38 def self.create(service:, forced: false) data = MultiJson.dump(start_time: Time.now.utc.to_i, forced: forced) Breakers.client.redis_connection.zadd(outages_key(service: service), Time.now.utc.to_i, data) Breakers.client.logger&.error(msg: 'Breakers outage beginning', service: service.name, forced: forced) Breakers.client.plugins.each do |plugin| plugin.on_outage_begin(Outage.new(service: service, body: data)) if plugin.respond_to?(:on_outage_begin) end end
Return the most recent outage on the given service
@param service [Breakers::Service] the service to look in @return [Breakers::Outage] the most recent outage, or nil
# File lib/breakers/outage.rb, line 13 def self.find_latest(service:) data = Breakers.client.redis_connection.zrange(outages_key(service: service), -1, -1)[0] data && new(service: service, body: data) end
Return all of the outages on the given service that begin in the time range
@param service [Breakers::Service] the service to look in @param start_time
[Time] the beginning of the time range @param end_time
[Time] the end of the time range @return [Breakers::Outage] a list of the outages in the range
# File lib/breakers/outage.rb, line 24 def self.in_range(service:, start_time:, end_time:) data = Breakers.client.redis_connection.zrangebyscore( outages_key(service: service), start_time.to_i, end_time.to_i ) data.map { |item| new(service: service, body: item) } end
Create a new outage
@param service [Breakers::Service] the service the outage is for @param body [Hash] the data to store in the outage, with keys start_time
, end_time
, last_test_time
, and forced @return [Breakers::Outage] the new outage
# File lib/breakers/outage.rb, line 62 def initialize(service:, body:) @body = MultiJson.load(body) @service = service end
Get the key for storing the outage data in Redis for this service
@param service [Breakers::Service] the service @return [String] the Redis key
# File lib/breakers/outage.rb, line 53 def self.outages_key(service:) "#{Breakers.redis_prefix}#{service.name}-outages" end
Public Instance Methods
Tell the outage to end, which will allow requests to begin flowing again
# File lib/breakers/outage.rb, line 82 def end! new_body = @body.dup new_body['end_time'] = Time.now.utc.to_i replace_body(body: new_body) Breakers.client.logger&.info(msg: 'Breakers outage ending', service: @service.name, forced: forced?) Breakers.client.plugins.each do |plugin| plugin.on_outage_end(self) if plugin.respond_to?(:on_outage_begin) end end
Get the time at which the outage ended
@return [Time] the time
# File lib/breakers/outage.rb, line 103 def end_time @body['end_time'] && Time.at(@body['end_time']).utc end
Check to see if the outage has ended
@return [Boolean] the status
# File lib/breakers/outage.rb, line 70 def ended? @body.key?('end_time') end
Was the outage forced?
@return [Boolean] the status
# File lib/breakers/outage.rb, line 77 def forced? @body['forced'] end
Get the time at which the outage last received a new request
@return [Time] the time
# File lib/breakers/outage.rb, line 110 def last_test_time (@body['last_test_time'] && Time.at(@body['last_test_time']).utc) || start_time end
Check to see if the outage should be retested to make sure it's still ongoing
@return [Boolean] is it ready?
# File lib/breakers/outage.rb, line 124 def ready_for_retest?(wait_seconds:) (Time.now.utc - last_test_time) > wait_seconds end
Get the time at which the outage started
@return [Time] the time
# File lib/breakers/outage.rb, line 96 def start_time @body['start_time'] && Time.at(@body['start_time']).utc end
Update the last test time to now
# File lib/breakers/outage.rb, line 115 def update_last_test_time! new_body = @body.dup new_body['last_test_time'] = Time.now.utc.to_i replace_body(body: new_body) end
Protected Instance Methods
# File lib/breakers/outage.rb, line 130 def key "#{Breakers.redis_prefix}#{@service.name}-outages" end
# File lib/breakers/outage.rb, line 134 def replace_body(body:) Breakers.client.redis_connection.multi do Breakers.client.redis_connection.zrem(key, MultiJson.dump(@body)) Breakers.client.redis_connection.zadd(key, start_time.to_i, MultiJson.dump(body)) end @body = body end