Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Check in gemspec plus documentation

  • Loading branch information...
commit 61281d4b213435e273239261df23201f87f9f381 1 parent 6d9150f
unknown authored
View
7 History.txt
@@ -1,6 +1,3 @@
-=== 1.0.0 / 2009-07-11
-
-* 1 major enhancement
-
- * Birthday!
+=== 1.0.0 / 2009-07-13
+* Initial release
View
9 Manifest.txt
@@ -1,8 +1,11 @@
-.autotest
History.txt
Manifest.txt
README.txt
Rakefile
-bin/circuit_breaker
+circuit_breaker.gemspec
lib/circuit_breaker.rb
-test/test_circuit_breaker.rb
+lib/circuit_breaker/circuit_state.rb
+lib/circuit_breaker/circuit_handler.rb
+lib/circuit_breaker/circuit_broken_exception.rb
+spec/unit_spec_helper.rb
+spec/unit/circuit_breaker_spec.rb
View
52 README.txt
@@ -1,26 +1,68 @@
= circuit_breaker
* http://github.com/wsargent/circuit_breaker
+ Will Sargent <will.sargent@gmail.com>
+ Copyright 2009 Will Sargent
== DESCRIPTION:
-FIX (describe your package)
+ CircuitBreaker is a relatively simple Ruby mixin that will wrap
+ a call to a given service in a circuit breaker pattern.
+
+ The circuit starts off "closed" meaning that all calls will go through.
+ However, consecutive failures are recorded and after a threshold is reached,
+ the circuit will "trip", setting the circuit into an "open" state.
+
+ In an "open" state, every call to the service will fail by raising
+ CircuitBrokenException.
+
+ The circuit will remain in an "open" state until the failure timeout has
+ elapsed.
+
+ After the failure_timeout has elapsed, the circuit will go into
+ a "half open" state and the call will go through. A failure will
+ immediately pop the circuit open again, and a success will close the
+ circuit and reset the failure count.
+
+ require 'circuit_breaker'
+ class TestService
+
+ include CircuitBreaker
+
+ def call_remote_service() ...
+
+ circuit_method :call_remote_service
+
+ # Optional
+ circuit_handler do |handler|
+ handler.logger = Logger.new(STDOUT)
+ handler.failure_threshold = 5
+ handler.failure_timeout = 5
+ end
+
+ # Optional
+ circuit_handler_class MyCustomCircuitHandler
+ end
== FEATURES/PROBLEMS:
-* FIX (list of features or problems)
+* Can run out of the box with minimal dependencies and a couple of lines of code.
+* Easy to extend: add your own circuit breakers or states or extend the existing ones.
+* Does not currently handle static class methods.
== SYNOPSIS:
- FIX (code sample of usage)
+ An implementation of Michael Nygard's Circuit Breaker pattern.
== REQUIREMENTS:
-* FIX (list of requirements)
+ circuit_breaker has a dependency on AASM (http://github.com/rubyist/aasm/tree/master).
== INSTALL:
-* FIX (sudo gem install, anything else)
+* gem sources -a http://gems.github.com
+* gem install rubyist-aasm
+* gem install wsargent_circuit-breaker
== LICENSE:
View
23 Rakefile
@@ -1,15 +1,26 @@
# -*- ruby -*-
+$:.unshift(File.dirname(__FILE__) + "/lib")
require 'rubygems'
require 'hoe'
+require 'circuit_breaker'
-$:.unshift(File.dirname(__FILE__) + "/lib")
-
-Hoe.spec 'circuit_breaker' do
+hoe = Hoe.spec 'circuit_breaker' do |p|
+ self.rubyforge_name = 'will_sargent'
developer('Will Sargent', 'will.sargent@gmail.com')
+
+ p.remote_rdoc_dir = '' # Release to root only one project
- extra_deps = [ 'rubyist-aasm' ]
- extra_dev_deps = [ 'rspec' ]
+ p.extra_deps << [ 'rubyist-aasm' ]
+ p.extra_dev_deps << [ 'rspec' ]
+ File.open(File.join(File.dirname(__FILE__), 'VERSION'), 'w') do |file|
+ file.puts CircuitBreaker::VERSION
+ end
end
-# vim: syntax=ruby
+begin
+ require 'jeweler'
+ Jeweler::Tasks.new(hoe.spec)
+rescue LoadError
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
+end
View
77 circuit_breaker.gemspec
@@ -0,0 +1,77 @@
+(in C:/Users/wsargent/work/circuit_breaker)
+# -*- encoding: utf-8 -*-
+
+Gem::Specification.new do |s|
+ s.name = %q{circuit_breaker}
+ s.version = "1.0.0"
+
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
+ s.authors = ["Will Sargent"]
+ s.date = %q{2009-07-13}
+ s.description = %q{CircuitBreaker is a relatively simple Ruby mixin that will wrap
+ a call to a given service in a circuit breaker pattern.
+
+ The circuit starts off "closed" meaning that all calls will go through.
+ However, consecutive failures are recorded and after a threshold is reached,
+ the circuit will "trip", setting the circuit into an "open" state.
+
+ In an "open" state, every call to the service will fail by raising
+ CircuitBrokenException.
+
+ The circuit will remain in an "open" state until the failure timeout has
+ elapsed.
+
+ After the failure_timeout has elapsed, the circuit will go into
+ a "half open" state and the call will go through. A failure will
+ immediately pop the circuit open again, and a success will close the
+ circuit and reset the failure count.
+
+ require 'circuit_breaker'
+ class TestService
+
+ include CircuitBreaker
+
+ def call_remote_service() ...
+
+ circuit_method :call_remote_service
+
+ # Optional
+ circuit_handler do |handler|
+ handler.logger = Logger.new(STDOUT)
+ handler.failure_threshold = 5
+ handler.failure_timeout = 5
+ end
+
+ # Optional
+ circuit_handler_class MyCustomCircuitHandler
+ end}
+ s.email = ["will.sargent@gmail.com"]
+ s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"]
+ s.files = ["History.txt", "Manifest.txt", "README.txt", "Rakefile", "circuit_breaker.gemspec", "lib/circuit_breaker.rb", "lib/circuit_breaker/circuit_state.rb", "lib/circuit_breaker/circuit_handler.rb", "lib/circuit_breaker/circuit_broken_exception.rb", "spec/unit_spec_helper.rb", "spec/unit/circuit_breaker_spec.rb"]
+ s.homepage = %q{http://github.com/wsargent/circuit_breaker}
+ s.rdoc_options = ["--main", "README.txt", "--charset=UTF-8"]
+ s.require_paths = ["lib"]
+ s.rubyforge_project = %q{will_sargent}
+ s.rubygems_version = %q{1.3.4}
+ s.summary = %q{CircuitBreaker is a relatively simple Ruby mixin that will wrap a call to a given service in a circuit breaker pattern}
+ s.test_files = ["spec/unit/circuit_breaker_spec.rb", "spec/unit_spec_helper.rb"]
+
+ if s.respond_to? :specification_version then
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
+ s.specification_version = 3
+
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
+ s.add_runtime_dependency(%q<rubyist-aasm>, [">= 0"])
+ s.add_development_dependency(%q<rspec>, [">= 1.2.7"])
+ s.add_development_dependency(%q<hoe>, [">= 2.3.1"])
+ else
+ s.add_dependency(%q<rubyist-aasm>, [">= 0"])
+ s.add_dependency(%q<rspec>, [">= 1.2.7"])
+ s.add_dependency(%q<hoe>, [">= 2.3.1"])
+ end
+ else
+ s.add_dependency(%q<rubyist-aasm>, [">= 0"])
+ s.add_dependency(%q<rspec>, [">= 1.2.7"])
+ s.add_dependency(%q<hoe>, [">= 2.3.1"])
+ end
+end
View
41 lib/circuit_breaker.rb
@@ -1,4 +1,3 @@
-
#
# CircuitBreaker is a relatively simple Ruby mixin that will wrap
# a call to a given service in a circuit breaker pattern.
@@ -14,7 +13,7 @@
# elapsed.
#
# After the failure_timeout has elapsed, the circuit will go into
-# a "half open" state and the call will go through. A failure will
+# a "half open" state and the call will go through. A failure will
# immediately pop the circuit open again, and a success will close the
# circuit and reset the failure count.
#
@@ -27,14 +26,19 @@
#
# circuit_method :call_remote_service
#
+# # Optional
# circuit_handler do |handler|
# handler.logger = Logger.new(STDOUT)
# handler.failure_threshold = 5
# handler.failure_timeout = 5
# end
+#
+# # Optional
+# circuit_handler_class MyCustomCircuitHandler
+#
# end
-
#
+# Copyright 2009 Will Sargent
# Author: Will Sargent <will.sargent@gmail.com>
# Many thanks to Devin Mullins
#
@@ -48,29 +52,48 @@ def self.included(klass)
klass.extend ::CircuitBreaker::ClassMethods
end
+ #
+ # Returns the current circuit state. This is defined on the instance, so
+ # you can have several instances of the same class with different states.
+ #
def circuit_state
@circuit_state ||= self.class.circuit_handler.new_circuit_state
end
module ClassMethods
-
- def circuit_method(meth)
+
+ #
+ # Takes a splat of method names, and wraps them with the circuit_handler.
+ #
+ def circuit_method(*methods)
circuit_handler = self.circuit_handler
- m = instance_method meth
- define_method meth do |*args|
- circuit_handler.handle self.circuit_state, m.bind(self), *args
+ methods.each do |meth|
+ m = instance_method meth
+ define_method meth do |*args|
+ circuit_handler.handle self.circuit_state, m.bind(self), *args
+ end
end
end
+ #
+ # Returns circuit_handler. Yields the instance back when passed a block.
+ #
def circuit_handler(&block)
- @circuit_handler ||= CircuitBreaker::CircuitHandler.new
+ @circuit_handler ||= circuit_handler_class.new
yield @circuit_handler if block_given?
return @circuit_handler
end
+ #
+ # Allows you to define a custom circuit_handler instead of CircuitBreaker::CircuitHandler
+ #
+ def circuit_handler_class(klass = nil)
+ @circuit_handler_class ||= (klass || CircuitBreaker::CircuitHandler)
+ end
+
end
end
View
3  lib/circuit_breaker/circuit_handler.rb
@@ -1,5 +1,3 @@
-require 'logger'
-
#
#
# CircuitHandler is stateless,
@@ -8,7 +6,6 @@
#
class CircuitBreaker::CircuitHandler
-
#
# The number of failures needed to trip the breaker.
#
Please sign in to comment.
Something went wrong with that request. Please try again.