class Freno::Client

Constants

REQUESTS
VERSION

Attributes

decorated_requests[R]
decorators[R]
default_app[RW]
default_store_name[RW]
default_store_type[RW]
faraday[R]
options[RW]

Public Class Methods

new(faraday) { |self| ... } click to toggle source

Creates a new instance of the client, that uses faraday to make http calls.

If most of the times you are going to ask Freno about the same app and/or storage name, you can tell the client to use some defaults, and override them as necessary.

Examples a ruby client that by default asks Freno for throttling information about `:my_app` accessing `:my_cluster` storage.

```ruby
freno = Freno::Client.new(faraday) do |client|
  client.default_store_name = :my_cluster
  client.default_app        = :my_app
end
```

Any options set on the Client are passed through to the initialization of each request:

```ruby
freno = Freno::Client.new(faraday) do |client|
  client.options = { raise_on_timeout: false }
end
```

These default options can be overridden per request. The given options
are merged into the defaults. The request below would be performed with
the options: `{ raise_on_timeout: false, low_priority: true }`

```ruby
freno = Freno::Client.new(faraday) do |client|
  client.options = { raise_on_timeout: false }
end

freno.check?(options: { low_priority: true })
```
# File lib/freno/client.rb, line 55
def initialize(faraday)
  @faraday            = faraday
  @default_store_type = :mysql
  @options            = {}
  @decorators         = {}
  @decorated_requests = {}

  yield self if block_given?
end

Public Instance Methods

check(app: default_app, store_type: default_store_type, store_name: default_store_name, options: {}) click to toggle source

Provides an interface to Freno“s check request

See github.com/github/freno/blob/master/doc/http.md#check-request

Returns Result

# File lib/freno/client.rb, line 71
def check(app: default_app, store_type: default_store_type, store_name: default_store_name, options: {})
  perform :check, app: app, store_type: store_type, store_name: store_name, options: self.options.merge(options)
end
check?(app: default_app, store_type: default_store_type, store_name: default_store_name, options: {}) click to toggle source

Determines whether Freno considers it“s OK to write to masters

Returns true or false.

# File lib/freno/client.rb, line 101
def check?(app: default_app, store_type: default_store_type, store_name: default_store_name, options: {})
  check(app: app, store_type: store_type, store_name: store_name, options: self.options.merge(options)).ok?
end
check_read(threshold:, app: default_app, store_type: default_store_type, store_name: default_store_name, options: {}) click to toggle source

Provides an interface to Freno“s check-read request

See github.com/github/freno/blob/master/doc/http.md#specialized-requests

Returns Result

# File lib/freno/client.rb, line 81
def check_read(threshold:, app: default_app, store_type: default_store_type, store_name: default_store_name, options: {})
  perform :check_read, app: app, store_type: store_type, store_name: store_name, threshold: threshold, options: self.options.merge(options)
end
check_read?(threshold:, app: default_app, store_type: default_store_type, store_name: default_store_name, options: {}) click to toggle source

Determines whether it“s OK to read from replicas as replication delay is below the given threshold.

Returns true or false.

# File lib/freno/client.rb, line 110
def check_read?(threshold:, app: default_app, store_type: default_store_type, store_name: default_store_name, options: {})
  check_read(threshold: threshold, app: app, store_type: store_type, store_name: store_name, options: self.options.merge(options)).ok?
end
decorate(request, with:) click to toggle source

Configures the client to extend the functionality of part or all the API by means of decorators.

A decorator is any object that has a `:request` accessor and can forward the execution of `perform` to it.

Examples:

The following is a decorator implementing a read-trough cache.

“`ruby class Cache

attr_accessor :request

def initialize(cache, ttl)
  @cache = cache
  @ttl = ttl
end

def perform(**kwargs)
  @cache.fetch("freno:client:v1:#{args.hash}", ttl: @ttl) do
    request.perform(kwargs)
  end
end

end “`

You can use it to decorate a single kind of request to freno:

“`ruby freno = Freno::Client.new(faraday) do |client|

client.decorate :replication_delay, with: Cache.new(App.cache, App.config.ttl)

end “`

Or every kind of request:

“`ruby freno = Freno::Client.new(faraday) do |client|

client.decorate :all, with: Cache.new(App.cache, App.config.ttl)

end “`

Additionally, decorators can be composed in multiple ways. The following client applies logging and instrumentation to all the requests, and it also applies caching, before the previous concerns, to `replication_delay` requests.

“`ruby freno = Freno::Client.new(faraday) do |client|

client.decorate :replication_delay, with: caching
client.decorate :all, with: [logging, instrumentation]

end “`

# File lib/freno/client.rb, line 168
def decorate(request, with:)
  if request == :all
    requests = REQUESTS.keys
  else
    requests = Array(request)
  end

  with = Array(with)
  validate!(with)

  requests.each do |request|
    decorators[request] ||= []
    decorators[request] += with
    decorated_requests[request] = nil
  end
end
replication_delay(app: default_app, store_type: default_store_type, store_name: default_store_name, options: {}) click to toggle source

Implements a specific check request to retrieve the consolidated replication delay

See github.com/github/freno/blob/master/doc/http.md#get-method

Returns Float indicating the replication delay in seconds as reported by Freno.

# File lib/freno/client.rb, line 92
def replication_delay(app: default_app, store_type: default_store_type, store_name: default_store_name, options: {})
  perform :replication_delay, app: app, store_type: store_type, store_name: store_name, options: self.options.merge(options)
end

Private Instance Methods

already_registered?(decorator) click to toggle source
# File lib/freno/client.rb, line 214
def already_registered?(decorator)
  registered_decorators.include? decorator
end
decorated(request) click to toggle source
# File lib/freno/client.rb, line 191
def decorated(request)
  decorated_requests[request] ||= begin
    to_decorate = Array(decorators[request]) + Array(REQUESTS[request])

    outermost = to_decorate[0]
    current = outermost

    (to_decorate[1..-1]).each do |decorator|
      current.request = decorator
      current = current.request
    end

    outermost
  end
end
perform(request, **kwargs) click to toggle source
# File lib/freno/client.rb, line 187
def perform(request, **kwargs)
  decorated(request).perform(faraday: faraday, **kwargs)
end
registered_decorators() click to toggle source
# File lib/freno/client.rb, line 218
def registered_decorators
  @registered_decorators ||= Set.new
end
validate!(decorators) click to toggle source
# File lib/freno/client.rb, line 207
def validate!(decorators)
  decorators.each do |decorator|
    raise DecorationError, "Cannot reuse decorator instance: #{decorator}" if already_registered?(decorator)
    registered_decorators << decorator
  end
end