Created
June 13, 2019 20:26
-
-
Save alex-magana/7f07fe73caddf56b60758e1f0b5b9878 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment