Circuit breakers in ruby
There are two persistence factories to choose from. In-memory storage and redis storage. To use one or the other you just need to include them:
include 'breakerbox/persistence_factories/memory'
include 'breakerbox/persistence_factories/redis'You can also create your own. Here is the memory factory as a simple example:
class PersistenceFactory
@storage = {}
def self.storage_for(name)
@storage[name] ||= BreakerBox::Storage::Memory.new
end
def self.reset!
@storage = {}
end
end
BreakerBox.persistence_factory = PersistenceFactoryThe classes that storage_for returns must conform to the persistence interface. Specifically, the classes will need these methods:
fail!: Called when a breaker task failsclear!: Clears all previous failuresall_since: Returns an array of failures that happen after a timestamplast_failure_time: returns the last time a failure occured on this breaker
Please looks in BreakerBox::MemoryStorage for an example implmentation.
To use a breaker box, call BreakerBox.circuit_for(name). This will return a breaker that can wrap a task. Call your task with the breaker box like so:
breaker = BreakerBox.circuit_for(:testing)
breaker.run SendEmailIf a task fails and you want some action, you can assign a failure callback to a breaker:
breaker = BreakerBox.circuit_for(:testing)
breaker.failure_callback = lambda { |e| Logger.alert('Email failed to send!') }
breaker.run SendEmailIf you don't provide a failure callback, any exceptions raised by the task will be rethrown.
Breakers have the following default options:
- They trip by default after two failures within two minutes
- They retry after one hour
You can change these options by passing them into the breaker:
breaker.options = {:failure_threshold_count => 10, :failure_threshold_time => 240, :retry_after => 60 * 60 * 2}Tasks are objects that do work and are passed into a breaker's run method. This object must have a .call method on it (so it could be a lambda or proc). If it fails, it should raise an exception.