Class: Breakers::Outage

Inherits:
Object
  • Object
show all
Defined in:
lib/breakers/outage.rb

Overview

A class defining an outage on a service

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(service:, body:) ⇒ Breakers::Outage

Create a new outage

Parameters:

  • service (Breakers::Service)

    the service the outage is for

  • body (Hash)

    the data to store in the outage, with keys start_time, end_time, last_test_time, and forced



62
63
64
65
# File 'lib/breakers/outage.rb', line 62

def initialize(service:, body:)
  @body = MultiJson.load(body)
  @service = service
end

Instance Attribute Details

#bodyObject (readonly)

Returns the value of attribute body.



7
8
9
# File 'lib/breakers/outage.rb', line 7

def body
  @body
end

#serviceObject (readonly)

Returns the value of attribute service.



6
7
8
# File 'lib/breakers/outage.rb', line 6

def service
  @service
end

Class Method Details

.create(service:, forced: false) ⇒ Breakers::Outage

Create a new outage on the given service

Parameters:

  • service (Breakers::Service)

    the service to create it for

  • forced (Boolean) (defaults to: false)

    is the service forced, or created via the middleware

Returns:



38
39
40
41
42
43
44
45
46
47
# 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

.find_latest(service:) ⇒ Breakers::Outage

Return the most recent outage on the given service

Parameters:

Returns:



13
14
15
16
# 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

.in_range(service:, start_time:, end_time:) ⇒ Breakers::Outage

Return all of the outages on the given service that begin in the time range

Parameters:

  • service (Breakers::Service)

    the service to look in

  • start_time (Time)

    the beginning of the time range

  • end_time (Time)

    the end of the time range

Returns:



24
25
26
27
28
29
30
31
# 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

.outages_key(service:) ⇒ String

Get the key for storing the outage data in Redis for this service

Parameters:

Returns:

  • (String)

    the Redis key



53
54
55
# File 'lib/breakers/outage.rb', line 53

def self.outages_key(service:)
  "#{Breakers.redis_prefix}#{service.name}-outages"
end

Instance Method Details

#end!Object

Tell the outage to end, which will allow requests to begin flowing again



82
83
84
85
86
87
88
89
90
91
# 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

#end_timeTime

Get the time at which the outage ended

Returns:

  • (Time)

    the time



103
104
105
# File 'lib/breakers/outage.rb', line 103

def end_time
  @body['end_time'] && Time.at(@body['end_time']).utc
end

#ended?Boolean

Check to see if the outage has ended

Returns:

  • (Boolean)

    the status



70
71
72
# File 'lib/breakers/outage.rb', line 70

def ended?
  @body.key?('end_time')
end

#forced?Boolean

Was the outage forced?

Returns:

  • (Boolean)

    the status



77
78
79
# File 'lib/breakers/outage.rb', line 77

def forced?
  @body['forced']
end

#last_test_timeTime

Get the time at which the outage last received a new request

Returns:

  • (Time)

    the time



110
111
112
# 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

#ready_for_retest?(wait_seconds:) ⇒ Boolean

Check to see if the outage should be retested to make sure it’s still ongoing

Returns:

  • (Boolean)

    is it ready?



124
125
126
# File 'lib/breakers/outage.rb', line 124

def ready_for_retest?(wait_seconds:)
  (Time.now.utc - last_test_time) > wait_seconds
end

#start_timeTime

Get the time at which the outage started

Returns:

  • (Time)

    the time



96
97
98
# File 'lib/breakers/outage.rb', line 96

def start_time
  @body['start_time'] && Time.at(@body['start_time']).utc
end

#update_last_test_time!Object

Update the last test time to now



115
116
117
118
119
# 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