Class: Breakers::Service

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

Overview

A service defines a backend system that your application relies upon. This class allows you to configure the outage detection for a service as well as to define which requests belong to it.

Constant Summary collapse

DEFAULT_OPTS =
{
  seconds_before_retry: 60,
  error_threshold: 50,
  data_retention_seconds: 60 * 60 * 24 * 30
}.freeze

Instance Method Summary collapse

Constructor Details

#initialize(opts) ⇒ Service

Create a new service

Parameters:

  • opts (Hash)

    the options to create the service with

Options Hash (opts):

  • :name (String)

    The name of the service for reporting and logging purposes

  • :request_matcher (Proc)

    A proc taking a Faraday::Env as an argument that returns true if the service handles that request

  • :seconds_before_retry (Integer)

    The number of seconds to wait after an outage begins before testing with a new request

  • :error_threshold (Integer)

    The percentage of errors over the last two minutes that indicates an outage

  • :data_retention_seconds (Integer)

    The number of seconds to retain success and error data in Redis



20
21
22
# File 'lib/breakers/service.rb', line 20

def initialize(opts)
  @configuration = DEFAULT_OPTS.merge(opts)
end

Instance Method Details

#add_errorObject

Indicate that an error has occurred and potentially create an outage



47
48
49
50
# File 'lib/breakers/service.rb', line 47

def add_error
  increment_key(key: errors_key)
  maybe_create_outage
end

#add_successObject

Indicate that a successful response has occurred



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

def add_success
  increment_key(key: successes_key)
end

#begin_forced_outage!Object

Force an outage to begin on the service. Forced outages are not periodically retested.



58
59
60
# File 'lib/breakers/service.rb', line 58

def begin_forced_outage!
  Outage.create(service: self, forced: true)
end

#end_forced_outage!Object

End a forced outage on the service.



63
64
65
66
67
68
# File 'lib/breakers/service.rb', line 63

def end_forced_outage!
  latest = Outage.find_latest(service: self)
  if latest.forced?
    latest.end!
  end
end

#errors_in_range(start_time:, end_time:, sample_minutes: 60) ⇒ Array[Hash]

Return data about the failed request counts in the time range

Parameters:

  • start_time (Time)

    the beginning of the range

  • end_time (Time)

    the end of the range

  • sample_minutes (Integer) (defaults to: 60)

    the rate at which to sample the data

Returns:

  • (Array[Hash])

    a list of hashes in the form: { count: Integer, time: Unix Timestamp }



104
105
106
# File 'lib/breakers/service.rb', line 104

def errors_in_range(start_time:, end_time:, sample_minutes: 60)
  values_in_range(start_time: start_time, end_time: end_time, type: :errors, sample_minutes: sample_minutes)
end

#handles_request?(request_env:) ⇒ Boolean

Given a Faraday::Env, return true if this service handles the request, via its matcher

Parameters:

  • request_env (Faraday::Env)

    the request environment

Returns:

  • (Boolean)

    should the service handle the request



35
36
37
# File 'lib/breakers/service.rb', line 35

def handles_request?(request_env:)
  @configuration[:request_matcher].call(request_env)
end

#latest_outageObject

Return the most recent outage on the service



71
72
73
# File 'lib/breakers/service.rb', line 71

def latest_outage
  Outage.find_latest(service: self)
end

#nameString

Get the name of the service

Returns:

  • (String)

    the name



27
28
29
# File 'lib/breakers/service.rb', line 27

def name
  @configuration[:name]
end

#outages_in_range(start_time:, end_time:) ⇒ Array[Outage]

Return a list of all outages in the given time range

Parameters:

  • start_time (Time)

    the beginning of the range

  • end_time (Time)

    the end of the range

Returns:

  • (Array[Outage])

    a list of outages that began in the range



80
81
82
83
84
85
86
# File 'lib/breakers/service.rb', line 80

def outages_in_range(start_time:, end_time:)
  Outage.in_range(
    service: self,
    start_time: start_time,
    end_time: end_time
  )
end

#seconds_before_retryInteger

Get the seconds before retry parameter

Returns:

  • (Integer)

    the value



42
43
44
# File 'lib/breakers/service.rb', line 42

def seconds_before_retry
  @configuration[:seconds_before_retry]
end

#successes_in_range(start_time:, end_time:, sample_minutes: 60) ⇒ Array[Hash]

Return data about the successful request counts in the time range

Parameters:

  • start_time (Time)

    the beginning of the range

  • end_time (Time)

    the end of the range

  • sample_minutes (Integer) (defaults to: 60)

    the rate at which to sample the data

Returns:

  • (Array[Hash])

    a list of hashes in the form: { count: Integer, time: Unix Timestamp }



94
95
96
# File 'lib/breakers/service.rb', line 94

def successes_in_range(start_time:, end_time:, sample_minutes: 60)
  values_in_range(start_time: start_time, end_time: end_time, type: :successes, sample_minutes: sample_minutes)
end