Skip to content

cesartalves/hiatus

Repository files navigation

Hiatus

  • noun:
    • a pause or gap in a sequence, series, or process.
    • A temporary gap, pause, break

Maintainability Test Coverage Build Status

Dead simple circuit breaker pattern implementation.

Currently this is an unambitious project for future reference and talks. Thought the pattern was interesting and wanted to give it a shot :)

--

Introduction

This pattern helps applications which deal with calls to remote services. When they're unavailable, it prevents repeated calls which may cause cascading failure.

Here is a great article about it: https://martinfowler.com/bliki/CircuitBreaker.html

Installation

Add gem 'circuit-hiatus' to your Gemfile and bundle install, or gem install circuit-hiatus

Usage

Once threshold is reached, the circuit will raise a Hiatus:CircuitBrokenError until half_open_interval passes. Then, it will half-open: a failed call trips the circuit again, a successful call closes it.

require 'hiatus' # not circuit-hiatus!

threshold = Hiatus::CountThreshold.new 5 # will be broken on the 5th failed attempt

circuit_breaker = Hiatus::CircuitBreaker.new threshold: threshold, half_open_interval: 60 # after 60 seconds, circuit is apt to make calls again

5.times do
  circuit_breaker.run do
    begin
    # Http call raising error
    rescue => e
    end
  end
end

circuit_breaker.run do
  # any call
end # => Hiatus:CircuitBrokenError

You can also include a Mixin in your class, since apparently this is what the ruby kids like. No idea why you'd like to tie your code to my little gem, but here it goes:

require 'hiatus'

class Service

include Hiatus::Mixin

# this gives you great flexiblity on which circuit to use
# you can even have your classes sharing the same circuit breaker :)
circuit_factory -> { Hiatus::Circuits::CountCircuitBreaker.new threshold: 3 }

circuit_protected def call
  raise 'Error'
end

# Check `spec/hiatus_mixin_spec.rb` for the full example

To configure a default factory:

Hiatus::Mixin.config do |c|
  c.default_circuit_factory = { Hiatus::Circuits::PercentageCircuitBreaker.new threshold: 0.5 }
end

Available Circuit types

  • Hiatus::Circuits::PercentageCircuitBreaker => shorthand for circuit with threshold= Hiatus::CountThreshold.new. Opens once requests fails enough times

  • Hiatus::Circuits::CountCircuitBreaker => shorthand for circuit with threshold= Hiatus::PercentageThreshold.new. Opens once failure percentage passes the given threshold

Advanced configuration

You can easily create new instances of Threshold, so that they can be stored anywhere (database, redis, your dog's house - anything that responds to the interface), effectively creating a circuit breaker that can be used across applications:

class RedisThreshold < CountThreshold
  def initialize(options)

  def increment
    super
    serialize
  end

  def reached?
    failure_count, threshold = *deserialize
    failure_count >= threshold
  end

  def reset
    super
    serialize
  end

  private

  def deserialize
    # get stuff from redis here
  end

  def serialize
    # put stuff into redis here
  end
end

threshold = RedisThreshold.new(url:, threshold: 15)

redis_cb = Hiatus::CircuitBreaker.new threshold: threshold, half_open_interval: 90

You can find an example of a Threshold stored in a file in extras/file_count_threshold.rb

Possible improvements

  • Figure out why travis badge says error even though the build is passing ¬ ¬'

  • Create health-check mechanism to test connection once circuit has half-opened

Contributing

PRs are welcome :)

  • PRs must be 100% test-covered
  • PRs must please my code aesthetical preferences

Development

After checking out the repo, run bundle install to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

License

The gem is available as open source under the terms of the MIT License.

Code of Conduct

Everyone interacting in the CircuitBreaker project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.

About

super simple circuit-breaker implementation

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published