# Circuit Breaker
# - Circuit starts in a "closed" state.
# - Here, all calls to a given service go through
# - Consecutive failures are recorded.
# - When threshold is reached, circuit trips and the circuit gets into an "open" state.
# - In open state, calls to a given service raise CircuitBrokenException
# - Circuit remains "open" until failure timeout elapses
# - After failure timeout elapses, circuit gets into "half-open" state
# - Here, a call to aservice will go through
# - If the call fails, the circuit goes back to "open" state
# - If the call succeeds, the circuit goes back to "closed" state and failuer count is reset
# - Invocation timeout sets the amount of time to wait for a response to be returned for a given request
# https://github.com/wsargent/circuit_breaker
# http://rdoc.info/projects/wsargent/circuit_breaker
require "circuit_breaker"
require "rest-client"
require "alephant/logger"
class Client
def fetch(url)
response = request(url)
return unless response
::JSON.parse(response)
end
def request(url)
attempts ||= 3
rq ||= RestClient::Request
headers = { "Accept" => "application/json" }
rq.execute(:method => :get,
:headers => headers,
:url => url).tap do
log_fetch_success(url)
response
end
rescue RestClient::ResourceNotFound => e
log_fetch_not_found url, e
return nil
rescue RestClient::RequestFailed => e
retry unless (attempts -= 1).zero?
log_fetch_failure(url, e)
nil
end
def log_fetch_success(url)
logger.info(
"event" => "RequestSuccess",
"url" => url,
"method" => "#{self.class}#request"
)
end
def log_fetch_failure(url, e)
logger.info(
"event" => "RequestFailure",
"url" => url,
"error" => e,
"method" => "#{self.class}#request"
)
end
def log_fetch_not_found url, e
logger.info(
"event" => "ResourceNotFound",
"url" => url,
"error" => e,
"method" => "#{self.class}#request"
)
end
circuit_method :request
circuit_handler do |handler|
threshold = instance.app_config[:CIRCUIT_BREAKER_FAILURES_THRESHOLD].to_i
timeout = instance.app_config[:CIRCUIT_BREAKER_TIMEOUT].to_i
handler.logger = Alephant::Logger.get_logger
handler.failure_threshold = threshold
handler.failure_timeout = timeout
handler.invocation_timeout = 3
end
end
class Node
attr_accessor :val, :left, :right
def initialize(val, left=nil, right=nil)
@val = val
@left = left
@right = right
end
end
node = Node.new('root', Node.new('left', Node.new('left.left')), Node.new('right'))
def query_results
ActiveRecord::Base.connection.execute('SELECT name FROM accounts;').to_a
end
# @params [Array<Hash>] records
def generate_csv(records)
attributes = records.first.keys
CSV.generate(headers: true) do |csv|
csv << attributes
records.each do |record|
csv << record
end
end
end
# requires aws-sdk
def prepare_s3
Aws.config.update(
{
region: 'us-west-2',
credentials: Aws::Credentials.new(ENV['AWS_ACCESS_KEY_ID'], ENV['AWS_SECRET_ACCESS_KEY']),
}
)
end
def export(data, bucket_name, file_name)
object = Aws::S3::Resource.new.bucket(bucket_name).object(file_name)
object.put(body: data)
end