Service-Jynx

Build Status

Eurasian Wryneck - Jynx torquilla

Eurasian Wryneck

Jinx - A condition or period of bad luck that appears to have been caused by a specific person or thing.

A simple solution, to allow a Ruby application to manage automatic failover and block calls to an external service and return a stubbed data when service is reported as down.

The code is MRI depended and is not thread safe(!), is is also designed specifically to run on a single VM and manage in memory hashes of data, though it can very well be executed with an external shared persistance counters such as, say, Redis.


  def index
    begin
      response = {country: "Israel"}
      if ServiceJynx.alive?("inbox")
        response = {country: HTTParty.get("https://api.github.com/users/AvnerCohen", :timeout => 20)["location"]}
      else
        response.merge!({error: "service down ! #{__method__}"})
      end
    rescue Exception => e 
      ServiceJynx.failure!("inbox")
      response.merge!({error: "exception occured, #{__method__}"})
    ensure
      render json: response and return
    end
  end

Complete Use case extracted

[1] Register the service for Jynx monitoring at application start time:

  opts = {
    time_window_in_seconds: 20,
    max_errors: 10,
    grace_period: 60
  }
  ServiceJynx.register!("github_api", opts)

[2] Define a module that wraps your HTTP calls to have a generic safe api

module HttpInternalWrapper
  extend self
    def get_api(service_name, url, &on_error_block)
      if ServiceJynx.alive?(service_name)
            HTTParty.get(url, :timeout => 20)
      else
        on_error_block.call("#{service_name}_service set as down.")
      end
    rescue Exception => e
      ServiceJynx.failure!(service_name)
      on_error_block.call("Exception in #{service_name}_service exceution - #{e.message}")
    end
end

[3] Execute with a stubbed on_error_block that gets executed on failure or service down

HttpInternalWrapper.get_api("github_api", "https://api.github.com/users/AvnerCohen") do |msg|
  @logger.error "#{msg} -- #{path} failed at #{__method__} !!"
  {error: "Github api is currently unavailable"} # stub an empty hash with error messages
end

Defaults

Defined when registering a service:

time_window_in_seconds: 10

max_errors: 40

grace_period: 360

Defaults means that 40 errors during 10 seconds would turn the service automatically off, for 5 minutes.

Methods


ServiceJynx.register!(:name, {time_window_in_seconds: 360,  max_errors: 40})
ServiceJynx.alive?(:name)
ServiceJynx.failure!(:name)
ServiceJynx.down!(:name)
ServiceJynx.up!(:name)